From b5b7d6dda38358b2be169e2302c73a425a68fba5 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Fri, 14 Aug 2015 14:19:31 +0200 Subject: [PATCH] hfp: start rewrite parser --- src/hfp.c | 146 +++++++++++++++++++++++----------- src/hfp.h | 3 +- src/hfp_ag.c | 14 ++-- src/hfp_hf.c | 9 ++- test/hfp/hfp_ag_parser_test.c | 41 ++++++++-- test/hfp/hfp_hf_parser_test.c | 14 ++++ 6 files changed, 164 insertions(+), 63 deletions(-) diff --git a/src/hfp.c b/src/hfp.c index 621988117..d51020fc3 100644 --- a/src/hfp.c +++ b/src/hfp.c @@ -497,8 +497,53 @@ uint32_t fromBinary(char *s) { return (uint32_t) strtol(s, NULL, 2); } +static void hfp_parser_write_buffer(hfp_connection_t * context, uint8_t byte){ + // TODO: add limit + context->line_buffer[context->line_size++] = byte; + context->line_buffer[context->line_size] = 0; +} + +static int hfp_parser_reached_end_of_line(uint8_t byte){ + return byte == '\n' || byte == '\r'; +} + +static int hfp_parser_reached_sequence_separator(uint8_t byte){ + return byte == ','; +} + +static int hfp_parser_item_done(uint8_t byte){ + return byte == ',' || byte == '\n' || byte == '\r'; +} + +static void hfp_parser_next_state(hfp_connection_t * context, uint8_t byte){ + context->line_size = 0; + if (hfp_parser_reached_end_of_line(byte)){ + context->parser_item_index = 0; + context->parser_state = HFP_PARSER_CMD_HEADER; + return; + } + switch (context->parser_state){ + case HFP_PARSER_CMD_HEADER: + case HFP_PARSER_CMD_INDICATOR_NAME: + case HFP_PARSER_CMD_INDICATOR_MIN_RANGE: + case HFP_PARSER_SECOND_ITEM: + context->parser_state = (hfp_parser_state_t)((int)context->parser_state + 1); + break; + case HFP_PARSER_CMD_INDICATOR_MAX_RANGE: + case HFP_PARSER_CMD_INDICATOR_STATUS: + context->parser_state = HFP_PARSER_CMD_SEQUENCE; + break; + case HFP_PARSER_CMD_SEQUENCE: + break; + case HFP_PARSER_THIRD_ITEM: + context->parser_state = HFP_PARSER_CMD_HEADER; + + } +} + void hfp_parse(hfp_connection_t * context, uint8_t byte){ int value; + int reached_end = 0; context->line_buffer[context->line_size] = 0; if (byte == ' ') return; @@ -546,8 +591,9 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){ context->parser_item_index = 0; return; } - - context->line_buffer[context->line_size++] = byte; + if (byte != '='){ + context->line_buffer[context->line_size++] = byte; + } break; case HFP_PARSER_CMD_SEQUENCE: // parse comma separated sequence, ignore breacktes @@ -640,28 +686,25 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){ printf("Parsed status of the AG indicator %d, status ", context->parser_item_index); 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->parser_state = HFP_PARSER_SECOND_ITEM; context->line_size = 0; - context->parser_state = HFP_PARSER_CMD_NETWORK_OPERATOR; + + if (context->operator_name_format == 1){ + if (context->line_buffer[0] == '3'){ + printf("Parsed Set network operator format : %s, ", context->line_buffer); + break; + } + // TODO emit ERROR, wrong format + printf("ERROR Set network operator format: index %s not supported\n", context->line_buffer); + break; + } + + if (context->operator_name == 1) { + context->network_operator.mode = atoi((char *)&context->line_buffer[0]); + printf("Parsed network operator mode: %d, ", context->network_operator.mode); + break; + } + break; default: @@ -678,35 +721,46 @@ 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; + case HFP_PARSER_SECOND_ITEM: + if (!hfp_parser_item_done(byte)){ + hfp_parser_write_buffer(context, byte); 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; + switch (context->command){ + case HFP_CMD_QUERY_OPERATOR_SELECTION: + if (context->operator_name_format == 1) { + printf("format %s \n", context->line_buffer); + context->network_operator.format = atoi((char *)&context->line_buffer[0]); + break; + } + if (context->operator_name == 1){ + printf("format %s, ", context->line_buffer); + context->network_operator.format = atoi((char *)&context->line_buffer[0]); + } + break; + default: + break; + } + hfp_parser_next_state(context, byte); + break; + + case HFP_PARSER_THIRD_ITEM: + if (!hfp_parser_item_done(byte)){ + hfp_parser_write_buffer(context, byte); break; } - if (context->line_size < 16){ - context->line_buffer[context->line_size++] = byte; + switch (context->command){ + case HFP_CMD_QUERY_OPERATOR_SELECTION: + if (context->operator_name == 1){ + strcpy(context->network_operator.name, (char *)context->line_buffer); + printf("name %s\n", context->line_buffer); + } + break; + default: + break; } + hfp_parser_next_state(context, byte); break; case HFP_PARSER_CMD_INDICATOR_STATUS: diff --git a/src/hfp.h b/src/hfp.h index f80094282..a6a926999 100644 --- a/src/hfp.h +++ b/src/hfp.h @@ -143,7 +143,8 @@ typedef enum { HFP_PARSER_CMD_INDICATOR_MIN_RANGE, HFP_PARSER_CMD_INDICATOR_MAX_RANGE, HFP_PARSER_CMD_INDICATOR_STATUS, - HFP_PARSER_CMD_NETWORK_OPERATOR + HFP_PARSER_SECOND_ITEM, + HFP_PARSER_THIRD_ITEM } hfp_parser_state_t; diff --git a/src/hfp_ag.c b/src/hfp_ag.c index a07c2c9d2..70f759d8b 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -80,6 +80,7 @@ int get_hfp_generic_status_indicators_nr(); void set_hfp_generic_status_indicators(hfp_generic_status_indicator_t * indicators, int indicator_nr); hfp_ag_indicator_t * get_hfp_ag_indicators(hfp_connection_t * context){ + // TODO: save only value, and value changed in the context? if (context->ag_indicators_nr != hfp_ag_indicators_nr){ context->ag_indicators_nr = hfp_ag_indicators_nr; memcpy(context->ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); @@ -94,6 +95,7 @@ int get_hfp_ag_indicators_nr(hfp_connection_t * context){ } return context->ag_indicators_nr; } + void set_hfp_ag_indicators(hfp_ag_indicator_t * indicators, int indicator_nr){ memcpy(hfp_ag_indicators, indicators, indicator_nr * sizeof(hfp_ag_indicator_t)); hfp_ag_indicators_nr = indicator_nr; @@ -383,16 +385,14 @@ 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 = 0; + 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 = 0; - context->operator_name = 1; - } + context->operator_name = 0; + } return; } } diff --git a/src/hfp_hf.c b/src/hfp_hf.c index 6e3119093..fe9259ed7 100644 --- a/src/hfp_hf.c +++ b/src/hfp_hf.c @@ -359,10 +359,17 @@ void update_command(hfp_connection_t * context){ return; } - if (strncmp((char *)context->line_buffer, HFP_TRANSFER_AG_INDICATOR_STATUS, strlen(HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS)) == 0){ + if (strncmp((char *)context->line_buffer, HFP_TRANSFER_AG_INDICATOR_STATUS, strlen(HFP_TRANSFER_AG_INDICATOR_STATUS)) == 0){ context->command = HFP_CMD_TRANSFER_AG_INDICATOR_STATUS; return; } + + if (strncmp((char *)context->line_buffer, HFP_QUERY_OPERATOR_SELECTION, strlen(HFP_QUERY_OPERATOR_SELECTION)) == 0){ + context->command = HFP_CMD_QUERY_OPERATOR_SELECTION; + context->operator_name = 1; + context->operator_name_format = 0; + return; + } } diff --git a/test/hfp/hfp_ag_parser_test.c b/test/hfp/hfp_ag_parser_test.c index 5ca0c3454..4dd89ab23 100644 --- a/test/hfp/hfp_ag_parser_test.c +++ b/test/hfp/hfp_ag_parser_test.c @@ -50,8 +50,8 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte); hfp_generic_status_indicator_t * get_hfp_generic_status_indicators(); void set_hfp_generic_status_indicators(hfp_generic_status_indicator_t * indicators, int indicator_nr); -hfp_ag_indicator_t * get_hfp_ag_indicators(); -int get_hfp_ag_indicators_nr(); +hfp_ag_indicator_t * get_hfp_ag_indicators(hfp_connection_t * context); +int get_hfp_ag_indicators_nr(hfp_connection_t * context); void set_hfp_ag_indicators(hfp_ag_indicator_t * indicators, int indicator_nr); static int hf_indicators_nr = 3; @@ -149,8 +149,8 @@ TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE){ memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - CHECK_EQUAL(get_hfp_ag_indicators()[pos].index, hfp_ag_indicators[pos].index); - CHECK_EQUAL(get_hfp_ag_indicators()[pos].enabled, hfp_ag_indicators[pos].enabled); + CHECK_EQUAL(get_hfp_ag_indicators(&context)[pos].index, hfp_ag_indicators[pos].index); + CHECK_EQUAL(get_hfp_ag_indicators(&context)[pos].enabled, hfp_ag_indicators[pos].enabled); CHECK_EQUAL(context.ag_indicators[pos].index, hfp_ag_indicators[pos].index); CHECK_EQUAL(context.ag_indicators[pos].enabled, hfp_ag_indicators[pos].enabled); } @@ -163,11 +163,11 @@ TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE){ CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - if (get_hfp_ag_indicators()[pos].mandatory){ - CHECK_EQUAL(get_hfp_ag_indicators()[pos].enabled, 1); + if (get_hfp_ag_indicators(&context)[pos].mandatory){ + CHECK_EQUAL(get_hfp_ag_indicators(&context)[pos].enabled, 1); CHECK_EQUAL(context.ag_indicators[pos].enabled, 1); } else { - CHECK_EQUAL(get_hfp_ag_indicators()[pos].enabled, 0); + CHECK_EQUAL(get_hfp_ag_indicators(&context)[pos].enabled, 0); CHECK_EQUAL(context.ag_indicators[pos].enabled, 0); } } @@ -181,11 +181,36 @@ TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE){ // CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); // for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - // CHECK_EQUAL(get_hfp_ag_indicators()[pos].enabled, 1); + // CHECK_EQUAL(get_hfp_ag_indicators(&context)[pos].enabled, 1); // CHECK_EQUAL(context.ag_indicators[pos].enabled, 1); // } } +TEST(HFPParser, HFP_AG_HF_QUERY_OPERATOR_SELECTION){ + context.network_operator.format = 0xff; + sprintf(packet, "\r\nAT%s=3,0\r\n", HFP_QUERY_OPERATOR_SELECTION); + + for (pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos]); + } + CHECK_EQUAL(context.operator_name_format, 1); + CHECK_EQUAL(context.operator_name, 0); + CHECK_EQUAL(context.operator_name_changed, 0); + + CHECK_EQUAL(HFP_CMD_QUERY_OPERATOR_SELECTION, context.command); + CHECK_EQUAL(context.network_operator.format, 0); + CHECK_EQUAL(context.network_operator.mode, 0); + + sprintf(packet, "\r\nAT%s?\r\n", HFP_QUERY_OPERATOR_SELECTION); + + for (pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos]); + } + CHECK_EQUAL(context.operator_name_format, 0); + CHECK_EQUAL(context.operator_name, 0); + CHECK_EQUAL(context.operator_name_changed, 0); +} + int main (int argc, const char * argv[]){ return CommandLineTestRunner::RunAllTests(argc, argv); } diff --git a/test/hfp/hfp_hf_parser_test.c b/test/hfp/hfp_hf_parser_test.c index 5c09389da..f98023ff9 100644 --- a/test/hfp/hfp_hf_parser_test.c +++ b/test/hfp/hfp_hf_parser_test.c @@ -207,6 +207,20 @@ TEST(HFPParser, HFP_HF_AG_INDICATOR_STATUS_UPDATE){ CHECK_EQUAL(context.ag_indicators[index - 1].status, status); } +TEST(HFPParser, HFP_HF_AG_QUERY_OPERATOR_SELECTION){ + sprintf(packet, "\r\n%s=1,0,sunrise\r\n", HFP_QUERY_OPERATOR_SELECTION); + + for (pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos]); + } + + CHECK_EQUAL(context.command, HFP_CMD_QUERY_OPERATOR_SELECTION); + CHECK_EQUAL(context.operator_name_format, 0); + CHECK_EQUAL(context.operator_name, 1); + CHECK_EQUAL(context.operator_name_changed, 0); + CHECK_EQUAL( strcmp("sunrise", context.network_operator.name), 0); +} + int main (int argc, const char * argv[]){ return CommandLineTestRunner::RunAllTests(argc, argv); }