Implement HFP client (Hands-Free Unit role) for the ESP32 test harness:
Firmware:
- bt_hfp.c/h: Full HFP client with call control, audio, volume, DTMF,
voice recognition
- Enable HFP in sdkconfig.defaults with Wide Band Speech support
- Add HFP commands/events to protocol.h and cmd_dispatcher.c
Python MCP tools:
- 15 new tools: enable, connect, audio_connect, answer, reject, dial,
send_dtmf, volume, voice_recognition_start/stop, query_calls, status
- Full protocol constants in protocol.py
Tested: HFP enable returns role='hands_free_unit', ready for AG pairing
Firmware:
- Add spp_connect, spp_disconnect, spp_data events
- Add spp_send, spp_disconnect, spp_status commands
- Track remote address for connected SPP peer
- Report received data as hex + optional text decode
Python MCP:
- esp32_spp_send(data/data_hex) - send text or binary
- esp32_spp_disconnect() - close SPP connection
- esp32_spp_status() - query connection state
Tested: Linux rfcomm connect → ESP32, bidirectional data transfer works
Two fixes for the E2E test failures:
1. event_reporter_init() was never called in app_main(), so the
FreeRTOS queue and reporter task were never created. Every BT
event (pair_request, gatt_read, gatt_write, gatt_subscribe)
was silently dropped at the NULL-queue guard.
2. SSP Numeric Comparison requires both sides to confirm, but
bt_pair blocks until completion — creating a deadlock since
the LLM can't send classic_pair_respond while waiting. Added
auto_accept flag to set_ssp_mode that auto-confirms numeric
comparison requests in the GAP callback.