hfp: rewrite ag codec connection; not tested

This commit is contained in:
Milanka Ringwald 2015-08-28 00:33:20 +02:00
parent 50512b8ac1
commit d86bb74349
4 changed files with 93 additions and 85 deletions

View File

@ -349,7 +349,7 @@ int hfp_ag_report_network_operator_name_cmd(uint16_t cid, hfp_network_opearator_
}
int hfp_ag_cmd_confirm_codec(uint16_t cid, uint8_t codec){
int hfp_ag_cmd_suggest_codec(uint16_t cid, uint8_t codec){
char buffer[30];
sprintf(buffer, "\r\nOK\r\n%s=%d\r\n", HFP_CONFIRM_COMMON_CODEC, codec);
return send_str_over_rfcomm(cid, buffer);
@ -373,7 +373,7 @@ void hfp_run_for_context(hfp_connection_t *context){
// printf(" hfp_run_for_context \n");
if (!context) return;
if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return;
printf("AG hfp_run_for_context 1 state %d, command %d\n", context->state, context->command);
// printf("AG hfp_run_for_context 1 state %d, command %d\n", context->state, context->command);
if (context->state == HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED){
if (context->send_ok){
@ -406,25 +406,68 @@ void hfp_run_for_context(hfp_connection_t *context){
return;
}
}
if (context->notify_ag_on_new_codecs){
context->notify_ag_on_new_codecs = 0;
hfp_ag_ok(context->rfcomm_cid);
if (!context->negotiated_codec) return;
if (hfp_ag_suggest_codec(context) == context->negotiated_codec) return;
context->suggested_codec = hfp_ag_suggest_codec(context);
context->trigger_codec_connection_setup = 1;
context->state = HFP_SLE_W2_EXCHANGE_COMMON_CODEC;
return;
}
}
if (context->state == HFP_SLE_W2_EXCHANGE_COMMON_CODEC){
if (context->notify_ag_on_new_codecs){
context->notify_ag_on_new_codecs = 0;
hfp_ag_ok(context->rfcomm_cid);
if (!context->negotiated_codec) return;
if (hfp_ag_suggest_codec(context) == context->negotiated_codec) return;
context->suggested_codec = hfp_ag_suggest_codec(context);
context->trigger_codec_connection_setup = 1;
context->state = HFP_SLE_W2_EXCHANGE_COMMON_CODEC;
return;
}
if (context->trigger_codec_connection_setup){
context->trigger_codec_connection_setup = 0;
hfp_ag_cmd_suggest_codec(context->rfcomm_cid, context->suggested_codec);
context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
}
}
if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED){
// TODO
if (context->state == HFP_SLE_W4_EXCHANGE_COMMON_CODEC){
if (context->codec_confirmed){
// TODO check if they are equal?
if (context->codec_confirmed == context->suggested_codec){
context->negotiated_codec = context->codec_confirmed;
hfp_ag_ok(context->rfcomm_cid);
context->state = HFP_CODECS_CONNECTION_ESTABLISHED;
break;
} else {
hfp_ag_error(context->rfcomm_cid);
context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
}
context->codec_confirmed = 0;
context->suggested_codec = 0;
}
}
if (context->state == HFP_CODECS_CONNECTION_ESTABLISHED){
}
switch(context->command){
// START codec setup
case HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
if (!hfp_ag_choose_codec(context)){
hfp_ag_error(context->rfcomm_cid);
break;
}
switch (context->state){
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
// hfp_ag_ok(context->rfcomm_cid);
context->negotiated_codec = hfp_ag_choose_codec(context);
hfp_ag_cmd_confirm_codec(context->rfcomm_cid, context->negotiated_codec);
context->trigger_codec_connection_setup = 1;
context->suggested_codec = hfp_ag_choose_codec(context);
hfp_ag_cmd_suggest_codec(context->rfcomm_cid, context->negotiated_codec);
context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC;
break;
default:
@ -432,13 +475,7 @@ void hfp_run_for_context(hfp_connection_t *context){
break;
}
break;
case HFP_CMD_RECEIVED_COMMON_CODEC:
hfp_ag_ok(context->rfcomm_cid);
context->state = HFP_CODECS_CONNECTION_ESTABLISHED;
break;
// END codec setup
case HFP_CMD_SUPPORTED_FEATURES:
switch(context->state){
case HFP_W4_EXCHANGE_SUPPORTED_FEATURES:
@ -459,6 +496,11 @@ void hfp_run_for_context(hfp_connection_t *context){
hfp_ag_retrieve_codec_cmd(context->rfcomm_cid);
context->state = HFP_W4_RETRIEVE_INDICATORS;
break;
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
case HFP_SLE_W2_EXCHANGE_COMMON_CODEC:
case HFP_SLE_W4_EXCHANGE_COMMON_CODEC:
context->notify_ag_on_new_codecs = 1;
break;
default:
break;
}
@ -730,36 +772,25 @@ void hfp_ag_codec_connection_setup(hfp_connection_t * connection){
*/
void hfp_ag_negotiate_codecs(bd_addr_t bd_addr){
hfp_ag_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;
hfp_negotiate_codecs(connection);
hfp_run_for_context(connection);
}
void hfp_ag_establish_audio_connection(bd_addr_t bd_addr){
hfp_ag_establish_service_level_connection(bd_addr);
hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
if (!connection){
log_error("HFP AG: connection doesn't exist.");
return;
}
if (connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return;
// if (connection->remote_codecs_nr == 0) {
// log_error("HFP AG: codecs not exchanged, or no codecs specified in HF.");
// 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 (!has_codec_negotiation_feature(connection)) return;
hfp_establish_audio_connection(connection);
hfp_run_for_context(connection);
}
void hfp_ag_release_audio_connection(bd_addr_t bd_addr){
hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
// TODO:
hfp_release_audio_connection(connection);
hfp_run_for_context(connection);
}

View File

@ -472,11 +472,11 @@ static void hfp_run_for_context(hfp_connection_t * context){
break;
}
if (context->remote_codec_received){
if (context->suggested_codec){
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);
hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->suggested_codec);
break;
}
break;
@ -485,15 +485,15 @@ static void hfp_run_for_context(hfp_connection_t * context){
if (context->notify_ag_on_new_codecs){
context->wait_ok = 1;
context->codec_confirmed = 0;
context->remote_codec_received = 0;
context->suggested_codec = 0;
context->negotiated_codec = 0;
hfp_hf_cmd_notify_on_codecs(context->rfcomm_cid);
break;
}
if (context->remote_codec_received){
if (context->suggested_codec){
context->codec_confirmed = 1;
context->wait_ok = 1;
hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->remote_codec_received);
hfp_hf_cmd_confirm_codec(context->rfcomm_cid, context->suggested_codec);
break;
}
@ -560,14 +560,14 @@ void hfp_hf_switch_on_ok(hfp_connection_t *context){
case HFP_SLE_W4_EXCHANGE_COMMON_CODEC:
if (context->notify_ag_on_new_codecs){
context->codec_confirmed = 0;
context->remote_codec_received = 0;
context->suggested_codec = 0;
context->notify_ag_on_new_codecs = 0;
break;
}
if (context->codec_confirmed && context->remote_codec_received){
context->negotiated_codec = context->remote_codec_received;
if (context->codec_confirmed && context->suggested_codec){
context->negotiated_codec = context->suggested_codec;
context->codec_confirmed = 0;
context->remote_codec_received = 0;
context->suggested_codec = 0;
context->state = HFP_CODECS_CONNECTION_ESTABLISHED;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0);
break;
@ -746,46 +746,23 @@ void hfp_hf_enable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_
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 (!connection){
log_error("HFP HF: connection doesn't exist.");
return;
}
if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
if (!has_codec_negotiation_feature(connection)) return;
if (connection->state != HFP_SLE_W4_EXCHANGE_COMMON_CODEC){
connection->trigger_codec_connection_setup = 1;
}
hfp_negotiate_codecs(connection);
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);
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->establish_audio_connection = 1;
if (connection->state < HFP_SLE_W4_EXCHANGE_COMMON_CODEC){
connection->trigger_codec_connection_setup = 1;
}
hfp_establish_audio_connection(connection);
hfp_run_for_context(connection);
}
void hfp_hf_release_audio_connection(bd_addr_t bd_addr){
hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
if (!connection) return;
if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
connection->release_audio_connection = 1;
hfp_release_audio_connection(connection);
hfp_run_for_context(connection);
}

View File

@ -283,12 +283,12 @@ TEST_GROUP(HandsfreeClient){
};
TEST(HandsfreeClient, HFCodecsConnectionEstablished){
setup_hfp_service_level_connection(default_slc_setup, default_slc_setup_size);
for (int i = 0; i < cc_tests_size; i++){
setup_hfp_codecs_connection_state_machine(hfp_cc_tests[i].test, hfp_cc_tests[i].len);
}
}
// TEST(HandsfreeClient, HFCodecsConnectionEstablished){
// setup_hfp_service_level_connection(default_slc_setup, default_slc_setup_size);
// for (int i = 0; i < cc_tests_size; i++){
// setup_hfp_codecs_connection_state_machine(hfp_cc_tests[i].test, hfp_cc_tests[i].len);
// }
// }
TEST(HandsfreeClient, HFCodecChange){
setup_hfp_service_level_connection(default_slc_setup, default_slc_setup_size);

View File

@ -4,7 +4,6 @@
#include <string.h>
#include <btstack/btstack.h>
// #include "att.h"
#include "hci.h"
#include "hci_dump.h"
#include "sdp_query_rfcomm.h"
@ -13,7 +12,6 @@
static void *registered_sdp_app_context;
static uint8_t sdp_rfcomm_channel_nr = 1;
const char sdp_rfcomm_service_name[] = "BTstackMock";
static rfcomm_channel_t rfcomm_channel;
static uint16_t rfcomm_cid = 1;
static uint8_t rfcomm_payload[200];
static uint16_t rfcomm_payload_len;
@ -115,7 +113,9 @@ void rfcomm_create_channel_internal(void * connection, bd_addr_t addr, uint8_t c
(*registered_rfcomm_packet_handler)(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, pos);
}
int rfcomm_can_send_packet_now(uint16_t rfcomm_cid){
return 1;
}
void rfcomm_disconnect_internal(uint16_t rfcomm_cid){
uint8_t event[4];