hfp: support CC256x assisted hfp

This commit is contained in:
Matthias Ringwald 2020-11-19 21:54:37 +01:00
parent 49ed206d42
commit 3721a23546
6 changed files with 121 additions and 7 deletions

View File

@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
---
## Unreleased
### Added
CC256x: With ENABLE_CC256X_ASSISTED_HFP, HFP enables WBS codec on demand and configures PCM/I2S interface for 8kH/16kHz
## Release v1.2.1
### Fixed

View File

@ -81,6 +81,7 @@ ENABLE_LOG_DEBUG | Enable log_debug messages
ENABLE_LOG_ERROR | Enable log_error messages
ENABLE_LOG_INFO | Enable log_info messages
ENABLE_SCO_OVER_HCI | Enable SCO over HCI for chipsets (if supported)
ENABLE_SCO_OVER_PCM | Enable SCO ofer PCM/I2S for chipsets (if supported)
ENABLE_HFP_WIDE_BAND_SPEECH | Enable support for mSBC codec used in HFP profile for Wide-Band Speech
ENBALE_LE_PERIPHERAL | Enable support for LE Peripheral Role in HCI and Security Manager
ENBALE_LE_CENTRAL | Enable support for LE Central Role in HCI and Security Manager
@ -96,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_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.
ENABLE_LE_LIMIT_ACL_FRAGMENT_BY_MAX_OCTETS | Force HCI to fragment ACL-LE packets to fit into over-the-air packet

View File

@ -59,6 +59,10 @@
#include "hci_dump.h"
#include "l2cap.h"
#if defined(ENABLE_CC256X_ASSISTED_HFP) && !defined(ENABLE_SCO_OVER_PCM)
#error "Assisted HFP 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
@ -690,6 +694,9 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
} else {
hfp_connection->hf_accept_sco = 1;
}
#ifdef ENABLE_CC256X_ASSISTED_HFP
hfp_cc256x_prepare_for_sco(hfp_connection);
#endif
log_info("hf accept sco %u\n", hfp_connection->hf_accept_sco);
sco_establishment_active = hfp_connection;
break;
@ -778,6 +785,10 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
if (!hfp_connection) break;
#ifdef ENABLE_CC256X_ASSISTED_HFP
hfp_connection->cc256x_send_wbs_disassociate = true;
#endif
hfp_connection->sco_handle = HCI_CON_HANDLE_INVALID;
hfp_connection->release_audio_connection = 0;
hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
@ -795,6 +806,7 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
}
}
void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role){
UNUSED(packet_type);
UNUSED(channel); // ok: no channel
@ -1598,6 +1610,41 @@ void hfp_setup_synchronous_connection(hfp_connection_t * hfp_connection){
sco_voice_setting, hfp_link_settings[setting].retransmission_effort, packet_types);
}
#ifdef ENABLE_CC256X_ASSISTED_HFP
void hfp_cc256x_prepare_for_sco(hfp_connection_t * hfp_connection){
hfp_connection->cc256x_send_write_codec_config = true;
if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){
hfp_connection->cc256x_send_wbs_associate = true;
}
}
void hfp_cc256x_write_codec_config(hfp_connection_t * hfp_connection){
uint32_t sample_rate_hz;
uint16_t clock_rate_khz;
if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){
clock_rate_khz = 512;
sample_rate_hz = 16000;
} else {
clock_rate_khz = 256;
sample_rate_hz = 8000;
}
uint8_t clock_direction = 0; // master
uint16_t frame_sync_duty_cycle = 0; // i2s with 50%
uint8_t frame_sync_edge = 1; // rising edge
uint8_t frame_sync_polarity = 0; // active high
uint8_t reserved = 0;
uint16_t size = 16;
uint16_t chan_1_offset = 1;
uint16_t chan_2_offset = chan_1_offset + size;
uint8_t out_edge = 1; // rising
uint8_t in_edge = 0; // falling
hci_send_cmd(&hci_ti_write_codec_config, clock_rate_khz, clock_direction, sample_rate_hz, frame_sync_duty_cycle,
frame_sync_edge, frame_sync_polarity, reserved,
size, chan_1_offset, out_edge, size, chan_1_offset, in_edge, reserved,
size, chan_2_offset, out_edge, size, chan_2_offset, in_edge, reserved);
}
#endif
void hfp_set_hf_callback(btstack_packet_handler_t callback){
hfp_hf_callback = callback;
}

View File

@ -643,6 +643,12 @@ typedef struct hfp_connection {
uint8_t bnip_type; // 0 == not set
char bnip_number[25]; //
#ifdef ENABLE_CC256X_ASSISTED_HFP
bool cc256x_send_write_codec_config;
bool cc256x_send_wbs_associate;
bool cc256x_send_wbs_disassociate;
#endif
} hfp_connection_t;
// UTILS_START : TODO move to utils
@ -701,6 +707,11 @@ const char * hfp_enhanced_call_status2str(uint16_t index);
const char * hfp_enhanced_call_mode2str(uint16_t index);
const char * hfp_enhanced_call_mpty2str(uint16_t index);
#ifdef ENABLE_CC256X_ASSISTED_HFP
void hfp_cc256x_prepare_for_sco(hfp_connection_t * hfp_connection);
void hfp_cc256x_write_codec_config(hfp_connection_t * hfp_connection);
#endif
/**
* @brief Set packet types for SCO connections
* @param common single packet_types: HFP_SCO_PACKET_TYPES_*

View File

@ -555,9 +555,11 @@ static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){
log_info("hfp: codec confirmed: %s", (hfp_connection->negotiated_codec == HFP_CODEC_MSBC) ? "mSBC" : "CVSD");
hfp_ag_send_ok(hfp_connection->rfcomm_cid);
// now, pick link settings
hfp_init_link_settings(hfp_connection, hfp_ag_esco_s4_supported(hfp_connection));
return 1;
#ifdef ENABLE_CC256X_ASSISTED_HFP
hfp_cc256x_prepare_for_sco(hfp_connection);
#endif
return 1;
default:
break;
}
@ -1712,6 +1714,30 @@ static void hfp_ag_run_for_context(hfp_connection_t *hfp_connection){
// during SDP query, RFCOMM CID is not set
if (hfp_connection->rfcomm_cid == 0) return;
// assert command could be sent
if (hci_can_send_command_packet_now() == 0) return;
#ifdef ENABLE_CC256X_ASSISTED_HFP
// WBS Disassociate
if (hfp_connection->cc256x_send_wbs_disassociate){
hfp_connection->cc256x_send_wbs_disassociate = false;
hci_send_cmd(&hci_ti_wbs_disassociate);
return;
}
// Write Codec Config
if (hfp_connection->cc256x_send_write_codec_config){
hfp_connection->cc256x_send_write_codec_config = false;
hfp_cc256x_write_codec_config(hfp_connection);
return;
}
// WBS Associate
if (hfp_connection->cc256x_send_wbs_associate){
hfp_connection->cc256x_send_wbs_associate = false;
hci_send_cmd(&hci_ti_wbs_associate, hfp_connection->acl_handle);
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);
rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid);
@ -2013,10 +2039,6 @@ static void hfp_ag_rfcomm_packet_handler(uint8_t packet_type, uint16_t channel,
static void hfp_ag_hci_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
hfp_handle_hci_event(packet_type, channel, packet, size, HFP_ROLE_AG);
// allow for sco established -> ring transition
if (packet_type != HCI_EVENT_PACKET) return;
if (hci_event_packet_get_type(packet) != HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE) return;
hfp_ag_run();
}
@ -2115,6 +2137,9 @@ static void hfp_ag_setup_audio_connection(hfp_connection_t * hfp_connection){
hfp_connection->codecs_state = HFP_CODECS_EXCHANGED;
// now, pick link settings
hfp_init_link_settings(hfp_connection, hfp_ag_esco_s4_supported(hfp_connection));
#ifdef ENABLE_CC256X_ASSISTED_HFP
hfp_cc256x_prepare_for_sco(hfp_connection);
#endif
return;
}

View File

@ -544,7 +544,31 @@ static void hfp_hf_run_for_context(hfp_connection_t * hfp_connection){
// during SDP query, RFCOMM CID is not set
if (hfp_connection->rfcomm_cid == 0) return;
if (hfp_connection->hf_accept_sco && hci_can_send_command_packet_now()){
// assert command could be sent
if (hci_can_send_command_packet_now() == 0) return;
#ifdef ENABLE_CC256X_ASSISTED_HFP
// WBS Disassociate
if (hfp_connection->cc256x_send_wbs_disassociate){
hfp_connection->cc256x_send_wbs_disassociate = false;
hci_send_cmd(&hci_ti_wbs_disassociate);
return;
}
// Write Codec Config
if (hfp_connection->cc256x_send_write_codec_config){
hfp_connection->cc256x_send_write_codec_config = false;
hfp_cc256x_write_codec_config(hfp_connection);
return;
}
// WBS Associate
if (hfp_connection->cc256x_send_wbs_associate){
hfp_connection->cc256x_send_wbs_associate = false;
hci_send_cmd(&hci_ti_wbs_associate, hfp_connection->acl_handle);
return;
}
#endif
if (hfp_connection->hf_accept_sco){
bool eSCO = hfp_connection->hf_accept_sco == 2;
hfp_connection->hf_accept_sco = 0;