【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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章