hfp: rewrite parser to handle single bytes

This commit is contained in:
Milanka Ringwald 2015-07-29 15:35:28 +02:00
parent f1ab900fb4
commit 67a9d233cd
3 changed files with 126 additions and 123 deletions

View File

@ -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;

View File

@ -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];

View File

@ -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;