diff --git a/CHANGELOG.md b/CHANGELOG.md index 2da5d659c..7a03c8179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added CC256x: With ENABLE_CC256X_ASSISTED_HFP, HFP enables WBS codec on demand and configures PCM/I2S interface for 8kH/16kHz +BCM: With ENABLE_BCM_PCM_WBS, HFP enables WBS codec on demand and configures PCM/I2S interface for 8kH/16kHz SDP Client RFCOMM: add `sdp_client_query_rfcomm_channel_and_name_for_service_class_uuid` HFP AG/HSP AG: avoid connecting to remote service with same role diff --git a/doc/manual/docs/how_to.md b/doc/manual/docs/how_to.md index 5f9c84ba9..e9466f22e 100644 --- a/doc/manual/docs/how_to.md +++ b/doc/manual/docs/how_to.md @@ -97,6 +97,7 @@ ENABLE_CROSS_TRANSPORT_KEY_DERIVATION | Enable Cross-Transport Key Derivation (C ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE | Enable L2CAP Enhanced Retransmission Mode. Mandatory for AVRCP Browsing ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL | Enable HCI Controller to Host Flow Control, see below ENABLE_ATT_DELAYED_RESPONSE | Enable support for delayed ATT operations, see [GATT Server](profiles/#sec:GATTServerProfile) +ENABLE_BCM_PCM_WBS | Enable support for Wide-Band Speech codec in BCM controller, requires ENABLE_SCO_OVER_PCM ENABLE_CC256X_ASSISTED_HFP | Enable support for Assisted HFP mode in CC256x Controller, requires ENABLE_SCO_OVER_PCM ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CC256x Flow Control during baud rate change, see chipset docs. ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CYW2070x Flow Control during baud rate change, similar to CC256x. diff --git a/src/classic/hfp.c b/src/classic/hfp.c index 4ebcc976f..50d77a572 100644 --- a/src/classic/hfp.c +++ b/src/classic/hfp.c @@ -63,6 +63,10 @@ #error "Assisted HFP is only possible over PCM/I2S. Please add define: ENABLE_SCO_OVER_PCM" #endif +#if defined(ENABLE_BCM_PCM_WBS) && !defined(ENABLE_SCO_OVER_PCM) +#error "WBS for PCM is only possible over PCM/I2S. Please add define: ENABLE_SCO_OVER_PCM" +#endif + #define HFP_HF_FEATURES_SIZE 10 #define HFP_AG_FEATURES_SIZE 12 @@ -701,6 +705,9 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet } #ifdef ENABLE_CC256X_ASSISTED_HFP hfp_cc256x_prepare_for_sco(hfp_connection); +#endif +#ifdef ENABLE_BCM_PCM_WBS + hfp_bcm_prepare_for_sco(hfp_connection); #endif log_info("hf accept sco %u\n", hfp_connection->hf_accept_sco); sco_establishment_active = hfp_connection; @@ -793,7 +800,9 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet #ifdef ENABLE_CC256X_ASSISTED_HFP hfp_connection->cc256x_send_wbs_disassociate = true; #endif - +#ifdef ENABLE_BCM_PCM_WBS + hfp_connection->bcm_send_disable_wbs = true; +#endif hfp_connection->sco_handle = HCI_CON_HANDLE_INVALID; hfp_connection->release_audio_connection = 0; hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; @@ -1607,7 +1616,11 @@ void hfp_setup_synchronous_connection(hfp_connection_t * hfp_connection){ sco_establishment_active = hfp_connection; uint16_t sco_voice_setting = hci_get_sco_voice_setting(); if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){ - sco_voice_setting = 0x0043; // Transparent data +#ifdef ENABLE_BCM_PCM_WBS + sco_voice_setting = 0x0063; // Transparent data, 16-bit for BCM controllers +#else + sco_voice_setting = 0x0043; // Transparent data, 8-bit otherwise +#endif } // get packet types - bits 6-9 are 'don't allow' uint16_t packet_types = hfp_link_settings[setting].packet_types ^ 0x03c0; @@ -1650,6 +1663,20 @@ void hfp_cc256x_write_codec_config(hfp_connection_t * hfp_connection){ } #endif +#ifdef ENABLE_BCM_PCM_WBS +void hfp_bcm_prepare_for_sco(hfp_connection_t * hfp_connection){ + hfp_connection->bcm_send_write_i2spcm_interface_param = true; + if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){ + hfp_connection->bcm_send_enable_wbs = true; + } +} +void hfp_bcm_write_i2spcm_interface_param(hfp_connection_t * hfp_connection){ + uint8_t sample_rate = (hfp_connection->negotiated_codec == HFP_CODEC_MSBC) ? 1 : 0; + // i2s enable, master, 8/16 kHz, 2048 kHz + hci_send_cmd(&hci_bcm_write_i2spcm_interface_param, 1, 1, sample_rate, 4); +} +#endif + void hfp_set_hf_callback(btstack_packet_handler_t callback){ hfp_hf_callback = callback; } diff --git a/src/classic/hfp.h b/src/classic/hfp.h index efd244c91..09b4aa1be 100644 --- a/src/classic/hfp.h +++ b/src/classic/hfp.h @@ -648,7 +648,11 @@ typedef struct hfp_connection { bool cc256x_send_wbs_associate; bool cc256x_send_wbs_disassociate; #endif - +#ifdef ENABLE_BCM_PCM_WBS + bool bcm_send_enable_wbs; + bool bcm_send_disable_wbs; + bool bcm_send_write_i2spcm_interface_param; +#endif } hfp_connection_t; // UTILS_START : TODO move to utils @@ -711,6 +715,10 @@ const char * hfp_enhanced_call_mpty2str(uint16_t index); void hfp_cc256x_prepare_for_sco(hfp_connection_t * hfp_connection); void hfp_cc256x_write_codec_config(hfp_connection_t * hfp_connection); #endif +#ifdef ENABLE_BCM_PCM_WBS +void hfp_bcm_prepare_for_sco(hfp_connection_t * hfp_connection); +void hfp_bcm_write_i2spcm_interface_param (hfp_connection_t * hfp_connection); +#endif /** * @brief Set packet types for SCO connections diff --git a/src/classic/hfp_ag.c b/src/classic/hfp_ag.c index c9ff55eb6..b765a71f0 100644 --- a/src/classic/hfp_ag.c +++ b/src/classic/hfp_ag.c @@ -1737,6 +1737,26 @@ static void hfp_ag_run_for_context(hfp_connection_t *hfp_connection){ return; } #endif +#ifdef ENABLE_BCM_PCM_WBS + // Enable WBS + if (hfp_connection->bcm_send_enable_wbs){ + hfp_connection->bcm_send_enable_wbs = false; + hci_send_cmd(&hci_bcm_enable_wbs, 1, 2); + return; + } + // Write I2S/PCM params + if (hfp_connection->bcm_send_write_i2spcm_interface_param){ + hfp_connection->bcm_send_write_i2spcm_interface_param = false; + hfp_bcm_write_i2spcm_interface_param(hfp_connection); + return; + } + // Disable WBS + if (hfp_connection->bcm_send_disable_wbs){ + hfp_connection->bcm_send_disable_wbs = false; + hci_send_cmd(&hci_bcm_enable_wbs, 0, 2); + return; + } +#endif if (!rfcomm_can_send_packet_now(hfp_connection->rfcomm_cid)) { log_info("hfp_ag_run_for_context: request can send for 0x%02x", hfp_connection->rfcomm_cid); diff --git a/src/classic/hfp_hf.c b/src/classic/hfp_hf.c index ed821594d..c2c5aed44 100644 --- a/src/classic/hfp_hf.c +++ b/src/classic/hfp_hf.c @@ -567,6 +567,26 @@ static void hfp_hf_run_for_context(hfp_connection_t * hfp_connection){ return; } #endif +#ifdef ENABLE_BCM_PCM_WBS + // Enable WBS + if (hfp_connection->bcm_send_enable_wbs){ + hfp_connection->bcm_send_enable_wbs = false; + hci_send_cmd(&hci_bcm_enable_wbs, 1, 2); + return; + } + // Write I2S/PCM params + if (hfp_connection->bcm_send_write_i2spcm_interface_param){ + hfp_connection->bcm_send_write_i2spcm_interface_param = false; + hfp_bcm_write_i2spcm_interface_param(hfp_connection); + return; + } + // Disable WBS + if (hfp_connection->bcm_send_disable_wbs){ + hfp_connection->bcm_send_disable_wbs = false; + hci_send_cmd(&hci_bcm_enable_wbs, 0, 2); + return; + } +#endif if (hfp_connection->hf_accept_sco){ @@ -599,7 +619,11 @@ static void hfp_hf_run_for_context(hfp_connection_t * hfp_connection){ // mSBC only allows for transparent data uint16_t sco_voice_setting = hci_get_sco_voice_setting(); if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){ - sco_voice_setting = 0x0043; // Transparent data +#ifdef ENABLE_BCM_PCM_WBS + sco_voice_setting = 0x0063; // Transparent data, 16-bit for BCM controllers +#else + sco_voice_setting = 0x0043; // Transparent data, 8-bit otherwise +#endif } // filter packet types