diff --git a/src/hfp.c b/src/hfp.c index f4df5713e..d5f64e463 100644 --- a/src/hfp.c +++ b/src/hfp.c @@ -93,9 +93,25 @@ static const char * hfp_ag_features[] = { "Reserved for future definition" }; +static int hfp_hf_indicators_nr = 0; +static hfp_generic_status_indicators_t hfp_hf_indicators[HFP_MAX_NUM_HF_INDICATORS]; static linked_list_t hfp_connections = NULL; +hfp_generic_status_indicators_t * get_hfp_generic_status_indicators(){ + return (hfp_generic_status_indicators_t *) &hfp_hf_indicators; +} + +int get_hfp_generic_status_indicators_nr(){ + return hfp_hf_indicators_nr; +} + +void set_hfp_generic_status_indicators(hfp_generic_status_indicators_t * indicators, int indicator_nr){ + if (indicator_nr > HFP_MAX_NUM_HF_INDICATORS) return; + hfp_hf_indicators_nr = indicator_nr; + memcpy(hfp_hf_indicators, indicators, indicator_nr * sizeof(hfp_generic_status_indicators_t)); +} + const char * hfp_hf_feature(int index){ if (index > HFP_HF_FEATURES_SIZE){ return hfp_hf_features[HFP_HF_FEATURES_SIZE]; @@ -237,6 +253,9 @@ static hfp_connection_t * create_hfp_connection_context(){ context->enable_status_update_for_ag_indicators = 0xFF; context->change_enable_status_update_for_individual_ag_indicators = 0xFF; + context->generic_status_indicators_nr = hfp_hf_indicators_nr; + memcpy(context->generic_status_indicators, hfp_hf_indicators, hfp_hf_indicators_nr * sizeof(hfp_generic_status_indicators_t)); + linked_list_add(&hfp_connections, (linked_item_t*)context); return context; } @@ -469,7 +488,7 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){ if (byte == ' ') return; if (context->line_size == 0 && (byte == '\n' || byte == '\r')) return; if ((byte == '\n' || byte == '\r') && (context->parser_state > HFP_PARSER_CMD_SEQUENCE && context->parser_state != HFP_PARSER_CMD_INITITAL_STATE_GENERIC_STATUS_INDICATORS) )return; - //printf("%c", byte); + switch (context->parser_state){ case HFP_PARSER_CMD_HEADER: // header if (byte == ':' || byte == '='){ @@ -512,7 +531,7 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){ context->remote_supported_features = store_bit(context->remote_supported_features,15-i,1); } } - // printf("Received supported feature %d\n", context->remote_supported_features); + printf("Received supported feature %d\n", context->remote_supported_features); context->parser_state = HFP_PARSER_CMD_HEADER; break; case HFP_CMD_AVAILABLE_CODECS: @@ -530,13 +549,10 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){ printf("Enable indicators: %s\n", context->line_buffer); value = atoi((char *)&context->line_buffer[0]); context->enable_status_update_for_ag_indicators = (uint8_t) value; + } else { + context->parser_item_index++; } break; - case HFP_CMD_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE: - value = atoi((char *)&context->line_buffer[0]); - printf("Indicator %d status: %d\n", context->ag_indicators_nr, value); - store_bit(context->ag_indicators_status_update_bitmap, context->ag_indicators_nr, (uint8_t)value); - break; case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES: // printf("Support call hold: %s\n", context->line_buffer); if (context->line_size > 2 ) break; @@ -544,14 +560,34 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){ context->remote_call_services_nr++; break; case HFP_CMD_GENERIC_STATUS_INDICATOR: + context->generic_status_indicators[context->generic_status_indicators_nr].uuid = (uint16_t)atoi((char*)context->line_buffer); context->generic_status_indicators_nr++; break; case HFP_CMD_GENERIC_STATUS_INDICATOR_STATE: + // HF parses inital AG gen. ind. state printf("HFP_CMD_GENERIC_STATUS_INDICATOR_STATE %s, %d\n", context->line_buffer, context->command); context->parser_state = HFP_PARSER_CMD_INITITAL_STATE_GENERIC_STATUS_INDICATORS; context->generic_status_indicator_state_index = (uint8_t)atoi((char*)context->line_buffer); break; + case HFP_CMD_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE: + // AG parses new gen. ind. state + value = atoi((char *)&context->line_buffer[0]); + context->generic_status_indicator_state_index = 255; + // TODO: match on uuid or index? + for (i = 0; i < hfp_hf_indicators_nr; i++){ + if (hfp_hf_indicators[i].uuid == value ){ + context->generic_status_indicator_state_index = i; + continue; + } + } + if (context->generic_status_indicator_state_index >= 0 && context->generic_status_indicator_state_index < hfp_hf_indicators_nr){ + printf("Set state of the indicator wiht index %d, ", context->generic_status_indicator_state_index); + context->parser_state = HFP_PARSER_CMD_INITITAL_STATE_GENERIC_STATUS_INDICATORS; + break; + } + context->parser_state = HFP_PARSER_CMD_HEADER; + break; default: break; } @@ -573,21 +609,18 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte){ break; case HFP_PARSER_CMD_INITITAL_STATE_GENERIC_STATUS_INDICATORS: context->line_buffer[context->line_size] = 0; - printf("HFP_PARSER_CMD_INITITAL_STATE_GENERIC_STATUS_INDICATORS 1 %s\n", context->line_buffer); if (byte == ',') break; - printf("HFP_PARSER_CMD_INITITAL_STATE_GENERIC_STATUS_INDICATORS 2 %s\n", context->line_buffer); if (byte == '\n' || byte == '\r'){ - printf("HFP_PARSER_CMD_INITITAL_STATE_GENERIC_STATUS_INDICATORS 4%s\n", context->line_buffer); - context->line_buffer[context->line_size] = 0; context->line_size = 0; context->parser_state = HFP_PARSER_CMD_HEADER; - printf("status %s [0-dissabled, 1-enabled]\n", context->line_buffer); + printf("to %s [0-dissabled, 1-enabled]\n", context->line_buffer); + // HF stores inital AG gen. ind. state + // AG stores new gen. ind. state context->generic_status_indicators[context->generic_status_indicator_state_index].state = (uint8_t)atoi((char*)context->line_buffer); break; } context->line_buffer[context->line_size++] = byte; - printf("HFP_PARSER_CMD_INITITAL_STATE_GENERIC_STATUS_INDICATORS 3 %s\n", context->line_buffer); break; case HFP_PARSER_CMD_INDICATOR_NAME: // parse indicator name diff --git a/src/hfp.h b/src/hfp.h index d90d6d803..0a899ca75 100644 --- a/src/hfp.h +++ b/src/hfp.h @@ -127,7 +127,7 @@ typedef enum { HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, HFP_CMD_LIST_GENERIC_STATUS_INDICATOR, HFP_CMD_GENERIC_STATUS_INDICATOR, // 10 - HFP_CMD_GENERIC_STATUS_INDICATOR_STATE, + HFP_CMD_GENERIC_STATUS_INDICATOR_STATE } hfp_command_t; typedef enum { @@ -184,8 +184,7 @@ typedef void (*hfp_callback_t)(uint8_t * event, uint16_t event_size); typedef struct{ uint16_t uuid; - uint8_t state; - uint8_t initial_state; + uint8_t state; // enabled } hfp_generic_status_indicators_t; typedef struct{ @@ -194,6 +193,7 @@ typedef struct{ uint8_t min_range; uint8_t max_range; uint8_t status; + uint8_t enabled; } hfp_ag_indicator_t; typedef struct{ @@ -224,15 +224,16 @@ typedef struct hfp_connection { hfp_ag_indicator_t ag_indicators[HFP_MAX_INDICATOR_DESC_SIZE]; int remote_call_services_nr; hfp_call_service_t remote_call_services[HFP_MAX_INDICATOR_DESC_SIZE]; + int generic_status_indicators_nr; hfp_generic_status_indicators_t generic_status_indicators[HFP_MAX_INDICATOR_DESC_SIZE]; uint8_t generic_status_indicator_state_index; - + uint8_t enable_status_update_for_ag_indicators; + // TODO: put in a bitmap // 0 = deactivate, 1 = activate, 0xff = do nothing uint8_t wait_ok; hfp_command_t sent_command; - uint8_t enable_status_update_for_ag_indicators; uint8_t change_enable_status_update_for_individual_ag_indicators; uint32_t ag_indicators_status_update_bitmap; diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 09b64918c..a37012bdb 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -66,9 +66,6 @@ static uint16_t hfp_supported_features = HFP_DEFAULT_AG_SUPPORTED_FEATURES; static uint8_t hfp_codecs_nr = 0; static uint8_t hfp_codecs[HFP_MAX_NUM_CODECS]; -static uint8_t hfp_hf_indicators_nr = 0; -static hfp_generic_status_indicators_t hfp_hf_indicators[HFP_MAX_NUM_HF_INDICATORS]; - static int hfp_ag_indicators_nr = 0; static hfp_ag_indicator_t hfp_ag_indicators[HFP_MAX_NUM_AG_INDICATORS]; @@ -78,6 +75,24 @@ static hfp_callback_t hfp_callback; static void packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +hfp_generic_status_indicators_t * get_hfp_generic_status_indicators(); +int get_hfp_generic_status_indicators_nr(); +void set_hfp_generic_status_indicators(hfp_generic_status_indicators_t * indicators, int indicator_nr); + +static void set_ag_indicators(hfp_ag_indicator_t * indicators, int indicator_nr){ + int i; + if (indicator_nr > HFP_MAX_NUM_AG_INDICATORS) return; + for (i = 0; i +#include +#include +#include + +#include "CppUTest/TestHarness.h" +#include "CppUTest/CommandLineTestRunner.h" + +#include "hfp.h" + +void hfp_parse(hfp_connection_t * context, uint8_t byte); +hfp_generic_status_indicators_t * get_hfp_generic_status_indicators(); +void set_hfp_generic_status_indicators(hfp_generic_status_indicators_t * indicators, int indicator_nr); + + +static int hf_indicators_nr = 2; +static hfp_generic_status_indicators_t hf_indicators[] = { + {1, 1}, + {2, 1} +}; + +static hfp_connection_t context; + +TEST_GROUP(HFPParser){ + char packet[200]; + int pos; + int offset; + + void setup(void){ + context.parser_state = HFP_PARSER_CMD_HEADER; + context.parser_item_index = 0; + context.line_size = 0; + memset(packet,0, sizeof(packet)); + } +}; +/* +TEST(HFPParser, HFP_AG_SUPPORTED_FEATURES){ + sprintf(packet, "\r\nAT%s=0000001111101111\r\n", HFP_SUPPORTED_FEATURES); + for (pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos]); + } + CHECK_EQUAL(HFP_CMD_SUPPORTED_FEATURES, context.command); + CHECK_EQUAL(1007, context.remote_supported_features); +} + + +TEST(HFPParser, HFP_AG_AVAILABLE_CODECS){ + sprintf(packet, "\r\nAT%s=0,1,2\r\n", HFP_AVAILABLE_CODECS); + for (pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos]); + } + CHECK_EQUAL(HFP_CMD_AVAILABLE_CODECS, context.command); + CHECK_EQUAL(3, context.remote_codecs_nr); + for (pos = 0; pos < 3; pos++){ + CHECK_EQUAL(pos, context.remote_codecs[pos]); + } +} + +TEST(HFPParser, HFP_AG_GENERIC_STATUS_INDICATOR){ + sprintf(packet, "\r\nAT%s=0,1\r\n", HFP_GENERIC_STATUS_INDICATOR); + context.sent_command = HFP_CMD_GENERIC_STATUS_INDICATOR; + + for (pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos]); + } + + CHECK_EQUAL(HFP_CMD_GENERIC_STATUS_INDICATOR, context.command); + CHECK_EQUAL(2, context.generic_status_indicators_nr); + + for (pos = 0; pos < context.generic_status_indicators_nr; pos++){ + CHECK_EQUAL(pos, context.generic_status_indicators[pos].uuid); + } +} + +TEST(HFPParser, HFP_AG_ENABLE_INDICATOR_STATUS_UPDATE){ + sprintf(packet, "\r\nAT%s=3,0,0,1\r\n", HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS); + for (pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos]); + } + CHECK_EQUAL(HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE, context.command); + CHECK_EQUAL(1, context.enable_status_update_for_ag_indicators); +} +*/ +TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE){ + set_hfp_generic_status_indicators((hfp_generic_status_indicators_t *)&hf_indicators, hf_indicators_nr); + context.generic_status_indicators_nr = hf_indicators_nr; + memcpy(context.generic_status_indicators, hf_indicators, hf_indicators_nr * sizeof(hfp_generic_status_indicators_t)); + for (pos = 0; pos < hf_indicators_nr; pos++){ + CHECK_EQUAL(get_hfp_generic_status_indicators()[pos].uuid, hf_indicators[pos].uuid); + CHECK_EQUAL(get_hfp_generic_status_indicators()[pos].state, hf_indicators[pos].state); + CHECK_EQUAL(context.generic_status_indicators[pos].uuid, hf_indicators[pos].uuid); + CHECK_EQUAL(context.generic_status_indicators[pos].state, hf_indicators[pos].state); + } + int indicator_index; + for (indicator_index = 0; indicator_index < hf_indicators_nr; indicator_index++){ + sprintf(packet, "\r\nAT%s=%d,0\r\n", + HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS, + get_hfp_generic_status_indicators()[indicator_index].uuid); + for (pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos]); + } + } + CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE, context.command); + + for (pos = 0; pos < hf_indicators_nr; pos++){ + CHECK_EQUAL(get_hfp_generic_status_indicators()[pos].state, 1); + CHECK_EQUAL(context.generic_status_indicators[pos].state, 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 e5e407c96..24e12a308 100644 --- a/test/hfp/hfp_hf_parser_test.c +++ b/test/hfp/hfp_hf_parser_test.c @@ -65,17 +65,13 @@ TEST_GROUP(HFPParser){ int pos; int offset; - void parser_init(hfp_connection_t * context){ - context->parser_state = HFP_PARSER_CMD_HEADER; - context->parser_item_index = 0; - context->line_size = 0; - context->ag_indicators_nr = 0; - context->remote_codecs_nr = 0; - memset(packet,0, sizeof(packet)); - } - void setup(void){ - parser_init(&context); + context.parser_state = HFP_PARSER_CMD_HEADER; + context.parser_item_index = 0; + context.line_size = 0; + context.ag_indicators_nr = 0; + context.remote_codecs_nr = 0; + memset(packet,0, sizeof(packet)); } }; @@ -96,18 +92,6 @@ TEST(HFPParser, HFP_HF_SUPPORTED_FEATURES){ CHECK_EQUAL(1007, context.remote_supported_features); } -TEST(HFPParser, HFP_HF_AVAILABLE_CODECS){ - sprintf(packet, "\r\n%s:0,1,2\r\n", HFP_AVAILABLE_CODECS); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos]); - } - CHECK_EQUAL(HFP_CMD_AVAILABLE_CODECS, context.command); - CHECK_EQUAL(3, context.remote_codecs_nr); - for (pos = 0; pos < 3; pos++){ - CHECK_EQUAL(pos, context.remote_codecs[pos]); - } -} - TEST(HFPParser, HFP_HF_INDICATORS){ offset = 0; offset += snprintf(packet, sizeof(packet), "%s:", HFP_INDICATOR); @@ -196,12 +180,6 @@ TEST(HFPParser, HFP_HF_GENERIC_STATUS_INDICATOR_STATE){ CHECK_EQUAL(1, context.generic_status_indicators[0].state); } -// TEST(HFPParser, HFP_AG_ENABLE_INDICATOR_STATUS_UPDATE){ -// } - -// TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE){ -// } - int main (int argc, const char * argv[]){ return CommandLineTestRunner::RunAllTests(argc, argv); } diff --git a/test/pts/hfp_ag_test.c b/test/pts/hfp_ag_test.c index 277ee3af3..703018ee0 100644 --- a/test/pts/hfp_ag_test.c +++ b/test/pts/hfp_ag_test.c @@ -92,8 +92,8 @@ static char* call_hold_services[] = {"1", "1x", "2", "2x", "3"}; static int hf_indicators_nr = 2; static hfp_generic_status_indicators_t hf_indicators[] = { - {1, 1, 1}, - {2, 1, 1}, + {1, 1}, + {2, 1}, }; // prototypes