hfp: query opertor selection

This commit is contained in:
Milanka Ringwald 2015-08-13 15:01:19 +02:00
parent d99b17319d
commit 39e5036320
5 changed files with 163 additions and 30 deletions

View File

@ -604,6 +604,31 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){
context->parser_item_index = atoi((char *)&context->line_buffer[0]) - 1;
context->parser_state = HFP_PARSER_CMD_INDICATOR_STATUS;
break;
case HFP_CMD_QUERY_OPERATOR_SELECTION:
printf("Parsed Network operator: %s\n", context->line_buffer);
if (context->operator_name_format == 1){
if (context->line_size == 1 && context->line_buffer[0] == '3'){
context->parser_state = HFP_PARSER_CMD_NETWORK_OPERATOR;
context->line_size = 0;
break;
}
// TODO emit ERROR, wrong format
break;
}
if (context->operator_name != 1) break;
if (context->line_size == 0) {
printf("No operator found\n");
context->network_operator.mode = 0;
context->network_operator.name[0] = 0;
break;
}
context->network_operator.mode = atoi((char *)&context->line_buffer[0]);
context->line_size = 0;
context->parser_state = HFP_PARSER_CMD_NETWORK_OPERATOR;
break;
default:
break;
}
@ -619,6 +644,37 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){
}
context->line_buffer[context->line_size++] = byte;
break;
case HFP_PARSER_CMD_NETWORK_OPERATOR:
if (context->operator_name_format == 1){
if (context->line_size == 1 && context->line_buffer[0] == '0'){
context->network_operator.format = 0;
break;
}
// TODO emit ERROR, wrong format
break;
}
if (context->operator_name != 1) break;
if (byte == ','){
context->line_size = 0;
context->line_buffer[context->line_size] = 0;
break;
}
if (byte == '\n' || byte == '\r'){
context->line_buffer[context->line_size] = 0;
context->line_size = 0;
printf("opearator name %s\n", context->line_buffer);
strcpy(context->network_operator.name, (char *)context->line_buffer);
context->parser_state = HFP_PARSER_CMD_HEADER;
context->parser_item_index = 0;
break;
}
if (context->line_size < 16){
context->line_buffer[context->line_size++] = byte;
}
break;
case HFP_PARSER_CMD_INDICATOR_STATUS:
context->line_buffer[context->line_size] = 0;
if (byte == ',') break;

View File

@ -109,6 +109,8 @@ extern "C" {
#define HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES "+CHLD"
#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_OK "OK"
#define HFP_ERROR "ERROR"
@ -131,7 +133,8 @@ typedef enum {
HFP_CMD_LIST_GENERIC_STATUS_INDICATOR,
HFP_CMD_GENERIC_STATUS_INDICATOR, // 10
HFP_CMD_GENERIC_STATUS_INDICATOR_STATE,
HFP_CMD_TRANSFER_AG_INDICATOR_STATUS
HFP_CMD_TRANSFER_AG_INDICATOR_STATUS,
HFP_CMD_QUERY_OPERATOR_SELECTION
} hfp_command_t;
typedef enum {
@ -140,7 +143,8 @@ typedef enum {
HFP_PARSER_CMD_INDICATOR_NAME,
HFP_PARSER_CMD_INDICATOR_MIN_RANGE,
HFP_PARSER_CMD_INDICATOR_MAX_RANGE,
HFP_PARSER_CMD_INDICATOR_STATUS
HFP_PARSER_CMD_INDICATOR_STATUS,
HFP_PARSER_CMD_NETWORK_OPERATOR
} hfp_parser_state_t;
@ -207,6 +211,14 @@ typedef struct{
char name[3];
} hfp_call_service_t;
typedef struct{
uint8_t mode;
uint8_t format;
char name[17]; // enabled
} hfp_network_opearator_t;
typedef struct hfp_connection {
linked_item_t item;
@ -248,7 +260,11 @@ typedef struct hfp_connection {
uint32_t ag_indicators_status_update_bitmap;
hfp_network_opearator_t network_operator;
uint8_t operator_name_format; // bit flag
uint8_t operator_name; // bit flag
uint8_t operator_name_changed;
// Retrieved during service level connection establishment, not used yet
uint8_t negotiated_codec;
} hfp_connection_t;

View File

@ -146,6 +146,12 @@ int hfp_ag_ok(uint16_t cid){
return send_str_over_rfcomm(cid, buffer);
}
int hfp_ag_error(uint16_t cid){
char buffer[10];
sprintf(buffer, "\r\nERROR\r\n");
return send_str_over_rfcomm(cid, buffer);
}
int hfp_ag_retrieve_codec_cmd(uint16_t cid){
return hfp_ag_ok(cid);
}
@ -269,10 +275,19 @@ int hfp_ag_retrieve_initital_supported_generic_status_indicators_cmd(uint16_t ci
int hfp_ag_transfer_ag_indicators_status_cmd(uint16_t cid, hfp_ag_indicator_t indicator){
char buffer[20];
sprintf(buffer, "\r\n%s:%d,%d", HFP_TRANSFER_AG_INDICATOR_STATUS, indicator.index, indicator.status);
sprintf(buffer, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, indicator.index, indicator.status);
return send_str_over_rfcomm(cid, buffer);
}
int hfp_ag_report_network_operator_name_cmd(uint16_t cid, hfp_network_opearator_t op){
char buffer[40];
if (strlen(op.name) == 0){
sprintf(buffer, "\r\n%s:%d,,\r\n\r\nOK\r\n", HFP_QUERY_OPERATOR_SELECTION, op.mode);
} else {
sprintf(buffer, "\r\n%s:%d,%d,%s\r\n\r\nOK\r\n", HFP_QUERY_OPERATOR_SELECTION, op.mode, op.format, op.name);
}
return send_str_over_rfcomm(cid, buffer);
}
void update_command(hfp_connection_t * context){
context->command = HFP_CMD_NONE;
@ -317,6 +332,18 @@ void update_command(hfp_connection_t * context){
context->command = HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE;
return;
}
if (strncmp((char *)context->line_buffer+2, HFP_QUERY_OPERATOR_SELECTION, strlen(HFP_QUERY_OPERATOR_SELECTION)) == 0){
context->command = HFP_CMD_QUERY_OPERATOR_SELECTION;
if (strncmp((char *)context->line_buffer+strlen(HFP_QUERY_OPERATOR_SELECTION)+2, "?", 1) == 0){
context->operator_name_format = 1;
context->operator_name = 0;
} else {
context->operator_name_format = 1;
context->operator_name = 0;
}
return;
}
}
@ -441,7 +468,21 @@ void hfp_run_for_context(hfp_connection_t *context){
break;
}
break;
case HFP_CMD_QUERY_OPERATOR_SELECTION:
if (context->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) break;
if (context->operator_name_format == 1){
if (context->network_operator.format != 0){
hfp_ag_error(context->rfcomm_cid);
break;
}
hfp_ag_ok(context->rfcomm_cid);
break;
}
if (context->operator_name == 1){
hfp_ag_report_network_operator_name_cmd(context->rfcomm_cid, context->network_operator);
break;
}
break;
case HFP_CMD_NONE:
switch(context->state){
case HFP_W2_DISCONNECT_RFCOMM:

View File

@ -188,6 +188,19 @@ int hfp_hs_list_initital_supported_generic_status_indicators_cmd(uint16_t cid){
return send_str_over_rfcomm(cid, buffer);
}
int hfp_hs_query_operator_name_format_cmd(uint16_t cid){
char buffer[20];
sprintf(buffer, "AT%s=3,0\r\n", HFP_QUERY_OPERATOR_SELECTION);
return send_str_over_rfcomm(cid, buffer);
}
int hfp_hs_query_operator_name_cmd(uint16_t cid){
char buffer[20];
sprintf(buffer, "AT%s?\r\n", HFP_QUERY_OPERATOR_SELECTION);
return send_str_over_rfcomm(cid, buffer);
}
static void hfp_emit_ag_indicator_event(hfp_callback_t callback, hfp_ag_indicator_t indicator){
if (!callback) return;
uint8_t event[5];
@ -251,6 +264,15 @@ static void hfp_run_for_context(hfp_connection_t * context){
rfcomm_disconnect_internal(context->rfcomm_cid);
break;
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) {
hfp_emit_ag_indicator_event(hfp_callback, context->ag_indicators[i]);
context->ag_indicators[i].status_changed = 0;
break;
}
}
if (context->wait_ok == 1) return;
if (context->enable_status_update_for_ag_indicators != 0xFF){
@ -268,11 +290,17 @@ static void hfp_run_for_context(hfp_connection_t * context){
break;
}
int i;
for (i = 0; i < context->ag_indicators_nr; i++){
if (context->ag_indicators[i].status_changed == 1) {
hfp_emit_ag_indicator_event(hfp_callback, context->ag_indicators[i]);
}
if (context->operator_name_format == 1){
hfp_hs_query_operator_name_format_cmd(context->rfcomm_cid);
context->operator_name_format = 0;
context->operator_name = 1;
context->wait_ok = 1;
break;
}
if (context->operator_name == 1){
hfp_hs_query_operator_name_cmd(context->rfcomm_cid);
context->wait_ok = 1;
context->operator_name = 0;
}
break;
}
@ -517,14 +545,13 @@ void hfp_hf_enable_status_update_for_individual_ag_indicators(bd_addr_t bd_addr,
hfp_run_for_context(connection);
}
void hfp_hf_transfer_signal_strength_indication(bd_addr_t bd_addr){
}
void hfp_hf_transfer_roaming_status_indication(bd_addr_t bd_addr){
}
void hfp_hf_transfer_battery_level_indication_of_ag(bd_addr_t bd_addr){
void hfp_hf_query_operator_selection(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->operator_name_format = 1;
hfp_run_for_context(connection);
}

View File

@ -102,19 +102,12 @@ void hfp_hf_enable_status_update_for_individual_ag_indicators(bd_addr_t bd_addr,
/**
* @brief
* @brief Find out the name of the currently selected Network operator by AG.
* The name is restricted to max 16 characters.
*/
void hfp_hf_transfer_signal_strength_indication(bd_addr_t bd_addr);
void hfp_hf_query_operator_selection(bd_addr_t bd_addr);
/**
* @brief
*/
void hfp_hf_transfer_roaming_status_indication(bd_addr_t bd_addr);
/**
* @brief
*/
void hfp_hf_transfer_battery_level_indication_of_ag(bd_addr_t bd_addr);
/* API_END */