hfp: report extended AG error result code

This commit is contained in:
Milanka Ringwald 2015-08-20 12:54:47 +02:00
parent d89553ebba
commit 8ca6f17bb0
11 changed files with 388 additions and 81 deletions

View File

@ -625,6 +625,7 @@ extern "C" {
#define HFP_SUBEVENT_COMPLETE 0x03
#define HFP_SUBEVENT_AG_INDICATOR_STATUS_CHANGED 0x04
#define HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED 0x05
#define HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR 0x06
// ANCS Client
#define ANCS_CLIENT_CONNECTED 0xF0

View File

@ -509,7 +509,7 @@ void process_command(hfp_connection_t * context){
return;
}
if (strncmp((char *)context->line_buffer+offset, HFP_OK, strlen(HFP_OK)) == 0){
if (isHandsFree && strncmp((char *)context->line_buffer+offset, HFP_OK, strlen(HFP_OK)) == 0){
//printf("parsed HFP_CMD_OK \n");
context->command = HFP_CMD_OK;
return;
@ -593,6 +593,19 @@ void process_command(hfp_connection_t * context){
context->command = HFP_CMD_TRANSFER_AG_INDICATOR_STATUS;
return;
}
if (isHandsFree && strncmp((char *)context->line_buffer+offset, HFP_EXTENDED_AUDIO_GATEWAY_ERROR, strlen(HFP_EXTENDED_AUDIO_GATEWAY_ERROR)) == 0){
printf(" process command 1 %s \n", context->line_buffer);
context->command = HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR;
return;
}
if (!isHandsFree && strncmp((char *)context->line_buffer+offset, HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR, strlen(HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR)) == 0){
printf(" process command 2 %s \n", context->line_buffer);
context->command = HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR;
return;
}
printf(" process unknown command 3 %s \n", context->line_buffer);
}
uint32_t fromBinary(char *s) {
@ -679,7 +692,7 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){
int value;
// TODO: handle space inside word
if (byte == ' ') return;
if (byte == ' ' && context->parser_state > HFP_PARSER_CMD_HEADER) return;
if (!hfp_parser_found_separator(context, byte)){
hfp_parser_store_byte(context, byte);
@ -805,7 +818,16 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){
break;
}
break;
case HFP_CMD_ERROR:
break;
case HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR:
context->extended_audio_gateway_error = (uint8_t)atoi((char*)context->line_buffer);
break;
case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR:
context->enable_extended_audio_gateway_error_report = (uint8_t)atoi((char*)context->line_buffer);
context->send_ok = 1;
context->extended_audio_gateway_error = 0;
break;
default:
break;
}

View File

@ -110,7 +110,8 @@ extern "C" {
#define HFP_GENERIC_STATUS_INDICATOR "+BIND"
#define HFP_TRANSFER_AG_INDICATOR_STATUS "+CIEV" // +CIEV: <index>,<value>
#define HFP_QUERY_OPERATOR_SELECTION "+COPS" // +COPS: <mode>,0,<opearator>
#define HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR "+CMEE"
#define HFP_EXTENDED_AUDIO_GATEWAY_ERROR "+CME ERROR"
#define HFP_OK "OK"
#define HFP_ERROR "ERROR"
@ -133,9 +134,49 @@ typedef enum {
HFP_CMD_GENERIC_STATUS_INDICATOR,
HFP_CMD_TRANSFER_AG_INDICATOR_STATUS,
HFP_CMD_QUERY_OPERATOR_SELECTION
HFP_CMD_QUERY_OPERATOR_SELECTION,
HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR,
HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR
} hfp_command_t;
typedef enum {
HFP_CME_ERROR_AG_FAILURE = 0,
HFP_CME_ERROR_NO_CONNECTION_TO_PHONE,
HFP_CME_ERROR_2,
HFP_CME_ERROR_OPERATION_NOT_ALLOWED,
HFP_CME_ERROR_OPERATION_NOT_SUPPORTED,
HFP_CME_ERROR_PH_SIM_PIN_REQUIRED,
HFP_CME_ERROR_6,
HFP_CME_ERROR_7,
HFP_CME_ERROR_8,
HFP_CME_ERROR_9,
HFP_CME_ERROR_SIM_NOT_INSERTED,
HFP_CME_ERROR_SIM_PIN_REQUIRED,
HFP_CME_ERROR_SIM_PUK_REQUIRED,
HFP_CME_ERROR_SIM_FAILURE,
HFP_CME_ERROR_SIM_BUSY,
HFP_CME_ERROR_15,
HFP_CME_ERROR_INCORRECT_PASSWORD,
HFP_CME_ERROR_SIM_PIN2_REQUIRED,
HFP_CME_ERROR_SIM_PUK2_REQUIRED,
HFP_CME_ERROR_19,
HFP_CME_ERROR_MEMORY_FULL,
HFP_CME_ERROR_INVALID_INDEX,
HFP_CME_ERROR_22,
HFP_CME_ERROR_MEMORY_FAILURE,
HFP_CME_ERROR_TEXT_STRING_TOO_LONG,
HFP_CME_ERROR_INVALID_CHARACTERS_IN_TEXT_STRING,
HFP_CME_ERROR_DIAL_STRING_TOO_LONG,
HFP_CME_ERROR_INVALID_CHARACTERS_IN_DIAL_STRING,
HFP_CME_ERROR_28,
HFP_CME_ERROR_29,
HFP_CME_ERROR_NO_NETWORK_SERVICE,
HFP_CME_ERROR_NETWORK_TIMEOUT,
HFP_CME_ERROR_NETWORK_NOT_ALLOWED_EMERGENCY_CALLS_ONLY
} hfp_cme_error_t;
typedef enum {
HFP_PARSER_CMD_HEADER = 0,
HFP_PARSER_CMD_SEQUENCE,
@ -254,7 +295,9 @@ typedef struct hfp_connection {
// TODO: put these bit flags in a bitmap
uint8_t wait_ok;
uint8_t send_ok;
uint8_t send_error;
uint8_t keep_separator;
uint8_t retrieve_ag_indicators; // HFP_CMD_INDICATOR, check if needed
@ -264,11 +307,14 @@ typedef struct hfp_connection {
uint8_t retrieve_generic_status_indicators; // HFP_CMD_GENERIC_STATUS_INDICATOR
uint8_t retrieve_generic_status_indicators_state; // HFP_CMD_GENERIC_STATUS_INDICATOR_STATE
uint8_t change_status_update_for_individual_ag_indicators;
uint8_t operator_name_format;
uint8_t operator_name;
uint8_t operator_name_changed;
uint8_t change_status_update_for_individual_ag_indicators;
uint8_t enable_extended_audio_gateway_error_report;
uint8_t extended_audio_gateway_error;
} hfp_connection_t;

View File

@ -163,6 +163,12 @@ int hfp_ag_error(uint16_t cid){
return send_str_over_rfcomm(cid, buffer);
}
int hfp_ag_report_extended_audio_gateway_error(uint16_t cid, uint8_t error){
char buffer[20];
sprintf(buffer, "\r\n%s=%d\r\n", HFP_EXTENDED_AUDIO_GATEWAY_ERROR, error);
return send_str_over_rfcomm(cid, buffer);
}
int hfp_ag_retrieve_codec_cmd(uint16_t cid){
return hfp_ag_ok(cid);
}
@ -333,17 +339,36 @@ void hfp_run_for_context(hfp_connection_t *context){
//printf(" hfp_run_for_context 1 state %d, command %d\n", context->state, context->command);
if (context->state == HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED){
if (context->enable_status_update_for_ag_indicators == 1){
if (context->send_ok){
hfp_ag_ok(context->rfcomm_cid);
context->send_ok = 0;
return;
}
if (context->send_error){
hfp_ag_error(context->rfcomm_cid);
context->send_error = 0;
return;
}
if (context->enable_status_update_for_ag_indicators){
int i;
for (i = 0; i < context->ag_indicators_nr; i++){
if (context->ag_indicators[i].enabled == 0) continue;
if (context->ag_indicators[i].status_changed == 0) continue;
hfp_ag_transfer_ag_indicators_status_cmd(context->rfcomm_cid, context->ag_indicators[i]);
context->ag_indicators[i].status_changed = 0;
return;
}
}
if (context->enable_extended_audio_gateway_error_report){
if (context->extended_audio_gateway_error){
hfp_ag_report_extended_audio_gateway_error(context->rfcomm_cid, context->extended_audio_gateway_error);
context->extended_audio_gateway_error = 0;
return;
}
}
}
switch(context->command){
@ -568,3 +593,16 @@ void hfp_ag_release_service_level_connection(bd_addr_t bd_addr){
hfp_run_for_context(connection);
}
void hfp_ag_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, hfp_cme_error_t error){
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->extended_audio_gateway_error = 0;
if (!connection->enable_extended_audio_gateway_error_report){
return;
}
connection->extended_audio_gateway_error = error;
hfp_run_for_context(connection);
}

View File

@ -92,6 +92,37 @@ void hfp_ag_establish_service_level_connection(bd_addr_t bd_addr);
*/
void hfp_ag_release_service_level_connection(bd_addr_t bd_addr);
/**
* @brief Report Extended Audio Gateway Error result codes in the AG.
* Whenever there is an error relating to the functionality of the AG as a
* result of AT command, the AG shall send +CME ERROR:
* - +CME ERROR: 0 - AG failure
* - +CME ERROR: 1 - no connection to phone
* - +CME ERROR: 3 - operation not allowed
* - +CME ERROR: 4 - operation not supported
* - +CME ERROR: 5 - PH-SIM PIN required
* - +CME ERROR: 10 - SIM not inserted
* - +CME ERROR: 11 - SIM PIN required
* - +CME ERROR: 12 - SIM PUK required
* - +CME ERROR: 13 - SIM failure
* - +CME ERROR: 14 - SIM busy
* - +CME ERROR: 16 - incorrect password
* - +CME ERROR: 17 - SIM PIN2 required
* - +CME ERROR: 18 - SIM PUK2 required
* - +CME ERROR: 20 - memory full
* - +CME ERROR: 21 - invalid index
* - +CME ERROR: 23 - memory failure
* - +CME ERROR: 24 - text string too long
* - +CME ERROR: 25 - invalid characters in text string
* - +CME ERROR: 26 - dial string too long
* - +CME ERROR: 27 - invalid characters in dial string
* - +CME ERROR: 30 - no network service
* - +CME ERROR: 31 - network Timeout.
* - +CME ERROR: 32 - network not allowed Emergency calls only
*/
void hfp_ag_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, hfp_cme_error_t error);
/* API_END */
#if defined __cplusplus

View File

@ -200,6 +200,11 @@ int hfp_hs_query_operator_name_cmd(uint16_t cid){
return send_str_over_rfcomm(cid, buffer);
}
int hfp_hs_enable_extended_audio_gateway_error_report_cmd(uint16_t cid, uint8_t enable){
char buffer[20];
sprintf(buffer, "AT%s=%d\r\n", HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR, enable);
return send_str_over_rfcomm(cid, buffer);
}
static void hfp_emit_ag_indicator_event(hfp_callback_t callback, int status, hfp_ag_indicator_t indicator){
if (!callback) return;
@ -289,21 +294,21 @@ static void hfp_run_for_context(hfp_connection_t * context){
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:{
int i;
for (i = 0; i < context->ag_indicators_nr; i++){
if (context->ag_indicators[i].status_changed == 1) {
if (context->ag_indicators[i].status_changed) {
hfp_emit_ag_indicator_event(hfp_callback, 0, context->ag_indicators[i]);
context->ag_indicators[i].status_changed = 0;
break;
}
}
if (context->wait_ok == 1) return;
if (context->wait_ok) return;
if (context->enable_status_update_for_ag_indicators != 0xFF){
hfp_hs_activate_status_update_for_all_ag_indicators_cmd(context->rfcomm_cid, context->enable_status_update_for_ag_indicators);
context->wait_ok = 1;
break;
};
if (context->change_status_update_for_individual_ag_indicators == 1){
if (context->change_status_update_for_individual_ag_indicators){
hfp_hs_activate_status_update_for_ag_indicator_cmd(context->rfcomm_cid,
context->ag_indicators_status_update_bitmap,
context->ag_indicators_nr);
@ -311,15 +316,23 @@ static void hfp_run_for_context(hfp_connection_t * context){
break;
}
if (context->operator_name_format == 1){
if (context->operator_name_format){
hfp_hs_query_operator_name_format_cmd(context->rfcomm_cid);
context->wait_ok = 1;
break;
}
if (context->operator_name == 1){
if (context->operator_name){
hfp_hs_query_operator_name_cmd(context->rfcomm_cid);
context->wait_ok = 1;
break;
}
if (context->enable_extended_audio_gateway_error_report){
hfp_hs_enable_extended_audio_gateway_error_report_cmd(context->rfcomm_cid, context->enable_extended_audio_gateway_error_report);
context->wait_ok = 1;
break;
}
break;
}
default:
@ -398,22 +411,28 @@ void handle_switch_on_ok(hfp_connection_t *context){
hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 0);
break;
};
if (context->change_status_update_for_individual_ag_indicators == 1){
context->change_status_update_for_individual_ag_indicators = 0;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 0);
break;
}
if (context->operator_name_format == 1){
if (context->operator_name_format){
context->operator_name_format = 0;
context->operator_name = 1;
break;
}
if (context->operator_name == 1){
if (context->operator_name){
context->operator_name = 0;
hfp_emit_network_operator_event(hfp_callback, 0, context->network_operator);
break;
}
if (context->enable_extended_audio_gateway_error_report){
context->enable_extended_audio_gateway_error_report = 0;
break;
}
break;
default:
@ -435,14 +454,17 @@ static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8
hfp_parse(context, packet[pos]);
if (context->command == HFP_CMD_ERROR){
if (context->state == HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED){
context->wait_ok = 0;
// TODO: reset state? repeat commands? restore bitmaps? get ERROR codes.
hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 1);
} else {
}
context->wait_ok = 0;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_COMPLETE, 1);
return;
}
if (context->command == HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR){
context->wait_ok = 0;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR, context->extended_audio_gateway_error);
context->extended_audio_gateway_error = 0;
return;
}
if (context->command != HFP_CMD_OK) continue;
handle_switch_on_ok(context);
}
@ -510,7 +532,7 @@ void hfp_hf_enable_status_update_for_all_ag_indicators(bd_addr_t bd_addr, uint8_
log_error("HFP HF: connection doesn't exist.");
return;
}
connection->enable_status_update_for_ag_indicators = 1;
connection->enable_status_update_for_ag_indicators = enable;
hfp_run_for_context(connection);
}
@ -537,3 +559,15 @@ void hfp_hf_query_operator_selection(bd_addr_t bd_addr){
connection->operator_name_format = 1;
hfp_run_for_context(connection);
}
void hfp_hf_enable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, uint8_t enable){
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->enable_extended_audio_gateway_error_report = enable;
hfp_run_for_context(connection);
}

View File

@ -107,6 +107,35 @@ void hfp_hf_enable_status_update_for_individual_ag_indicators(bd_addr_t bd_addr,
*/
void hfp_hf_query_operator_selection(bd_addr_t bd_addr);
/**
* @brief Enable/disable Extended Audio Gateway Error result codes in the AG.
* Whenever there is an error relating to the functionality of the AG as a
* result of AT command, the AG shall send +CME ERROR:
* - +CME ERROR: 0 - AG failure
* - +CME ERROR: 1 - no connection to phone
* - +CME ERROR: 3 - operation not allowed
* - +CME ERROR: 4 - operation not supported
* - +CME ERROR: 5 - PH-SIM PIN required
* - +CME ERROR: 10 - SIM not inserted
* - +CME ERROR: 11 - SIM PIN required
* - +CME ERROR: 12 - SIM PUK required
* - +CME ERROR: 13 - SIM failure
* - +CME ERROR: 14 - SIM busy
* - +CME ERROR: 16 - incorrect password
* - +CME ERROR: 17 - SIM PIN2 required
* - +CME ERROR: 18 - SIM PUK2 required
* - +CME ERROR: 20 - memory full
* - +CME ERROR: 21 - invalid index
* - +CME ERROR: 23 - memory failure
* - +CME ERROR: 24 - text string too long
* - +CME ERROR: 25 - invalid characters in text string
* - +CME ERROR: 26 - dial string too long
* - +CME ERROR: 27 - invalid characters in dial string
* - +CME ERROR: 30 - no network service
* - +CME ERROR: 31 - network Timeout.
* - +CME ERROR: 32 - network not allowed Emergency calls only
*/
void hfp_hf_enable_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, uint8_t enable);
/* API_END */

View File

@ -211,6 +211,18 @@ TEST(HFPParser, HFP_AG_HF_QUERY_OPERATOR_SELECTION){
CHECK_EQUAL(context.operator_name_changed, 0);
}
TEST(HFPParser, HFP_AG_EXTENDED_AUDIO_GATEWAY_ERROR){
sprintf(packet, "\r\nAT%s=1\r\n", HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR);
for (pos = 0; pos < strlen(packet); pos++){
hfp_parse(&context, packet[pos]);
}
CHECK_EQUAL(context.command, HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR);
CHECK_EQUAL(context.enable_extended_audio_gateway_error_report, 1);
}
int main (int argc, const char * argv[]){
return CommandLineTestRunner::RunAllTests(argc, argv);
}

View File

@ -103,7 +103,6 @@ TEST(HFPParser, HFP_HF_INDICATORS){
}
offset += snprintf(packet+offset, sizeof(packet)-offset, "\"%s\", (%d, %d)\r\n\r\nOK\r\n", hfp_ag_indicators[pos].name, hfp_ag_indicators[pos].min_range, hfp_ag_indicators[pos].max_range);
context.command = HFP_CMD_INDICATOR;
context.retrieve_ag_indicators = 1;
context.retrieve_ag_indicators_status = 0;
@ -161,8 +160,6 @@ TEST(HFPParser, HFP_HF_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES){
TEST(HFPParser, HFP_HF_GENERIC_STATUS_INDICATOR){
sprintf(packet, "\r\n%s:0,1,2,3,4\r\n\r\nOK\r\n", HFP_GENERIC_STATUS_INDICATOR);
context.command = HFP_CMD_GENERIC_STATUS_INDICATOR;
context.list_generic_status_indicators = 0;
context.retrieve_generic_status_indicators = 1;
context.retrieve_generic_status_indicators_state = 0;
@ -181,7 +178,6 @@ TEST(HFPParser, HFP_HF_GENERIC_STATUS_INDICATOR){
TEST(HFPParser, HFP_HF_GENERIC_STATUS_INDICATOR_STATE){
sprintf(packet, "\r\n%s:0,1\r\n\r\nOK\r\n", HFP_GENERIC_STATUS_INDICATOR);
context.command = HFP_CMD_GENERIC_STATUS_INDICATOR;
context.list_generic_status_indicators = 0;
context.retrieve_generic_status_indicators = 0;
context.retrieve_generic_status_indicators_state = 1;
@ -211,7 +207,7 @@ TEST(HFPParser, HFP_HF_AG_INDICATOR_STATUS_UPDATE){
}
TEST(HFPParser, HFP_HF_AG_QUERY_OPERATOR_SELECTION){
sprintf(packet, "\r\n%s:1,0,sunrise\r\n\r\nOK\r\n", HFP_QUERY_OPERATOR_SELECTION);
sprintf(packet, "\r\n%s:1,0,\"sunrise\"\r\n\r\nOK\r\n", HFP_QUERY_OPERATOR_SELECTION);
for (pos = 0; pos < strlen(packet); pos++){
hfp_parse(&context, packet[pos]);
@ -224,6 +220,27 @@ TEST(HFPParser, HFP_HF_AG_QUERY_OPERATOR_SELECTION){
CHECK_EQUAL( strcmp("sunrise", context.network_operator.name), 0);
}
TEST(HFPParser, HFP_HF_ERROR){
sprintf(packet, "\r\n%s\r\n", HFP_ERROR);
for (pos = 0; pos < strlen(packet); pos++){
hfp_parse(&context, packet[pos]);
}
CHECK_EQUAL(context.command, HFP_CMD_ERROR);
}
TEST(HFPParser, HFP_HF_EXTENDED_AUDIO_GATEWAY_ERROR){
sprintf(packet, "\r\n%s:%d\r\n", HFP_EXTENDED_AUDIO_GATEWAY_ERROR, HFP_CME_ERROR_NO_NETWORK_SERVICE);
for (pos = 0; pos < strlen(packet); pos++){
hfp_parse(&context, packet[pos]);
}
CHECK_EQUAL(context.command, HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR);
CHECK_EQUAL(context.extended_audio_gateway_error, HFP_CME_ERROR_NO_NETWORK_SERVICE);
}
int main (int argc, const char * argv[]){
return CommandLineTestRunner::RunAllTests(argc, argv);
}

View File

@ -71,6 +71,7 @@ const uint32_t hfp_service_buffer[150/4]; // implicit alignment to 4-byte memo
const uint8_t rfcomm_channel_nr = 1;
const char hfp_ag_service_name[] = "BTstack HFP AG Test";
static bd_addr_t device_addr;
static bd_addr_t pts_addr = {0x00,0x1b,0xDC,0x07,0x32,0xEF};
static bd_addr_t speaker = {0x00, 0x21, 0x3C, 0xAC, 0xF7, 0x38};
static uint8_t codecs[1] = {HFP_CODEC_CVSD};
@ -96,37 +97,65 @@ static hfp_generic_status_indicator_t hf_indicators[] = {
{2, 1},
};
uint8_t hfp_connect = 1;
char cmd;
// prototypes
static void show_usage(void);
static void show_usage();
static void reset_pst_flags(){
hfp_connect = 1;
}
// Testig User Interface
static void show_usage(void){
printf("\n--- Bluetooth HFP Hands-Free (HF) unit Test Console ---\n");
printf("---\n");
printf("p - establish HFP connection to PTS module\n");
printf("e - establish HFP connection to local mac\n");
printf("d - release HFP connection\n");
if (hfp_connect){
printf("p - establish HFP connection to PTS module\n");
printf("c - establish HFP connection to local mac\n");
} else {
printf("p - release HFP connection to PTS module\n");
printf("c - release HFP connection to local mac\n");
}
printf("d - report AG failure\n");
printf("---\n");
printf("Ctrl-c - exit\n");
printf("---\n");
}
static int stdin_process(struct data_source *ds){
char buffer;
read(ds->fd, &buffer, 1);
switch (buffer){
read(ds->fd, &cmd, 1);
switch (cmd){
case 'p':
printf("Establishing HFP service level connection to PTS module %s...\n", bd_addr_to_str(pts_addr));
hfp_ag_establish_service_level_connection(pts_addr);
memcpy(device_addr, pts_addr, 6);
if (hfp_connect){
printf("Establish HFP service level connection to PTS module %s...\n", bd_addr_to_str(device_addr));
hfp_ag_establish_service_level_connection(device_addr);
} else {
printf("Release HFP service level connection.\n");
hfp_ag_release_service_level_connection(device_addr);
}
hfp_connect = !hfp_connect;
break;
case 'e':
printf("Establishing HFP service level connection to %s...\n", bd_addr_to_str(speaker));
hfp_ag_establish_service_level_connection(speaker);
case 'c':
memcpy(device_addr, speaker, 6);
if (hfp_connect){
printf("Establish HFP service level connection to %s...\n", bd_addr_to_str(device_addr));
hfp_ag_establish_service_level_connection(device_addr);
} else {
printf("Release HFP service level connection.\n");
hfp_ag_release_service_level_connection(device_addr);
}
hfp_connect = !hfp_connect;
break;
case 'd':
printf("Releasing HFP service level connection.\n");
hfp_ag_release_service_level_connection(speaker);
break;
printf("Report AG failure\n");
hfp_ag_report_extended_audio_gateway_error_result_code(device_addr, HFP_CME_ERROR_AG_FAILURE);
default:
show_usage();
break;
@ -135,23 +164,21 @@ static int stdin_process(struct data_source *ds){
return 0;
}
void packet_handler(uint8_t * event, uint16_t event_size){
if (event[0] != HCI_EVENT_HFP_META) return;
if (event[3]){
printf("ERROR, status: %u\n", event[3]);
return;
}
switch (event[2]) {
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
if (event[3] == 0){
printf("Service level connection established.\n\n");
} else {
printf("Service level connection establishment failed with status %u\n", event[3]);
}
printf("Service level connection established.\n\n");
break;
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
if (event[3] == 0){
printf("Service level connection released.\n\n");
} else {
printf("Service level connection releasing failed with status %u\n", event[3]);
}
printf("Service level connection released.\n\n");
reset_pst_flags();
break;
default:
printf("event not handled %u\n", event[2]);

View File

@ -80,22 +80,46 @@ static uint8_t codecs[1] = {HFP_CODEC_CVSD};
static uint16_t indicators[1] = {0x01};
char cmd;
uint8_t hfp_enable_extended_audio_gateway_error_report = 1;
uint8_t hfp_connect = 1;
uint8_t hfp_enable_status_update_for_all_ag_indicators = 1;
// prototypes
static void show_usage();
static void reset_pst_flags(){
hfp_enable_extended_audio_gateway_error_report = 1;
hfp_connect = 1;
hfp_enable_status_update_for_all_ag_indicators = 1;
}
// Testig User Interface
static void show_usage(void){
printf("\n--- Bluetooth HFP Hands-Free (HF) unit Test Console ---\n");
printf("---\n");
printf("p - establish HFP connection to PTS module\n");
printf("e - establish HFP connection to local mac\n");
printf("r - enable registration status update\n");
printf("d - release HFP connection\n");
printf("i - enabling HFP AG registration status update for individual indicators\n");
printf("o - query network operator\n");
if (hfp_connect){
printf("p - establish HFP connection to PTS module\n");
printf("c - establish HFP connection to local mac\n");
} else {
printf("p - release HFP connection to PTS module\n");
printf("c - release HFP connection to local mac\n");
}
if (hfp_enable_status_update_for_all_ag_indicators){
printf("d - enable registration status update\n");
} else {
printf("d - disable registration status update\n");
}
printf("e - enable HFP AG registration status update for individual indicators\n");
printf("f - query network operator\n");
if (hfp_enable_extended_audio_gateway_error_report){
printf("g - enable reporting of the extended AG error result code\n");
} else {
printf("g - disable reporting of the extended AG error result code\n");
}
printf("---\n");
printf("Ctrl-c - exit\n");
printf("---\n");
@ -106,31 +130,52 @@ static int stdin_process(struct data_source *ds){
switch (cmd){
case 'p':
memcpy(device_addr, pts_addr, 6);
printf("Establishing HFP service level connection to PTS module %s...\n", bd_addr_to_str(device_addr));
hfp_hf_establish_service_level_connection(device_addr);
if (hfp_connect){
printf("Establish HFP service level connection to PTS module %s...\n", bd_addr_to_str(device_addr));
hfp_hf_establish_service_level_connection(device_addr);
} else {
printf("Release HFP service level connection.\n");
hfp_hf_release_service_level_connection(device_addr);
}
hfp_connect = !hfp_connect;
break;
case 'e':
case 'c':
memcpy(device_addr, phone_addr, 6);
printf("Establishing HFP service level connection to %s...\n", bd_addr_to_str(device_addr));
hfp_hf_establish_service_level_connection(device_addr);
if (hfp_connect){
printf("Establish HFP service level connection to %s...\n", bd_addr_to_str(device_addr));
hfp_hf_establish_service_level_connection(device_addr);
} else {
printf("Release HFP service level connection.\n");
hfp_hf_release_service_level_connection(device_addr);
}
hfp_connect = !hfp_connect;
break;
case 'd':
printf("Releasing HFP service level connection.\n");
hfp_hf_release_service_level_connection(device_addr);
if (hfp_enable_status_update_for_all_ag_indicators){
printf("Enable HFP AG registration status update.\n");
} else {
printf("Disable HFP AG registration status update.\n");
}
hfp_hf_enable_status_update_for_all_ag_indicators(device_addr, hfp_enable_status_update_for_all_ag_indicators);
hfp_enable_status_update_for_all_ag_indicators = !hfp_enable_status_update_for_all_ag_indicators;
break;
case 'r':
printf("Enabling HFP AG registration status update.\n");
hfp_hf_enable_status_update_for_all_ag_indicators(device_addr, 1);
break;
case 'i':
printf("Enabling HFP AG registration status update for individual indicators.\n");
case 'e':
printf("Enable HFP AG registration status update for individual indicators.\n");
hfp_hf_enable_status_update_for_individual_ag_indicators(device_addr, 63);
break;
case 'o':
case 'f':
printf("Query network operator.\n");
hfp_hf_query_operator_selection(device_addr);
break;
case 'g':
if (hfp_enable_extended_audio_gateway_error_report){
printf("Enable reporting of the extended AG error result code.\n");
} else {
printf("Disable reporting of the extended AG error result code.\n");
}
hfp_hf_enable_report_extended_audio_gateway_error_result_code(device_addr, hfp_enable_extended_audio_gateway_error_report);
hfp_enable_extended_audio_gateway_error_report = !hfp_enable_extended_audio_gateway_error_report;
break;
default:
show_usage();
break;
@ -142,8 +187,8 @@ static int stdin_process(struct data_source *ds){
void packet_handler(uint8_t * event, uint16_t event_size){
if (event[0] != HCI_EVENT_HFP_META) return;
if (event[3]){
printf("Command \'%c\' failed with status %u\n", cmd, event[3]);
if (event[3] && event[2] != HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR){
printf("ERROR, status: %u\n", event[3]);
return;
}
switch (event[2]) {
@ -152,13 +197,14 @@ void packet_handler(uint8_t * event, uint16_t event_size){
break;
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
printf("Service level connection released.\n\n");
reset_pst_flags();
break;
case HFP_SUBEVENT_COMPLETE:
switch (cmd){
case 'r':
case 'd':
printf("HFP AG registration status update enabled.\n");
break;
case 'i':
case 'e':
printf("HFP AG registration status update for individual indicators set.\n");
default:
break;
@ -168,7 +214,11 @@ void packet_handler(uint8_t * event, uint16_t event_size){
printf("AG_INDICATOR_STATUS_CHANGED, AG indicator index: %d, status: %d\n", event[4], event[5]);
break;
case HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED:
printf("HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED, operator mode: %d, format: %d, name: %s\n", event[4], event[5], (char *) &event[6]);
printf("NETWORK_OPERATOR_CHANGED, operator mode: %d, format: %d, name: %s\n", event[4], event[5], (char *) &event[6]);
break;
case HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR:
if (event[4])
printf("EXTENDED_AUDIO_GATEWAY_ERROR_REPORT, status : %d\n", event[3]);
break;
default:
printf("event not handled %u\n", event[2]);