mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-23 10:21:12 +00:00
hfp_hf: send codec_event(CVSD) if no codec negotation happens. hfp_ag: use T2/T1 connection settings. only accept SCO connections in hfp_hf
This commit is contained in:
parent
d6ff09e13f
commit
7522e673fc
@ -318,7 +318,7 @@ void hfp_reset_context_flags(hfp_connection_t * hfp_connection){
|
||||
|
||||
// establish codecs hfp_connection
|
||||
hfp_connection->suggested_codec = 0;
|
||||
hfp_connection->negotiated_codec = HFP_CODEC_CVSD;
|
||||
hfp_connection->negotiated_codec = 0;
|
||||
hfp_connection->codec_confirmed = 0;
|
||||
|
||||
hfp_connection->establish_audio_connection = 0;
|
||||
@ -495,14 +495,22 @@ static void hfp_handle_failed_sco_connection(uint8_t status){
|
||||
sco_establishment_active->link_setting = HFP_LINK_SETTINGS_D1;
|
||||
break;
|
||||
case HFP_LINK_SETTINGS_S2:
|
||||
case HFP_LINK_SETTINGS_S3:
|
||||
case HFP_LINK_SETTINGS_S4:
|
||||
sco_establishment_active->link_setting = HFP_LINK_SETTINGS_S1;
|
||||
break;
|
||||
case HFP_LINK_SETTINGS_T1:
|
||||
case HFP_LINK_SETTINGS_T2:
|
||||
case HFP_LINK_SETTINGS_S3:
|
||||
sco_establishment_active->link_setting = HFP_LINK_SETTINGS_S2;
|
||||
break;
|
||||
case HFP_LINK_SETTINGS_S4:
|
||||
sco_establishment_active->link_setting = HFP_LINK_SETTINGS_S3;
|
||||
break;
|
||||
case HFP_LINK_SETTINGS_T1:
|
||||
log_info("T1 failed, fallback to CVSD - D1");
|
||||
sco_establishment_active->negotiated_codec = HFP_CODEC_CVSD;
|
||||
sco_establishment_active->link_setting = HFP_LINK_SETTINGS_D1;
|
||||
break;
|
||||
case HFP_LINK_SETTINGS_T2:
|
||||
sco_establishment_active->link_setting = HFP_LINK_SETTINGS_T1;
|
||||
break;
|
||||
}
|
||||
sco_establishment_active->establish_audio_connection = 1;
|
||||
sco_establishment_active = 0;
|
||||
@ -520,12 +528,16 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
case HCI_EVENT_CONNECTION_REQUEST:
|
||||
// printf("hfp HCI_EVENT_CONNECTION_REQUEST\n");
|
||||
|
||||
hci_event_connection_request_get_bd_addr(packet, event_addr);
|
||||
hfp_connection = provide_hfp_connection_context_for_bd_addr(event_addr);
|
||||
|
||||
if (!hfp_connection) break;
|
||||
hfp_connection->ag_establish_SCO = 1;
|
||||
switch(hci_event_connection_request_get_link_type(packet)){
|
||||
case 0: // SCO
|
||||
case 2: // eSCO
|
||||
hci_event_connection_request_get_bd_addr(packet, event_addr);
|
||||
hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr);
|
||||
if (!hfp_connection) break;
|
||||
hfp_connection->ag_establish_SCO = 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case RFCOMM_EVENT_INCOMING_CONNECTION:
|
||||
@ -1400,7 +1412,7 @@ 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 = 0x0003; // Transparent data
|
||||
sco_voice_setting = 0x0043; // Transparent data
|
||||
}
|
||||
hci_send_cmd(&hci_setup_synchronous_connection, hfp_connection->acl_handle, 8000, 8000, hfp_link_settings[setting].max_latency,
|
||||
sco_voice_setting, hfp_link_settings[setting].retransmission_effort, hfp_link_settings[setting].packet_types); // all types 0x003f, only 2-ev3 0x380
|
||||
|
@ -536,6 +536,29 @@ static uint8_t hfp_ag_suggest_codec(hfp_connection_t *hfp_connection){
|
||||
return HFP_CODEC_CVSD;
|
||||
}
|
||||
|
||||
static void hfp_init_link_settings(hfp_connection_t * hfp_connection){
|
||||
// determine highest possible link setting
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_D1;
|
||||
switch (hfp_connection->negotiated_codec){
|
||||
default:
|
||||
case HFP_CODEC_CVSD:
|
||||
if (hci_remote_esco_supported(hfp_connection->acl_handle)){
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_S3;
|
||||
if ((hfp_connection->remote_supported_features & (1<<HFP_HFSF_ESCO_S4))
|
||||
&& (hfp_supported_features & (1<<HFP_AGSF_ESCO_S4))){
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_S4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HFP_CODEC_MSBC:
|
||||
if (hci_remote_esco_supported(hfp_connection->acl_handle)){
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_T2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
log_info("hfp_init_link_settings: %u", hfp_connection->link_setting);
|
||||
}
|
||||
|
||||
static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){
|
||||
/* events ( == commands):
|
||||
HFP_CMD_AVAILABLE_CODECS == received AT+BAC with list of codecs
|
||||
@ -599,6 +622,8 @@ 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_emit_codec_event(hfp_callback, 0, hfp_connection->negotiated_codec);
|
||||
hfp_ag_ok(hfp_connection->rfcomm_cid);
|
||||
// now, pick link settings
|
||||
hfp_init_link_settings(hfp_connection);
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
@ -606,24 +631,10 @@ static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hfp_init_link_settings(hfp_connection_t * hfp_connection){
|
||||
// determine highest possible link setting
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_D1;
|
||||
if (hci_remote_esco_supported(hfp_connection->acl_handle)){
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_S3;
|
||||
if ((hfp_connection->remote_supported_features & (1<<HFP_HFSF_ESCO_S4))
|
||||
&& (hfp_supported_features & (1<<HFP_AGSF_ESCO_S4))){
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_S4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void hfp_ag_slc_established(hfp_connection_t * hfp_connection){
|
||||
hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
|
||||
hfp_emit_connection_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0, hfp_connection->acl_handle, hfp_connection->remote_addr);
|
||||
|
||||
hfp_init_link_settings(hfp_connection);
|
||||
|
||||
// if active call exist, set per-hfp_connection state active, too (when audio is on)
|
||||
if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
|
||||
hfp_connection->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE;
|
||||
@ -1626,34 +1637,6 @@ static void hfp_run_for_context(hfp_connection_t *hfp_connection){
|
||||
|
||||
if (!hfp_connection->rfcomm_cid) return;
|
||||
|
||||
if (hfp_connection->ag_establish_SCO && hci_can_send_command_packet_now()){
|
||||
// remote supported feature eSCO is set if link type is eSCO
|
||||
// eSCO: S4 - max latency == transmission interval = 0x000c == 12 ms,
|
||||
uint16_t max_latency;
|
||||
uint8_t retransmission_effort;
|
||||
uint16_t packet_types;
|
||||
|
||||
if (hci_remote_esco_supported(hfp_connection->acl_handle)){
|
||||
max_latency = 0x000c;
|
||||
retransmission_effort = 0x02;
|
||||
packet_types = 0x388;
|
||||
} else {
|
||||
max_latency = 0xffff;
|
||||
retransmission_effort = 0xff;
|
||||
packet_types = 0x003f;
|
||||
}
|
||||
|
||||
uint16_t sco_voice_setting = hci_get_sco_voice_setting();
|
||||
if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){
|
||||
sco_voice_setting = 0x0003; // Transparent data
|
||||
}
|
||||
|
||||
log_info("HFP: sending hci_accept_connection_request, sco_voice_setting %02x", sco_voice_setting);
|
||||
hci_send_cmd(&hci_accept_synchronous_connection, hfp_connection->remote_addr, 8000, 8000, max_latency,
|
||||
sco_voice_setting, retransmission_effort, packet_types);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rfcomm_can_send_packet_now(hfp_connection->rfcomm_cid)) {
|
||||
log_info("hfp_run_for_context: request can send for 0x%02x", hfp_connection->rfcomm_cid);
|
||||
rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid);
|
||||
@ -2134,6 +2117,8 @@ static void hfp_ag_setup_audio_connection(hfp_connection_t * hfp_connection){
|
||||
hfp_connection->negotiated_codec = HFP_CODEC_CVSD;
|
||||
hfp_connection->codecs_state = HFP_CODECS_EXCHANGED;
|
||||
hfp_emit_codec_event(hfp_callback, 0, hfp_connection->negotiated_codec);
|
||||
// now, pick link settings
|
||||
hfp_init_link_settings(hfp_connection);
|
||||
}
|
||||
|
||||
switch (hfp_connection->codecs_state){
|
||||
|
@ -588,6 +588,42 @@ static int call_setup_state_machine(hfp_connection_t * hfp_connection){
|
||||
static void hfp_run_for_context(hfp_connection_t * hfp_connection){
|
||||
if (!hfp_connection) return;
|
||||
if (!hfp_connection->rfcomm_cid) return;
|
||||
|
||||
if (hfp_connection->ag_establish_SCO && hci_can_send_command_packet_now()){
|
||||
|
||||
// notify about codec selection if not done already
|
||||
if (hfp_connection->negotiated_codec == 0){
|
||||
hfp_connection->negotiated_codec = HFP_CODEC_CVSD;
|
||||
hfp_emit_codec_event(hfp_callback, 0, hfp_connection->negotiated_codec);
|
||||
}
|
||||
|
||||
// remote supported feature eSCO is set if link type is eSCO
|
||||
// eSCO: S4 - max latency == transmission interval = 0x000c == 12 ms,
|
||||
uint16_t max_latency;
|
||||
uint8_t retransmission_effort;
|
||||
uint16_t packet_types;
|
||||
|
||||
if (hci_remote_esco_supported(hfp_connection->acl_handle)){
|
||||
max_latency = 0x000c;
|
||||
retransmission_effort = 0x02;
|
||||
packet_types = 0x388;
|
||||
} else {
|
||||
max_latency = 0xffff;
|
||||
retransmission_effort = 0xff;
|
||||
packet_types = 0x003f;
|
||||
}
|
||||
|
||||
uint16_t sco_voice_setting = hci_get_sco_voice_setting();
|
||||
if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){
|
||||
sco_voice_setting = 0x0043; // Transparent data
|
||||
}
|
||||
|
||||
log_info("HFP: sending hci_accept_connection_request, sco_voice_setting %02x", sco_voice_setting);
|
||||
hci_send_cmd(&hci_accept_synchronous_connection, hfp_connection->remote_addr, 8000, 8000, max_latency,
|
||||
sco_voice_setting, retransmission_effort, packet_types);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rfcomm_can_send_packet_now(hfp_connection->rfcomm_cid)) return;
|
||||
|
||||
int done = hfp_hf_run_for_context_service_level_connection(hfp_connection);
|
||||
@ -824,23 +860,11 @@ static void hfp_run_for_context(hfp_connection_t * hfp_connection){
|
||||
}
|
||||
}
|
||||
|
||||
static void hfp_init_link_settings(hfp_connection_t * hfp_connection){
|
||||
// determine highest possible link setting
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_D1;
|
||||
if (hci_remote_esco_supported(hfp_connection->acl_handle)){
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_S3;
|
||||
if ((hfp_supported_features & (1<<HFP_HFSF_ESCO_S4))
|
||||
&& (hfp_connection->remote_supported_features & (1<<HFP_AGSF_ESCO_S4))){
|
||||
hfp_connection->link_setting = HFP_LINK_SETTINGS_S4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void hfp_ag_slc_established(hfp_connection_t * hfp_connection){
|
||||
hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
|
||||
|
||||
hfp_emit_connection_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0, hfp_connection->acl_handle, hfp_connection->remote_addr);
|
||||
hfp_init_link_settings(hfp_connection);
|
||||
|
||||
// restore volume settings
|
||||
hfp_connection->speaker_gain = hfp_hf_speaker_gain;
|
||||
hfp_connection->send_speaker_gain = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user