mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-17 02:42:33 +00:00
hfp: audio connection: accept codec negotiatio from AG
This commit is contained in:
parent
a231942b45
commit
69de467120
32
src/hfp.c
32
src/hfp.c
@ -131,10 +131,10 @@ const char * hfp_ag_feature(int index){
|
||||
}
|
||||
|
||||
int send_str_over_rfcomm(uint16_t cid, char * command){
|
||||
// if (!rfcomm_can_send_packet_now(cid)) return 1;
|
||||
if (!rfcomm_can_send_packet_now(cid)) return 1;
|
||||
int err = rfcomm_send_internal(cid, (uint8_t*) command, strlen(command));
|
||||
if (err){
|
||||
printf("rfcomm_send_internal -> error 0X%02x", err);
|
||||
printf("rfcomm_send_internal -> error 0x%02x \n", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@ -835,7 +835,7 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){
|
||||
break;
|
||||
case HFP_CMD_SUPPORTED_FEATURES:
|
||||
context->remote_supported_features = atoi((char*)context->line_buffer);
|
||||
log_info("Parsed supported feature %d\n", context->remote_supported_features);
|
||||
printf("Parsed supported feature %d\n", context->remote_supported_features);
|
||||
break;
|
||||
case HFP_CMD_AVAILABLE_CODECS:
|
||||
printf("Parsed codec %s\n", context->line_buffer);
|
||||
@ -847,11 +847,11 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){
|
||||
if (context->retrieve_ag_indicators == 1){
|
||||
strcpy((char *)context->ag_indicators[context->parser_item_index].name, (char *)context->line_buffer);
|
||||
context->ag_indicators[context->parser_item_index].index = context->parser_item_index+1;
|
||||
log_info("Indicator %d: %s (", context->ag_indicators_nr+1, context->line_buffer);
|
||||
printf("Indicator %d: %s (", context->ag_indicators_nr+1, context->line_buffer);
|
||||
}
|
||||
|
||||
if (context->retrieve_ag_indicators_status == 1){
|
||||
log_info("Parsed Indicator %d with status: %s\n", context->parser_item_index+1, context->line_buffer);
|
||||
printf("Parsed Indicator %d with status: %s\n", context->parser_item_index+1, context->line_buffer);
|
||||
context->ag_indicators[context->parser_item_index].status = atoi((char *) context->line_buffer);
|
||||
context->parser_item_index++;
|
||||
break;
|
||||
@ -860,32 +860,32 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){
|
||||
case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE:
|
||||
context->parser_item_index++;
|
||||
if (context->parser_item_index != 4) break;
|
||||
log_info("Parsed Enable indicators: %s\n", context->line_buffer);
|
||||
printf("Parsed Enable indicators: %s\n", context->line_buffer);
|
||||
value = atoi((char *)&context->line_buffer[0]);
|
||||
context->enable_status_update_for_ag_indicators = (uint8_t) value;
|
||||
break;
|
||||
case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES:
|
||||
log_info("Parsed Support call hold: %s\n", context->line_buffer);
|
||||
printf("Parsed Support call hold: %s\n", context->line_buffer);
|
||||
if (context->line_size > 2 ) break;
|
||||
strcpy((char *)context->remote_call_services[context->remote_call_services_nr].name, (char *)context->line_buffer);
|
||||
context->remote_call_services_nr++;
|
||||
break;
|
||||
case HFP_CMD_GENERIC_STATUS_INDICATOR:
|
||||
log_info("parser HFP_CMD_GENERIC_STATUS_INDICATOR 1 (%d, %d, %d)\n",
|
||||
printf("parser HFP_CMD_GENERIC_STATUS_INDICATOR 1 (%d, %d, %d)\n",
|
||||
context->list_generic_status_indicators,
|
||||
context->retrieve_generic_status_indicators,
|
||||
context->retrieve_generic_status_indicators_state);
|
||||
if (context->retrieve_generic_status_indicators == 1 || context->list_generic_status_indicators == 1){
|
||||
log_info("Parsed Generic status indicator: %s\n", context->line_buffer);
|
||||
printf("Parsed Generic status indicator: %s\n", context->line_buffer);
|
||||
context->generic_status_indicators[context->parser_item_index].uuid = (uint16_t)atoi((char*)context->line_buffer);
|
||||
context->parser_item_index++;
|
||||
context->generic_status_indicators_nr = context->parser_item_index;
|
||||
break;
|
||||
}
|
||||
log_info("parser HFP_CMD_GENERIC_STATUS_INDICATOR 2\n");
|
||||
printf("parser HFP_CMD_GENERIC_STATUS_INDICATOR 2\n");
|
||||
if (context->retrieve_generic_status_indicators_state == 1){
|
||||
// HF parses inital AG gen. ind. state
|
||||
log_info("Parsed List generic status indicator %s state: ", context->line_buffer);
|
||||
printf("Parsed List generic status indicator %s state: ", context->line_buffer);
|
||||
context->parser_item_index = (uint8_t)atoi((char*)context->line_buffer);
|
||||
break;
|
||||
}
|
||||
@ -893,7 +893,7 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){
|
||||
|
||||
case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE:
|
||||
// AG parses new gen. ind. state
|
||||
log_info("Parsed Enable ag indicator state: %s\n", context->line_buffer);
|
||||
printf("Parsed Enable ag indicator state: %s\n", context->line_buffer);
|
||||
value = atoi((char *)&context->line_buffer[0]);
|
||||
if (!context->ag_indicators[context->parser_item_index].mandatory){
|
||||
context->ag_indicators[context->parser_item_index].enabled = value;
|
||||
@ -903,22 +903,22 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){
|
||||
case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS:
|
||||
// indicators are indexed starting with 1
|
||||
context->parser_item_index = atoi((char *)&context->line_buffer[0]) - 1;
|
||||
log_info("Parsed status of the AG indicator %d, status ", context->parser_item_index);
|
||||
printf("Parsed status of the AG indicator %d, status ", context->parser_item_index);
|
||||
break;
|
||||
case HFP_CMD_QUERY_OPERATOR_SELECTION:
|
||||
if (context->operator_name_format == 1){
|
||||
if (context->line_buffer[0] == '3'){
|
||||
log_info("Parsed Set network operator format : %s, ", context->line_buffer);
|
||||
printf("Parsed Set network operator format : %s, ", context->line_buffer);
|
||||
break;
|
||||
}
|
||||
// TODO emit ERROR, wrong format
|
||||
log_info("ERROR Set network operator format: index %s not supported\n", context->line_buffer);
|
||||
printf("ERROR Set network operator format: index %s not supported\n", context->line_buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (context->operator_name == 1) {
|
||||
context->network_operator.mode = atoi((char *)&context->line_buffer[0]);
|
||||
log_info("Parsed network operator mode: %d, ", context->network_operator.mode);
|
||||
printf("Parsed network operator mode: %d, ", context->network_operator.mode);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -397,6 +397,8 @@ void hfp_reset_context_flags(hfp_connection_t * context);
|
||||
const char * hfp_hf_feature(int index);
|
||||
const char * hfp_ag_feature(int index);
|
||||
|
||||
int send_str_over_rfcomm(uint16_t cid, char * command);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -433,7 +433,7 @@ void hfp_run_for_context(hfp_connection_t *context){
|
||||
}
|
||||
break;
|
||||
|
||||
case HFP_CMD_CONFIRM_COMMON_CODEC:
|
||||
case HFP_CMD_RECEIVED_COMMON_CODEC:
|
||||
hfp_ag_ok(context->rfcomm_cid);
|
||||
context->state = HFP_CODECS_CONNECTION_ESTABLISHED;
|
||||
break;
|
||||
@ -566,6 +566,8 @@ void hfp_run_for_context(hfp_connection_t *context){
|
||||
rfcomm_disconnect_internal(context->rfcomm_cid);
|
||||
break;
|
||||
default:
|
||||
printf("Unhandled command, send default ERROR\n");
|
||||
hfp_ag_error(context->rfcomm_cid);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
36
src/hfp_hf.c
36
src/hfp_hf.c
@ -251,7 +251,7 @@ static void hfp_emit_network_operator_event(hfp_callback_t callback, int status,
|
||||
|
||||
static void hfp_hf_run_for_context_handle_service_level_connection_establishment(hfp_connection_t * context){
|
||||
if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return;
|
||||
|
||||
printf("hfp_hf_run_for_context_handle_service_level_connection_establishment %d \n", context->state);
|
||||
switch (context->state){
|
||||
case HFP_EXCHANGE_SUPPORTED_FEATURES:
|
||||
hfp_hf_cmd_exchange_supported_features(context->rfcomm_cid);
|
||||
@ -309,7 +309,7 @@ static void hfp_hf_run_for_context_handle_service_level_connection_establishment
|
||||
|
||||
void hfp_hf_switch_on_ok_handle_service_level_connection_establishment(hfp_connection_t *context){
|
||||
if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return;
|
||||
|
||||
printf("hfp_hf_switch_on_ok_handle_service_level_connection_establishment %d\n", context->state);
|
||||
switch (context->state){
|
||||
case HFP_W4_EXCHANGE_SUPPORTED_FEATURES:
|
||||
if (has_codec_negotiation_feature(context)){
|
||||
@ -442,9 +442,12 @@ static void hfp_hf_switch_on_ok_handle_service_level_connection_queries(hfp_conn
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
static void hfp_run_for_context(hfp_connection_t * context){
|
||||
if (!context) return;
|
||||
|
||||
if (!context) return;
|
||||
if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return;
|
||||
|
||||
hfp_hf_run_for_context_handle_service_level_connection_establishment(context);
|
||||
hfp_hf_run_for_context_handle_service_level_connection_queries(context);
|
||||
|
||||
@ -468,6 +471,14 @@ static void hfp_run_for_context(hfp_connection_t * context){
|
||||
hfp_hf_cmd_trigger_codec_connection_setup(context->rfcomm_cid);
|
||||
break;
|
||||
}
|
||||
|
||||
if (context->remote_codec_received){
|
||||
context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
|
||||
context->codec_confirmed = 1;
|
||||
context->wait_ok = 1;
|
||||
hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->remote_codec_received);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HFP_SLE_W4_EXCHANGE_COMMON_CODEC:
|
||||
@ -739,6 +750,7 @@ void hfp_hf_negotiate_codecs(bd_addr_t bd_addr){
|
||||
log_error("HFP HF: connection doesn't exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
|
||||
if (!has_codec_negotiation_feature(connection)) return;
|
||||
|
||||
@ -750,27 +762,19 @@ void hfp_hf_negotiate_codecs(bd_addr_t bd_addr){
|
||||
|
||||
|
||||
void hfp_hf_establish_audio_connection(bd_addr_t bd_addr){
|
||||
hfp_hf_establish_service_level_connection(bd_addr);
|
||||
hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
|
||||
if (!connection){
|
||||
log_error("HFP HF: connection doesn't exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
connection->establish_audio_connection = 0;
|
||||
if (!has_codec_negotiation_feature(connection)) return;
|
||||
if (connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return;
|
||||
if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
|
||||
|
||||
connection->trigger_codec_connection_setup = 1;
|
||||
connection->establish_audio_connection = 1;
|
||||
|
||||
if (!has_codec_negotiation_feature(connection)){
|
||||
connection->trigger_codec_connection_setup = 0;
|
||||
connection->establish_audio_connection = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->state == HFP_CODECS_CONNECTION_ESTABLISHED){
|
||||
connection->trigger_codec_connection_setup = 0;
|
||||
return;
|
||||
if (connection->state < HFP_SLE_W4_EXCHANGE_COMMON_CODEC){
|
||||
connection->trigger_codec_connection_setup = 1;
|
||||
}
|
||||
hfp_run_for_context(connection);
|
||||
}
|
||||
|
@ -280,10 +280,6 @@ TEST_GROUP(HandsfreeClient){
|
||||
CHECK_EQUAL(codecs_connection_established, 1);
|
||||
}
|
||||
|
||||
void test_audio_connection_state_machine(){
|
||||
audio_connection_established = 0;
|
||||
hfp_hf_establish_audio_connection(device_addr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -76,7 +76,7 @@ static bd_addr_t pts_addr = {0x00,0x1b,0xDC,0x07,0x32,0xEF};
|
||||
static bd_addr_t phone_addr = {0xD8,0xBb,0x2C,0xDf,0xF1,0x08};
|
||||
|
||||
static bd_addr_t device_addr;
|
||||
static uint8_t codecs[1] = {HFP_CODEC_CVSD};
|
||||
static uint8_t codecs[] = {HFP_CODEC_CVSD, HFP_CODEC_MSBC};
|
||||
static uint16_t indicators[1] = {0x01};
|
||||
|
||||
char cmd;
|
||||
@ -119,7 +119,6 @@ static int stdin_process(struct data_source *ds){
|
||||
read(ds->fd, &cmd, 1);
|
||||
switch (cmd){
|
||||
case 'a':
|
||||
memcpy(device_addr, pts_addr, 6);
|
||||
printf("Establish Audio connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_hf_establish_audio_connection(device_addr);
|
||||
break;
|
||||
@ -128,7 +127,6 @@ static int stdin_process(struct data_source *ds){
|
||||
hfp_hf_release_audio_connection(device_addr);
|
||||
break;
|
||||
case 'h':
|
||||
memcpy(device_addr, pts_addr, 6);
|
||||
printf("Establish HFP service level connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_hf_establish_service_level_connection(device_addr);
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user