mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-10 15:40:11 +00:00
hfp: rewrite parser to handle single bytes
This commit is contained in:
parent
f1ab900fb4
commit
67a9d233cd
@ -183,13 +183,14 @@ static hfp_connection_t * create_hfp_connection_context(){
|
||||
context->state = HFP_IDLE;
|
||||
context->line_size = 0;
|
||||
context->cmd_value_state = HFP_CMD_HEADER;
|
||||
context->cmd_state = HFP_CMD_NONE;
|
||||
context->command = HFP_CMD_NONE;
|
||||
|
||||
context->negotiated_codec = HFP_CODEC_CVSD;
|
||||
context->remote_supported_features = 0;
|
||||
context->remote_indicators_update_enabled = 0;
|
||||
context->remote_indicators_nr = 0;
|
||||
context->remote_indicators_status = 0;
|
||||
context->generic_indicator_name_read = 0;
|
||||
|
||||
linked_list_add(&hfp_connections, (linked_item_t*)context);
|
||||
return context;
|
||||
|
13
src/hfp.h
13
src/hfp.h
@ -113,7 +113,7 @@ extern "C" {
|
||||
#define HFP_CODEC_MSBC 0x02
|
||||
|
||||
typedef enum {
|
||||
HFP_CMD_NONE,
|
||||
HFP_CMD_NONE = 0,
|
||||
HFP_CMD_OK,
|
||||
HFP_CMD_SUPPORTED_FEATURES,
|
||||
HFP_CMD_AVAILABLE_CODECS,
|
||||
@ -121,10 +121,10 @@ typedef enum {
|
||||
HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE,
|
||||
HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES,
|
||||
HFP_CMD_GENERIC_STATUS_INDICATOR
|
||||
} hfp_cmd_state_t;
|
||||
} hfp_command_t;
|
||||
|
||||
typedef enum {
|
||||
HFP_CMD_HEADER,
|
||||
HFP_CMD_HEADER = 0,
|
||||
HFP_CMD_SEQUENCE,
|
||||
HFP_CMD_INDICATOR_NAME,
|
||||
HFP_CMD_INDICATOR_MIN_RANGE,
|
||||
@ -133,7 +133,7 @@ typedef enum {
|
||||
|
||||
|
||||
typedef enum {
|
||||
HFP_IDLE = 0, //50
|
||||
HFP_IDLE = 0, //0
|
||||
HFP_SDP_QUERY_RFCOMM_CHANNEL,
|
||||
HFP_W4_SDP_QUERY_COMPLETE,
|
||||
HFP_W4_RFCOMM_CONNECTED,
|
||||
@ -205,7 +205,7 @@ typedef struct hfp_connection {
|
||||
linked_item_t item;
|
||||
hfp_state_t state;
|
||||
|
||||
hfp_cmd_state_t cmd_state;
|
||||
hfp_command_t command;
|
||||
hfp_cmd_value_state_t cmd_value_state;
|
||||
|
||||
uint8_t line_buffer[HFP_MAX_INDICATOR_DESC_SIZE];
|
||||
@ -218,10 +218,11 @@ typedef struct hfp_connection {
|
||||
|
||||
uint8_t wait_ok;
|
||||
uint8_t negotiated_codec;
|
||||
uint8_t generic_indicator_name_read;
|
||||
|
||||
uint32_t remote_supported_features;
|
||||
uint8_t remote_indicators_update_enabled;
|
||||
uint8_t remote_indicators_nr;
|
||||
int remote_indicators_nr;
|
||||
char remote_indicators[20][HFP_MAX_INDICATOR_DESC_SIZE];
|
||||
int remote_indicators_range[20][2];
|
||||
|
||||
|
233
src/hfp_hf.c
233
src/hfp_hf.c
@ -255,43 +255,48 @@ static void hfp_run_for_context(hfp_connection_t * connection){
|
||||
}
|
||||
}
|
||||
|
||||
void update_cmd_state(hfp_connection_t * context){
|
||||
char * cmd = (char * )&context->line_buffer[0];
|
||||
context->cmd_state = HFP_CMD_NONE;
|
||||
|
||||
if (strncmp(cmd, HFP_OK, strlen(HFP_OK)) == 0){
|
||||
context->cmd_state = HFP_CMD_OK;
|
||||
void update_command(hfp_connection_t * context){
|
||||
context->command = HFP_CMD_NONE;
|
||||
if (strncmp((char *)context->line_buffer, HFP_OK, strlen(HFP_OK)) == 0){
|
||||
context->command = HFP_CMD_OK;
|
||||
printf("Received OK\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(cmd, HFP_SUPPORTED_FEATURES, strlen(HFP_SUPPORTED_FEATURES)) == 0){
|
||||
context->cmd_state = HFP_CMD_SUPPORTED_FEATURES;
|
||||
if (strncmp((char *)context->line_buffer, HFP_SUPPORTED_FEATURES, strlen(HFP_SUPPORTED_FEATURES)) == 0){
|
||||
printf("Received +BRSF\n");
|
||||
context->command = HFP_CMD_SUPPORTED_FEATURES;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(cmd, HFP_INDICATOR, strlen(HFP_INDICATOR)) == 0){
|
||||
context->cmd_state = HFP_CMD_INDICATOR;
|
||||
if (strncmp((char *)context->line_buffer, HFP_INDICATOR, strlen(HFP_INDICATOR)) == 0){
|
||||
printf("Received +CIND\n");
|
||||
context->command = HFP_CMD_INDICATOR;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (strncmp(cmd, HFP_AVAILABLE_CODECS, strlen(HFP_AVAILABLE_CODECS)) == 0){
|
||||
context->cmd_state = HFP_CMD_AVAILABLE_CODECS;
|
||||
if (strncmp((char *)context->line_buffer, HFP_AVAILABLE_CODECS, strlen(HFP_AVAILABLE_CODECS)) == 0){
|
||||
printf("Received +BAC\n");
|
||||
context->command = HFP_CMD_AVAILABLE_CODECS;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(cmd, HFP_ENABLE_INDICATOR_STATUS_UPDATE, strlen(HFP_ENABLE_INDICATOR_STATUS_UPDATE)) == 0){
|
||||
context->cmd_state = HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE;
|
||||
if (strncmp((char *)context->line_buffer, HFP_ENABLE_INDICATOR_STATUS_UPDATE, strlen(HFP_ENABLE_INDICATOR_STATUS_UPDATE)) == 0){
|
||||
printf("Received +CMER\n");
|
||||
context->command = HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(cmd, HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, strlen(HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES)) == 0){
|
||||
context->cmd_state = HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES;
|
||||
if (strncmp((char *)context->line_buffer, HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, strlen(HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES)) == 0){
|
||||
printf("Received +CHLD\n");
|
||||
context->command = HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(cmd, HFP_GENERIC_STATUS_INDICATOR, strlen(HFP_GENERIC_STATUS_INDICATOR)) == 0){
|
||||
context->cmd_state = HFP_CMD_GENERIC_STATUS_INDICATOR;
|
||||
if (strncmp((char *)context->line_buffer, HFP_GENERIC_STATUS_INDICATOR, strlen(HFP_GENERIC_STATUS_INDICATOR)) == 0){
|
||||
printf("Received +BIND\n");
|
||||
context->command = HFP_CMD_GENERIC_STATUS_INDICATOR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -303,23 +308,31 @@ static void hfp_parse2(hfp_connection_t * context, uint8_t byte){
|
||||
|
||||
switch (context->cmd_value_state){
|
||||
case HFP_CMD_HEADER: // header
|
||||
if (byte == ':' || ( (byte == '\n' || byte == '\r' ) && context->line_size > 0) ) {
|
||||
if (byte == ':'){
|
||||
context->cmd_value_state = HFP_CMD_SEQUENCE;
|
||||
context->line_buffer[context->line_size] = 0;
|
||||
context->line_size = 0;
|
||||
update_cmd_state(context);
|
||||
break;
|
||||
update_command(context);
|
||||
return;
|
||||
}
|
||||
if (byte == '\n' || byte == '\r'){
|
||||
// received OK
|
||||
context->line_buffer[context->line_size] = 0;
|
||||
context->line_size = 0;
|
||||
update_command(context);
|
||||
return;
|
||||
}
|
||||
context->line_buffer[context->line_size++] = byte;
|
||||
break;
|
||||
|
||||
case HFP_CMD_SEQUENCE: // parse comma separated sequence, ignore breacktes
|
||||
if (byte == '"'){ // indicators
|
||||
if (byte == '"'){ // indicators
|
||||
context->cmd_value_state = HFP_CMD_INDICATOR_NAME;
|
||||
context->remote_indicators_nr = 0;
|
||||
context->line_size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (byte == '('){ // tuple sepparated mit comma
|
||||
if (byte == '(' ){ // tuple separated mit comma
|
||||
break;
|
||||
}
|
||||
|
||||
@ -334,9 +347,9 @@ static void hfp_parse2(hfp_connection_t * context, uint8_t byte){
|
||||
printf("AG supported feature: %s\n", hfp_ag_feature(i));
|
||||
}
|
||||
}
|
||||
context->cmd_value_state = HFP_CMD_HEADER;
|
||||
break;
|
||||
case HFP_W4_NOTIFY_ON_CODECS:
|
||||
printf("Supported codec: %s\n", context->line_buffer);
|
||||
case HFP_W4_RETRIEVE_INDICATORS:
|
||||
break;
|
||||
case HFP_W4_RETRIEVE_INDICATORS_STATUS:
|
||||
printf("Indicator with status: %s\n", context->line_buffer);
|
||||
@ -344,75 +357,77 @@ static void hfp_parse2(hfp_connection_t * context, uint8_t byte){
|
||||
case HFP_W4_RETRIEVE_CAN_HOLD_CALL:
|
||||
printf("Support call hold: %s\n", context->line_buffer);
|
||||
break;
|
||||
case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS:
|
||||
printf("HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS: %s\n", context->line_buffer);
|
||||
case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS: // comma separated ints
|
||||
printf("Generic status indicator: %s\n", context->line_buffer);
|
||||
break;
|
||||
case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
|
||||
printf("HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS: %s\n", context->line_buffer);
|
||||
if (!context->generic_indicator_name_read){
|
||||
printf("Generic status indicator: %s, ", context->line_buffer);
|
||||
context->generic_indicator_name_read = 1;
|
||||
} else {
|
||||
context->generic_indicator_name_read = 0;
|
||||
printf("status %s\n", context->line_buffer);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("sequence value : %s\n", context->line_buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (byte == '\n' || byte == '\r'){
|
||||
context->cmd_value_state = 0;
|
||||
context->cmd_value_state = HFP_CMD_HEADER;
|
||||
break;
|
||||
}
|
||||
if (byte == ')') {
|
||||
context->cmd_value_state = 1;
|
||||
if (byte == ')' && context->state == HFP_W4_RETRIEVE_CAN_HOLD_CALL){ // tuple separated mit comma
|
||||
context->cmd_value_state = HFP_CMD_HEADER;
|
||||
break;
|
||||
}
|
||||
|
||||
context->line_buffer[context->line_size++] = byte;
|
||||
break;
|
||||
|
||||
|
||||
case HFP_CMD_INDICATOR_NAME: // parse indicator name
|
||||
if (byte == '('){
|
||||
// indicator name end
|
||||
memcpy(context->remote_indicators[context->remote_indicators_nr], context->line_buffer, context->line_size);
|
||||
context->cmd_value_state = HFP_CMD_INDICATOR_MIN_RANGE;
|
||||
context->line_size = 0;
|
||||
break;
|
||||
}
|
||||
context->line_buffer[context->line_size++] = byte;
|
||||
break;
|
||||
case HFP_CMD_INDICATOR_MIN_RANGE: // minrange
|
||||
if (byte == ',' || byte == '-'){
|
||||
|
||||
case HFP_CMD_INDICATOR_NAME: // parse indicator name
|
||||
if (byte == '"'){
|
||||
context->line_buffer[context->line_size] = 0;
|
||||
context->remote_indicators_range[context->remote_indicators_nr][0] = atoi((char *)&context->line_buffer[0]);
|
||||
context->cmd_value_state = HFP_CMD_INDICATOR_MAX_RANGE;
|
||||
printf("Indicator %d: %s (", context->remote_indicators_nr, context->line_buffer);
|
||||
context->line_size = 0;
|
||||
break;
|
||||
}
|
||||
// min-range
|
||||
if (byte == '('){ // parse indicator range
|
||||
context->cmd_value_state = HFP_CMD_INDICATOR_MIN_RANGE;
|
||||
break;
|
||||
}
|
||||
context->line_buffer[context->line_size++] = byte;
|
||||
break;
|
||||
case HFP_CMD_INDICATOR_MIN_RANGE:
|
||||
if (byte == ',' || byte == '-'){ // end min_range
|
||||
context->cmd_value_state = HFP_CMD_INDICATOR_MAX_RANGE;
|
||||
context->line_buffer[context->line_size] = 0;
|
||||
printf("%d, ", atoi((char *)&context->line_buffer[0]));
|
||||
context->line_size = 0;
|
||||
break;
|
||||
}
|
||||
// min. range
|
||||
context->line_buffer[context->line_size++] = byte;
|
||||
break;
|
||||
case HFP_CMD_INDICATOR_MAX_RANGE:
|
||||
if (byte == ')'){
|
||||
context->line_buffer[context->line_size] = 0;
|
||||
context->remote_indicators_range[context->remote_indicators_nr][1] = atoi((char *)&context->line_buffer[0]);
|
||||
if (byte == ')'){ // end max_range
|
||||
context->cmd_value_state = HFP_CMD_SEQUENCE;
|
||||
context->line_size = 0;
|
||||
|
||||
printf("Indicator %d: %s, range [%d, %d] \n", context->remote_indicators_nr,
|
||||
context->remote_indicators[context->remote_indicators_nr],
|
||||
context->remote_indicators_range[context->remote_indicators_nr][0],
|
||||
context->remote_indicators_range[context->remote_indicators_nr][1]);
|
||||
context->remote_indicators_nr++;
|
||||
context->line_buffer[context->line_size] = 0;
|
||||
printf("%d)\n", atoi((char *)&context->line_buffer[0]));
|
||||
context->line_size = 0;
|
||||
context->remote_indicators_nr+=1;
|
||||
break;
|
||||
}
|
||||
// max-range
|
||||
//
|
||||
context->line_buffer[context->line_size++] = byte;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int wait_for_more_cmd_data(hfp_connection_t * context){
|
||||
return context->cmd_value_state == 0;
|
||||
return context->command == HFP_CMD_NONE;
|
||||
}
|
||||
|
||||
int wait_for_more_data(hfp_connection_t * context){
|
||||
@ -424,35 +439,36 @@ static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8
|
||||
if (!context) return;
|
||||
|
||||
packet[size] = 0;
|
||||
printf("Received %s\n", packet);
|
||||
|
||||
|
||||
int pos = 0;
|
||||
|
||||
context->command = HFP_CMD_NONE;
|
||||
while (wait_for_more_cmd_data(context) && pos < size){
|
||||
hfp_parse2(context, packet[pos++]);
|
||||
}
|
||||
if (wait_for_more_cmd_data(context)) return;
|
||||
|
||||
if (context->wait_ok){
|
||||
if (context->cmd_state == HFP_CMD_OK){
|
||||
context->wait_ok = 0;
|
||||
switch (context->state){
|
||||
case HFP_W4_NOTIFY_ON_CODECS:
|
||||
context->state = HFP_RETRIEVE_INDICATORS;
|
||||
break;
|
||||
case HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE:
|
||||
context->state = HFP_RETRIEVE_CAN_HOLD_CALL;
|
||||
break;
|
||||
case HFP_W4_LIST_GENERIC_STATUS_INDICATORS:
|
||||
context->state = HFP_RETRIEVE_GENERIC_STATUS_INDICATORS;
|
||||
break;
|
||||
case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
|
||||
context->state = HFP_ACTIVE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
// printf("context->command %d == %d OK \n", context->command, HFP_CMD_OK);
|
||||
|
||||
if (context->command == HFP_CMD_OK){
|
||||
context->wait_ok = 0;
|
||||
switch (context->state){
|
||||
case HFP_W4_NOTIFY_ON_CODECS:
|
||||
printf("switch on OK: HFP_RETRIEVE_INDICATORS\n");
|
||||
context->state = HFP_RETRIEVE_INDICATORS;
|
||||
break;
|
||||
case HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE:
|
||||
printf("switch on OK: HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE\n");
|
||||
context->state = HFP_RETRIEVE_CAN_HOLD_CALL;
|
||||
break;
|
||||
case HFP_W4_LIST_GENERIC_STATUS_INDICATORS:
|
||||
printf("switch on OK: HFP_W4_LIST_GENERIC_STATUS_INDICATORS\n");
|
||||
context->state = HFP_RETRIEVE_GENERIC_STATUS_INDICATORS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (wait_for_more_data(context) && pos < size){
|
||||
@ -460,43 +476,28 @@ static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8
|
||||
}
|
||||
if (wait_for_more_data(context)) return;
|
||||
|
||||
switch (context->cmd_state){
|
||||
case HFP_CMD_SUPPORTED_FEATURES:
|
||||
switch (context->state){
|
||||
case HFP_W4_EXCHANGE_SUPPORTED_FEATURES:
|
||||
context->state = HFP_NOTIFY_ON_CODECS;
|
||||
break;
|
||||
case HFP_CMD_AVAILABLE_CODECS:
|
||||
context->state = HFP_RETRIEVE_INDICATORS;
|
||||
|
||||
case HFP_W4_RETRIEVE_INDICATORS:
|
||||
context->remote_indicators_status = 0;
|
||||
context->state = HFP_RETRIEVE_INDICATORS_STATUS;
|
||||
break;
|
||||
case HFP_CMD_INDICATOR:
|
||||
switch (context->state){
|
||||
case HFP_W4_RETRIEVE_INDICATORS:
|
||||
context->remote_indicators_status = 0;
|
||||
context->state = HFP_RETRIEVE_INDICATORS_STATUS;
|
||||
break;
|
||||
case HFP_W4_RETRIEVE_INDICATORS_STATUS:
|
||||
context->state = HFP_ENABLE_INDICATORS_STATUS_UPDATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case HFP_W4_RETRIEVE_INDICATORS_STATUS:
|
||||
context->state = HFP_ENABLE_INDICATORS_STATUS_UPDATE;
|
||||
break;
|
||||
case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE:
|
||||
context->state = HFP_RETRIEVE_CAN_HOLD_CALL;
|
||||
break;
|
||||
case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES:
|
||||
|
||||
case HFP_W4_RETRIEVE_CAN_HOLD_CALL:
|
||||
context->state = HFP_LIST_GENERIC_STATUS_INDICATORS;
|
||||
break;
|
||||
case HFP_CMD_GENERIC_STATUS_INDICATOR:
|
||||
switch (context->state){
|
||||
case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS:
|
||||
context->remote_hf_indicators_status = 0;
|
||||
context->state = HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
|
||||
break;
|
||||
case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS:
|
||||
context->remote_hf_indicators_status = 0;
|
||||
context->state = HFP_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
|
||||
break;
|
||||
case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS:
|
||||
printf("Supported initial state generic status indicators \n");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
Loading…
x
Reference in New Issue
Block a user