rewrite hfp hs codecs sm

This commit is contained in:
Milanka Ringwald 2015-11-18 12:32:57 +01:00
parent 22c9a32a8c
commit ae245cdf0a
5 changed files with 58 additions and 167 deletions

View File

@ -279,12 +279,7 @@ void hfp_reset_context_flags(hfp_connection_t * context){
context->enable_extended_audio_gateway_error_report = 0;
context->extended_audio_gateway_error = 0;
// can come any time (here taken into account only after SLE),
// if codec negotiation feature is set
context->notify_ag_on_new_codecs = 0;
// establish codecs connection
context->hf_trigger_codec_connection_setup = 0;
context->suggested_codec = 0;
context->negotiated_codec = 0;
context->codec_confirmed = 0;
@ -669,7 +664,6 @@ static void process_command(hfp_connection_t * context){
if (strncmp((char *)context->line_buffer+offset, HFP_AVAILABLE_CODECS, strlen(HFP_AVAILABLE_CODECS)) == 0){
context->command = HFP_CMD_AVAILABLE_CODECS;
context->notify_ag_on_new_codecs = 1;
return;
}
@ -739,8 +733,6 @@ static void process_command(hfp_connection_t * context){
if (strncmp((char *)context->line_buffer+offset, HFP_TRIGGER_CODEC_CONNECTION_SETUP, strlen(HFP_TRIGGER_CODEC_CONNECTION_SETUP)) == 0){
context->command = HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP;
// printf("HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP update command\n");
context->hf_trigger_codec_connection_setup = 1;
return;
}

View File

@ -242,27 +242,22 @@ typedef enum {
HFP_RETRIEVE_GENERIC_STATUS_INDICATORS,
HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS,
HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS, // 20
HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS,
HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS,
HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED, // 22
HFP_SLE_W2_EXCHANGE_COMMON_CODEC,
HFP_SLE_W4_EXCHANGE_COMMON_CODEC,
HFP_CODECS_CONNECTION_ESTABLISHED, // 25
HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED,
HFP_W2_CONNECT_SCO,
HFP_W4_SCO_CONNECTED,
HFP_AUDIO_CONNECTION_ESTABLISHED,
HFP_AUDIO_CONNECTION_ESTABLISHED,
HFP_W2_DISCONNECT_SCO,
HFP_W4_SCO_DISCONNECTED, // 30
HFP_W4_SCO_DISCONNECTED,
HFP_W2_DISCONNECT_RFCOMM,
HFP_W4_RFCOMM_DISCONNECTED,
HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART,
HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART,
HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN
} hfp_state_t;
@ -270,6 +265,7 @@ typedef enum {
HFP_CODECS_IDLE,
HFP_CODECS_RECEIVED_LIST,
HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE,
HFP_CODECS_W4_AG_COMMON_CODEC,
HFP_CODECS_AG_SENT_COMMON_CODEC,
HFP_CODECS_AG_RESEND_COMMON_CODEC,
HFP_CODECS_EXCHANGED,
@ -395,12 +391,7 @@ typedef struct hfp_connection {
uint8_t enable_extended_audio_gateway_error_report;
uint8_t extended_audio_gateway_error;
// can come any time (here taken into account only after SLE),
// if codec negotiation feature is set
uint8_t notify_ag_on_new_codecs;
// establish codecs connection
uint8_t hf_trigger_codec_connection_setup;
uint8_t suggested_codec;
uint8_t codec_confirmed;

View File

@ -184,10 +184,6 @@ static int hfp_ag_report_extended_audio_gateway_error(uint16_t cid, uint8_t erro
return send_str_over_rfcomm(cid, buffer);
}
static int hfp_ag_retrieve_codec_cmd(uint16_t cid){
return hfp_ag_ok(cid);
}
static int hfp_ag_indicators_join(char * buffer, int buffer_size, hfp_connection_t * context){
if (buffer_size < get_hfp_ag_indicators_nr(context) * (1 + sizeof(hfp_ag_indicator_t))) return 0;
int i;

View File

@ -461,154 +461,81 @@ static void hfp_hf_handle_ok_service_level_connection_queries(hfp_connection_t *
}
}
static int hfp_hf_run_for_context_codecs_connection(hfp_connection_t * context){
if (context->state <= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED ||
context->state > HFP_CODECS_CONNECTION_ESTABLISHED) return 0;
static int codecs_exchange_state_machine(hfp_connection_t * context){
if (context->wait_ok) return 0;
int done = 0;
// handle audio connection setup
// printf("hfp_run_for_context state %d \n", context->state);
if (context->wait_ok) return done;
switch (context->state){
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
if (context->notify_ag_on_new_codecs){
context->wait_ok = 1;
hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
done = 1;
break;
switch(context->command){
case HFP_CMD_AVAILABLE_CODECS:
switch (context->codecs_state){
case HFP_CODECS_W4_AG_COMMON_CODEC:
context->codec_confirmed = 0;
context->suggested_codec = 0;
context->negotiated_codec = 0;
break;
case HFP_CODECS_EXCHANGED:
context->negotiated_codec = 0;
context->codecs_state = HFP_CODECS_W4_AG_COMMON_CODEC;
break;
default:
break;
}
if (context->hf_trigger_codec_connection_setup){
context->state = HFP_SLE_W2_EXCHANGE_COMMON_CODEC;
context->wait_ok = 1;
hfp_hf_cmd_trigger_codec_connection_setup(context->rfcomm_cid);
done = 1;
break;
}
hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
done = 1;
if (context->suggested_codec){
context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
context->codec_confirmed = 1;
context->wait_ok = 1;
break;
case HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
context->codecs_state = HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE;
hfp_hf_cmd_trigger_codec_connection_setup(context->rfcomm_cid);
done = 1;
break;
case HFP_CMD_AG_SUGGESTED_CODEC:
if (hfp_hf_supports_codec(context->suggested_codec)){
context->codec_confirmed = context->suggested_codec;
hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->suggested_codec);
done = 1;
break;
}
break;
case HFP_SLE_W4_EXCHANGE_COMMON_CODEC:
if (context->notify_ag_on_new_codecs){
context->wait_ok = 1;
} else {
context->codec_confirmed = 0;
context->suggested_codec = 0;
context->negotiated_codec = 0;
hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
done = 1;
break;
}
if (context->suggested_codec){
if (hfp_hf_supports_codec(context->suggested_codec)){
context->codec_confirmed = context->suggested_codec;
context->wait_ok = 1;
hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->suggested_codec);
done = 1;
} else {
context->notify_ag_on_new_codecs = 1;
context->wait_ok = 1;
context->codec_confirmed = 0;
context->suggested_codec = 0;
context->negotiated_codec = 0;
hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
done = 1;
}
break;
}
break;
case HFP_CODECS_CONNECTION_ESTABLISHED:
if (context->notify_ag_on_new_codecs){
context->negotiated_codec = 0;
context->wait_ok = 1;
context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
done = 1;
break;
}
default:
break;
}
if (context->hf_trigger_codec_connection_setup){
context->state = HFP_SLE_W2_EXCHANGE_COMMON_CODEC;
context->wait_ok = 1;
hfp_hf_cmd_trigger_codec_connection_setup(context->rfcomm_cid);
done = 1;
break;
}
if (context->establish_audio_connection){
// TODO AUDIO CONNECTION
}
break;
default:
break;
if (done){
context->wait_ok = 1;
}
return done;
}
static void hfp_hf_handle_ok_codecs_connection(hfp_connection_t * context){
// handle audio connection setup
switch (context->state){
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
if (context->notify_ag_on_new_codecs){
context->notify_ag_on_new_codecs = 0;
break;
}
case HFP_SLE_W2_EXCHANGE_COMMON_CODEC:
if (context->hf_trigger_codec_connection_setup){
context->hf_trigger_codec_connection_setup = 0;
context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
break;
}
// handle audio connection setup
switch (context->codecs_state){
case HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE:
context->codecs_state = HFP_CODECS_W4_AG_COMMON_CODEC;
break;
case HFP_SLE_W4_EXCHANGE_COMMON_CODEC:
if (context->notify_ag_on_new_codecs){
context->codec_confirmed = 0;
context->suggested_codec = 0;
context->notify_ag_on_new_codecs = 0;
break;
}
if (context->codec_confirmed && context->suggested_codec){
context->negotiated_codec = context->suggested_codec;
context->codec_confirmed = 0;
context->suggested_codec = 0;
context->state = HFP_CODECS_CONNECTION_ESTABLISHED;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0);
break;
}
break;
case HFP_AUDIO_CONNECTION_ESTABLISHED:
printf("HFP_AUDIO_CONNECTION_ESTABLISHED \n");
break;
default:
break;
}
}
static void hfp_run_for_context(hfp_connection_t * context){
if (!context) return;
if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return;
int done = hfp_hf_run_for_context_service_level_connection(context);
if (rfcomm_can_send_packet_now(context->rfcomm_cid) && !done){
if (!done){
done = hfp_hf_run_for_context_service_level_connection_queries(context);
if (rfcomm_can_send_packet_now(context->rfcomm_cid) && !done){
done = hfp_hf_run_for_context_codecs_connection(context);
}
}
if (!done){
done = codecs_exchange_state_machine(context);
}
if (done) return;
@ -631,7 +558,6 @@ static void hfp_hf_switch_on_ok(hfp_connection_t *context){
hfp_hf_handle_ok_service_level_connection_establishment(context);
hfp_hf_handle_ok_service_level_connection_queries(context);
hfp_hf_handle_ok_codecs_connection(context);
// done
context->command = HFP_CMD_NONE;
}
@ -718,7 +644,7 @@ void hfp_hf_set_codecs(uint8_t * codecs, int codecs_nr){
while (linked_list_iterator_has_next(&it)){
hfp_connection_t * connection = (hfp_connection_t *)linked_list_iterator_next(&it);
if (!connection) continue;
connection->notify_ag_on_new_codecs = 1;
connection->command = HFP_CMD_AVAILABLE_CODECS;
hfp_run_for_context(connection);
}
}
@ -795,22 +721,6 @@ void hfp_hf_enable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_
hfp_run_for_context(connection);
}
void hfp_hf_negotiate_codecs(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 (!has_codec_negotiation_feature(connection)) return;
if (connection->remote_codecs_nr == 0) return;
if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
if (connection->state != HFP_SLE_W2_EXCHANGE_COMMON_CODEC &&
connection->state != HFP_SLE_W4_EXCHANGE_COMMON_CODEC){
connection->hf_trigger_codec_connection_setup = 1;
}
hfp_run_for_context(connection);
}
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);
@ -820,9 +730,13 @@ void hfp_hf_establish_audio_connection(bd_addr_t bd_addr){
if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
connection->establish_audio_connection = 1;
if (connection->state < HFP_SLE_W4_EXCHANGE_COMMON_CODEC){
connection->hf_trigger_codec_connection_setup = 1;
}
switch (connection->codecs_state){
case HFP_CODECS_W4_AG_COMMON_CODEC:
break;
default:
connection->command = HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP;
break;
}
hfp_run_for_context(connection);
}

View File

@ -141,8 +141,6 @@ void hfp_hf_enable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_
/**
* @brief
*/
void hfp_hf_negotiate_codecs(bd_addr_t bd_addr);
void hfp_hf_establish_audio_connection(bd_addr_t bd_addr);
/**