hfp: transfer status call, callsetup, callheld

This commit is contained in:
Milanka Ringwald 2015-08-20 16:21:07 +02:00
parent 7a4980db5e
commit 374724f4ef
5 changed files with 134 additions and 1 deletions

View File

@ -177,6 +177,24 @@ typedef enum {
HFP_CME_ERROR_NETWORK_NOT_ALLOWED_EMERGENCY_CALLS_ONLY
} hfp_cme_error_t;
typedef enum {
HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS = 0,
HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT
} hfp_call_status_t;
typedef enum {
HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS = 0,
HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS,
HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_DIALING_STATE,
HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE
} hfp_callsetup_status_t;
typedef enum {
HFP_HELDCALL_STATUS_NO_CALLS_HELD = 0,
HFP_HELDCALL_STATUS_CALL_ON_HOLD_OR_SWAPPED,
HFP_HELDCALL_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS
} hfp_callheld_status_t;
typedef enum {
HFP_PARSER_CMD_HEADER = 0,
HFP_PARSER_CMD_SEQUENCE,
@ -287,6 +305,7 @@ typedef struct hfp_connection {
int generic_status_indicators_nr;
hfp_generic_status_indicator_t generic_status_indicators[HFP_MAX_INDICATOR_DESC_SIZE];
uint8_t enable_status_update_for_ag_indicators;
uint32_t ag_indicators_status_update_bitmap;
hfp_network_opearator_t network_operator;
@ -316,6 +335,7 @@ typedef struct hfp_connection {
uint8_t enable_extended_audio_gateway_error_report;
uint8_t extended_audio_gateway_error;
} hfp_connection_t;
// UTILS_START : TODO move to utils

View File

@ -110,6 +110,23 @@ void hfp_ag_register_packet_handler(hfp_callback_t callback){
hfp_callback = callback;
}
static uint8_t hfp_get_indicator_index_by_name(hfp_connection_t * context, const char * name){
int i;
for (i=0; i<context->ag_indicators_nr; i++){
if (strcmp(context->ag_indicators[i].name, name) == 0){
return i;
}
}
return 0xFF;
}
static void hfp_ag_update_indicator_status(hfp_connection_t * context, const char * indicator_name, uint8_t status){
int index = hfp_get_indicator_index_by_name(context, indicator_name);
if (index == 0xFF) return;
if (context->ag_indicators[index].status == status) return;
context->ag_indicators[index].status = status;
context->ag_indicators[index].status_changed = 1;
}
static int has_codec_negotiation_feature(hfp_connection_t * connection){
int hf = get_bit(connection->remote_supported_features, HFP_HFSF_CODEC_NEGOTIATION);
@ -123,7 +140,6 @@ static int has_call_waiting_and_3way_calling_feature(hfp_connection_t * connecti
return hf && ag;
}
static int has_hf_indicators_feature(hfp_connection_t * connection){
int hf = get_bit(connection->remote_supported_features, HFP_HFSF_HF_INDICATORS);
int ag = get_bit(hfp_supported_features, HFP_AGSF_HF_INDICATORS);
@ -606,3 +622,34 @@ void hfp_ag_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, h
connection->extended_audio_gateway_error = error;
hfp_run_for_context(connection);
}
void hfp_ag_transfer_call_status(bd_addr_t bd_addr, hfp_callsetup_status_t status){
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->enable_status_update_for_ag_indicators) return;
hfp_ag_update_indicator_status(connection, (char *)"call", status);
}
void hfp_ag_transfer_callsetup_status(bd_addr_t bd_addr, hfp_callsetup_status_t status){
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->enable_status_update_for_ag_indicators) return;
hfp_ag_update_indicator_status(connection, (char *)"callsetup", status);
}
void hfp_ag_transfer_callheld_status(bd_addr_t bd_addr, hfp_callheld_status_t status){
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->enable_status_update_for_ag_indicators) return;
hfp_ag_update_indicator_status(connection, (char *)"callheld", status);
hfp_run_for_context(connection);
}

View File

@ -122,6 +122,33 @@ void hfp_ag_release_service_level_connection(bd_addr_t bd_addr);
*/
void hfp_ag_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, hfp_cme_error_t error);
/**
* @brief Report the change in AG's call status.
* Call status:
* - 0 = No calls (held or active)
* - 1 = Call is present (active or held)
*/
void hfp_ag_transfer_call_status(bd_addr_t bd_addr, uint8_t index, hfp_call_status_t status);
/**
* @brief Report the change in AG's call setup status.
* Call setup status:
* - 0 = No call setup in progress
* - 1 = Incoming call setup in progress
* - 2 = Outgoing call setup in dialing state
* - 3 = Outgoing call setup in alerting state
*/
void hfp_ag_transfer_callsetup_status(bd_addr_t bd_addr, uint8_t index, hfp_callsetup_status_t status);
/**
* @brief Report the change in AG's held call status.
* Held call status:
* - 0 = No calls held
* - 1 = Call is placed on hold or active/held calls are swapped
* - 2 = Call on hold, no active calls
*/
void hfp_ag_transfer_callheld_status(bd_addr_t bd_addr, uint8_t index, hfp_callheld_status_t status);
/* API_END */

View File

@ -138,6 +138,7 @@ void hfp_hf_query_operator_selection(bd_addr_t bd_addr);
void hfp_hf_enable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, uint8_t enable);
/* API_END */
#if defined __cplusplus

View File

@ -60,6 +60,10 @@ static hfp_ag_indicator_t hfp_ag_indicators[] = {
{6, "roam", 0, 1, 0, 0, 0, 0},
{7, "callheld", 0, 2, 0, 1, 1, 0}
};
static uint8_t call_status_index = 2;
static uint8_t callsetup_status_index = 3;
static uint8_t callheld_status_index = 7;
TEST_GROUP(HFPParser){
char packet[200];
@ -241,6 +245,40 @@ TEST(HFPParser, HFP_HF_EXTENDED_AUDIO_GATEWAY_ERROR){
CHECK_EQUAL(context.extended_audio_gateway_error, HFP_CME_ERROR_NO_NETWORK_SERVICE);
}
TEST(HFPParser, HFP_HF_AG_INDICATOR_CALLS_STATUS_UPDATE){
context.ag_indicators_nr = hfp_ag_indicators_nr;
memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
uint8_t status = 1;
// call status
uint8_t index = call_status_index;
sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status);
for (pos = 0; pos < strlen(packet); pos++){
hfp_parse(&context, packet[pos]);
}
CHECK_EQUAL(HFP_CMD_OK, context.command);
CHECK_EQUAL(context.ag_indicators[index - 1].status, status);
// callsetup status
index = callsetup_status_index;
sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status);
for (pos = 0; pos < strlen(packet); pos++){
hfp_parse(&context, packet[pos]);
}
CHECK_EQUAL(HFP_CMD_OK, context.command);
CHECK_EQUAL(context.ag_indicators[index - 1].status, status);
// callheld status
index = callheld_status_index;
sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status);
for (pos = 0; pos < strlen(packet); pos++){
hfp_parse(&context, packet[pos]);
}
CHECK_EQUAL(HFP_CMD_OK, context.command);
CHECK_EQUAL(context.ag_indicators[index - 1].status, status);
}
int main (int argc, const char * argv[]){
return CommandLineTestRunner::RunAllTests(argc, argv);
}