【ESP32】HFP/A2DP 共存时,iOS的兼容性问题

最近一直被 HFP 和 A2DP 的问题困扰着,不知道为什么和 Android 设备就完美链接,但是和 iOS 的测试就不那么顺畅。

当使用官方的 HFP/A2DP demo 时,使用 ESP32 初始化 HFP 服务并主动连接 iPhone 拨打电话,总是会显示对方设备断开连接的 log 。但是使用 IDF 并配合官方 单 HFP demo 就没有这个问题。

W (41925) BT_RFCOMM: port_rfc_closed RFCOMM connection in state 2 closed: Peer connection failed (res: 16)

版本使用:根据 https://github.com/espressif/esp-adf 的指示,全部使用 default 版本的 ADF 和 IDF 版本。

这个问题搞了我好久,其实并没有找到根本的问题,只是进行了一些配置项对问题进行了规避。从抓包的结果来看,是由于连接建立时,ESP32 发送 max_slot 更新,但是在 SCO 建立之前已经与 iPhone 协商了max_slot = 0x05。所以我认为,当 max_slot 为 最大数值时,并不需要去更新。因为,max_slot 代表的是最大可接受的包长,而非一定要使用的包长。 所以,我首先去掉了 max_slot 更新的操作。

 

更烦人的是,在解决了 max_slot 问题之后,sniff_req 的问题又付出了水面...当时的心情真的是,一波未平,一波又起!!!

 

那我还是从抓包进行分析,当 SCO 链接建立之后的 7s 之内,ESP32 会主动发送 sniff_req 要求进入 sniff mode,这时 iPhone 并不接受 ESP32 sniff_req 的参数,并且重新发送了 sniff_req 给 ESP32。在我的测试中,10 次 有 9 次会进入 LMP 的 Timeout,且在 timeout 情况的抓包来看,ESP32 并没有回复 iPhone 发来的 sniff_req。

从测试的现象来看,ESP32 大概率会丢掉 sniff_req 的回复动作。一方面,是我的测试环境比较复杂,RX 在刚开始建立 SCO 情况下比较忙碌,collision 的概率比较大。所以,我尝试在 SCO 链接有效期间不使能 sniff mode。因为我认为在 SCO 链接期间,电池的消耗并不是最主要矛盾,所以可以减少协议栈的行为。具体的配置方式是,在 

/esp-idf/componnets/bt/host/bluedroid/bta/bta_dm_pm_cfg.c

中 将 HS 的配置表 改成如下:

/* HS : 4 */

{

    (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */

    #if (BTM_SSR_INCLUDED == TRUE)

    (BTA_DM_PM_SSR2), /* the SSR entry */

    #endif
    {

    {{BTA_DM_PM_SNIFF, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */

    {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */

    {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */

    {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */

    {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */

    {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */

    {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */

    {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */

    {{BTA_DM_PM_RETRY, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */

}

},

然后,一切就相当的完美了...测试过程为,在 pipeline 建立之后 调用 esp_hf_client_connect(); 链接设备,并在链接建立成功后调用 esp_hf_client_dial(); 拨打电话。测试 log 如下:

I (0) cpu_start: App cpu up.
I (504) heap_init: Initializing. RAM available for dynamic allocation:
I (510) heap_init: At 3FFAFF10 len 000000F0 (0 KiB): DRAM
I (516) heap_init: At 3FFB7468 len 00000B98 (2 KiB): DRAM
I (523) heap_init: At 3FFB9A20 len 00004108 (16 KiB): DRAM
I (529) heap_init: At 3FFBDB5C len 00000004 (0 KiB): DRAM
I (535) heap_init: At 3FFD0278 len 0000FD88 (63 KiB): DRAM
I (541) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (547) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (554) heap_init: At 40093C20 len 0000C3E0 (48 KiB): IRAM
I (560) cpu_start: Pro cpu start user code
I (243) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (285) BLUETOOTH_EXAMPLE: [ 1 ] Create Bluetooth service
I (285) BTDM_INIT: BT controller compile version [345e951]
I (285) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (385) phy: phy_version: 4009, e7844c0, Jul 15 2019, 13:20:06, 0, 0
E (955) BT_BTM: btm_sco_process_num_bufs, 4
I (995) BLUETOOTH_EXAMPLE: [ 2 ] Start codec chip
I (1005) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 
I (1005) ES8388_DRIVER: init,out:02, in:00
I (1015) AUDIO_HAL: Codec mode is 3, Ctrl:1
I (1025) BLUETOOTH_EXAMPLE: [ 3 ] Create audio pipeline for playback
I (1025) BLUETOOTH_EXAMPLE: [3.1] Create i2s stream to write data to codec chip and read data from codec chip
I (1035) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=3
I (1045) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=3
I (1055) I2S: APLL: Req RATE: 44100, real rate: 44099.988, BITS: 16, CLKM: 1, BCK_M: 8, MCLK: 11289597.000, SCLK: 1411199.625000, diva: 1, divb: 0
I (1065) LYRAT_V4_2: I2S0, MCLK output by GPIO0
W (1065) I2S: I2S driver already installed
I (1075) LYRAT_V4_2: I2S0, MCLK output by GPIO0
I (1075) BLUETOOTH_EXAMPLE: [3.2] Get Bluetooth stream
I (1085) BLUETOOTH_EXAMPLE: [3.2] Register all elements to audio pipeline
I (1095) BLUETOOTH_EXAMPLE: [3.3] Link it together [Bluetooth]-->bt_stream_reader-->i2s_stream_writer-->[codec_chip]
I (1105) AUDIO_PIPELINE: link el->rb, el:0x3ffdbd9c, tag:bt, rb:0x3ffdc108
I (1115) AUDIO_PIPELINE: link el->rb, el:0x3ffdb78c, tag:i2s, rb:0x3ffde244
I (1115) BLUETOOTH_EXAMPLE: [ 4 ] Initialize peripherals
I (1125) BLUETOOTH_EXAMPLE: [4.1] Initialize Touch peripheral
I (1135) BLUETOOTH_EXAMPLE: [4.2] Create Bluetooth peripheral
I (1135) BLUETOOTH_EXAMPLE: [4.2] Start all peripherals
W (1155) PERIPH_TOUCH: _touch_init
I (1155) BLUETOOTH_EXAMPLE: [ 5 ] Set up  event listener
I (1155) BLUETOOTH_EXAMPLE: [5.1] Listening event from all elements of pipeline
I (1165) BLUETOOTH_EXAMPLE: [5.2] Listening event from peripherals
I (1175) BLUETOOTH_EXAMPLE: [ 6.1 ] Start audio_pipeline
I (1175) AUDIO_ELEMENT: [bt] Element task created
I (1195) AUDIO_ELEMENT: [i2s] Element task created
I (1195) AUDIO_PIPELINE: Func:audio_pipeline_run, Line:360, MEM Total:115044 Bytes

I (1195) AUDIO_ELEMENT: [i2s] AEL_MSG_CMD_RESUME,state:1
I (1205) I2S_STREAM: AUDIO_STREAM_WRITER
I (1205) AUDIO_PIPELINE: Pipeline started
I (1215) AUDIO_ELEMENT: [i2s] Element task created
I (1215) AUDIO_ELEMENT: [raw] Element task created
I (1235) AUDIO_PIPELINE: Func:audio_pipeline_run, Line:360, MEM Total:109044 Bytes

I (1235) AUDIO_ELEMENT: [i2s] AEL_MSG_CMD_RESUME,state:1
I (1235) I2S_STREAM: AUDIO_STREAM_READER,Rate:44100,ch:2
I (1245) I2S: APLL: Req RATE: 44100, real rate: 44099.988, BITS: 16, CLKM: 1, BCK_M: 8, MCLK: 11289597.000, SCLK: 1411199.625000, diva: 1, divb: 0
I (1255) AUDIO_PIPELINE: Pipeline started
I (1265) BLUETOOTH_EXAMPLE: [ 6.2 ] Start audio_pipeline

W (3035) BT_APPL: new conn_srvc id:27, app_id:1
E (3045) BT_HF: APP HFP event: CONNECTION_STATE_EVT
E (3045) BT_HF: --connection state connected, peer feats 0x0, chld_feats 0x0
E (3085) BT_HF: APP HFP event: NETWORK_STATE_EVT
E (3085) BT_HF: --NETWORK STATE available
E (3085) BT_HF: APP HFP event: CALL_IND_EVT
E (3085) BT_HF: --Call indicator NO call in progress
E (3095) BT_HF: APP HFP event: CALL_SETUP_IND_EVT
E (3095) BT_HF: --Call setup indicator IDLE
E (3105) BT_HF: APP HFP event: BATTERY_LEVEL_IND_EVT
E (3105) BT_HF: --battery level 3
E (3115) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (3125) BT_HF: -- signal strength: 4
E (3125) BT_HF: APP HFP event: ROAMING_STATUS_IND_EVT
E (3125) BT_HF: --ROAMING: inactive
E (3135) BT_HF: APP HFP event: CALL_HELD_IND_EVT
E (3135) BT_HF: --Call held indicator NONE held
E (3145) BT_HF: APP HFP event: CONNECTION_STATE_EVT
E (3145) BT_HF: --connection state slc_connected, peer feats 0x3ef, chld_feats 0x3f
I (3275) BLUETOOTH_EXAMPLE: [ 7 ] Listen for all pipeline events

Dial number.
E (4155) BT_HF: APP HFP event: INBAND_RING_TONE_EVT
E (4155) BT_HF: --inband ring state Provided
E (4195) BT_HF: APP HFP event: AT_RESPONSE
E (4195) BT_HF: --AT response event, code 0, cme 0
E (4245) BT_HF: APP HFP event: CALL_SETUP_IND_EVT
E (4245) BT_HF: --Call setup indicator OUTGOING_DIALING

E (4615) BT_BTM: btm_sco_connected, handle 181
E (4615) BT_HF: APP HFP event: AUDIO_STATE_EVT
E (4615) BT_HF: --audio state connected
E (4625) BT_HF: bt_app_hf_client_audio_open
I (4625) BLUETOOTH_EXAMPLE: [ * ] Receive music info from Bluetooth, sample_rates=8000, bits=16, ch=1
E (4645) BT_HF: APP HFP event: VOLUME_CONTROL_EVT
E (4645) BT_HF: --volume_target: SPEAKER, volume 2
I (4665) AUDIO_ELEMENT: [i2s] AEL_MSG_CMD_PAUSE
I (4665) I2S: PLL_D2: Req RATE: 8000, real rate: 8012.000, BITS: 16, CLKM: 78, BCK: 8, MCLK: 2048000.000, SCLK: 256384.000000, diva: 64, divb: 8
I (4665) AUDIO_ELEMENT: [i2s] AEL_MSG_CMD_RESUME,state:3
I (4675) I2S_STREAM: AUDIO_STREAM_WRITER
E (4845) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (4845) BT_HF: -- signal strength: 1
E (6845) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (6855) BT_HF: -- signal strength: 5
E (8655) BT_HF: APP HFP event: CALL_SETUP_IND_EVT
E (8655) BT_HF: --Call setup indicator OUTGOING_ALERTING
E (15275) BT_HF: APP HFP event: CALL_SETUP_IND_EVT
E (15275) BT_HF: --Call setup indicator IDLE

E (171605) BT_HF: APP HFP event: AUDIO_STATE_EVT
E (171605) BT_HF: --audio state disconnected
E (171605) BT_HF: bt_app_hf_client_audio_close
I (171615) BLUETOOTH_EXAMPLE: [ * ] Receive music info from Bluetooth, sample_rates=44100, bits=16, ch=2
E (171675) BT_HF: APP HFP event: CALL_IND_EVT
E (171675) BT_HF: --Call indicator NO call in progress
I (171995) AUDIO_ELEMENT: [i2s] AEL_MSG_CMD_PAUSE
I (171995) I2S: APLL: Req RATE: 44100, real rate: 44099.988, BITS: 16, CLKM: 1, BCK_M: 8, MCLK: 11289597.000, SCLK: 1411199.625000, diva: 1, divb: 0
I (172005) AUDIO_ELEMENT: [i2s] AEL_MSG_CMD_RESUME,state:3
I (172005) I2S_STREAM: AUDIO_STREAM_WRITER
E (172715) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (172715) BT_HF: -- signal strength: 4

E (551715) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (551715) BT_HF: -- signal strength: 5
E (1786525) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (1786525) BT_HF: -- signal strength: 4
E (2178445) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (2178445) BT_HF: -- signal strength: 5
E (2198365) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (2198365) BT_HF: -- signal strength: 4
E (2254285) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (2254285) BT_HF: -- signal strength: 3
E (2273245) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (2273245) BT_HF: -- signal strength: 4

最后说一句,兼容性问题通常都是一个比较复杂的问题,关乎到整个系统的响应策略。越是市场份额比较大的厂商的产品,有时候兼容性问题越突出,因为你的系统需要为他做出单独的处理。

避免问题当然比不上解决问题,但是也不免是一个让产品快速量产的思路...

Thanks

=====================THE END=========================

如果觉得有用,请点赞、收藏、关注、或转发给你觉得有用的人。
本帐号会不定期记录与ESP-IDF调试小技巧,或者其他功能模块介绍。

LOVE AND SHARE.  PEACE.

发布了6 篇原创文章 · 获赞 2 · 访问量 505
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章