mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-29 22:20:37 +00:00
hfp: query opertor selection
This commit is contained in:
parent
d99b17319d
commit
39e5036320
56
src/hfp.c
56
src/hfp.c
@ -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;
|
||||
|
22
src/hfp.h
22
src/hfp.h
@ -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;
|
||||
|
45
src/hfp_ag.c
45
src/hfp_ag.c
@ -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:
|
||||
|
57
src/hfp_hf.c
57
src/hfp_hf.c
@ -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);
|
||||
}
|
||||
|
13
src/hfp_hf.h
13
src/hfp_hf.h
@ -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 */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user