mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-20 18:40:31 +00:00
hfp: report extended AG error result code
This commit is contained in:
parent
d89553ebba
commit
8ca6f17bb0
@ -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
|
||||
|
28
src/hfp.c
28
src/hfp.c
@ -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;
|
||||
}
|
||||
|
54
src/hfp.h
54
src/hfp.h
@ -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;
|
||||
|
||||
|
42
src/hfp_ag.c
42
src/hfp_ag.c
@ -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);
|
||||
}
|
||||
|
31
src/hfp_ag.h
31
src/hfp_ag.h
@ -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
|
||||
|
64
src/hfp_hf.c
64
src/hfp_hf.c
@ -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);
|
||||
}
|
||||
|
||||
|
29
src/hfp_hf.h
29
src/hfp_hf.h
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user