void hfp_parse(hfp_connection_t * context, uint8_t byte){ int value; // TODO: handle space inside word if (byte == ' ' && context->parser_state > HFP_PARSER_CMD_HEADER) return; if (!hfp_parser_found_separator(context, byte)){ hfp_parser_store_byte(context, byte); return; } if (hfp_parser_is_end_of_line(byte)) { if (hfp_parser_is_buffer_empty(context)){ context->parser_state = HFP_PARSER_CMD_HEADER; } } if (hfp_parser_is_buffer_empty(context)) return; switch (context->parser_state){ case HFP_PARSER_CMD_HEADER: // header // printf(" parse header 1 \n"); if (byte == '='){ context->keep_separator = 1; hfp_parser_store_byte(context, byte); return; } if (byte == '?'){ context->keep_separator = 0; hfp_parser_store_byte(context, byte); return; } // printf(" parse header 2 %s, keep separator $ %d\n", context->line_buffer, context->keep_separator); if (hfp_parser_is_end_of_header(byte) || context->keep_separator == 1){ // printf(" parse header 3 %s, keep separator $ %d\n", context->line_buffer, context->keep_separator); process_command(context); } break; case HFP_PARSER_CMD_SEQUENCE: // parse comma separated sequence, ignore breacktes switch (context->command){ case HFP_CMD_CONFIRM_COMMON_CODEC: context->remote_codec_received = atoi((char*)context->line_buffer); break; case HFP_CMD_SUPPORTED_FEATURES: context->remote_supported_features = atoi((char*)context->line_buffer); printf("Parsed supported feature %d\n", context->remote_supported_features); break; case HFP_CMD_AVAILABLE_CODECS: printf("Parsed codec %s\n", context->line_buffer); context->remote_codecs[context->parser_item_index] = (uint16_t)atoi((char*)context->line_buffer); context->parser_item_index++; context->remote_codecs_nr = context->parser_item_index; break; case HFP_CMD_INDICATOR: if (context->retrieve_ag_indicators == 1){ strcpy((char *)context->ag_indicators[context->parser_item_index].name, (char *)context->line_buffer); context->ag_indicators[context->parser_item_index].index = context->parser_item_index+1; printf("Indicator %d: %s (", context->ag_indicators_nr+1, context->line_buffer); } if (context->retrieve_ag_indicators_status == 1){ printf("Parsed Indicator %d with status: %s\n", context->parser_item_index+1, context->line_buffer); context->ag_indicators[context->parser_item_index].status = atoi((char *) context->line_buffer); context->parser_item_index++; break; } break; case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE: context->parser_item_index++; if (context->parser_item_index != 4) break; printf("Parsed Enable indicators: %s\n", context->line_buffer); value = atoi((char *)&context->line_buffer[0]); context->enable_status_update_for_ag_indicators = (uint8_t) value; break; case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES: printf("Parsed Support call hold: %s\n", context->line_buffer); if (context->line_size > 2 ) break; strcpy((char *)context->remote_call_services[context->remote_call_services_nr].name, (char *)context->line_buffer); context->remote_call_services_nr++; break; case HFP_CMD_GENERIC_STATUS_INDICATOR: printf("parser HFP_CMD_GENERIC_STATUS_INDICATOR 1 (%d, %d, %d)\n", context->list_generic_status_indicators, context->retrieve_generic_status_indicators, context->retrieve_generic_status_indicators_state); if (context->retrieve_generic_status_indicators == 1 || context->list_generic_status_indicators == 1){ printf("Parsed Generic status indicator: %s\n", context->line_buffer); context->generic_status_indicators[context->parser_item_index].uuid = (uint16_t)atoi((char*)context->line_buffer); context->parser_item_index++; context->generic_status_indicators_nr = context->parser_item_index; break; } printf("parser HFP_CMD_GENERIC_STATUS_INDICATOR 2\n"); if (context->retrieve_generic_status_indicators_state == 1){ // HF parses inital AG gen. ind. state printf("Parsed List generic status indicator %s state: ", context->line_buffer); context->parser_item_index = (uint8_t)atoi((char*)context->line_buffer); break; } break; case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE: // AG parses new gen. ind. state printf("Parsed Enable ag indicator state: %s\n", context->line_buffer); value = atoi((char *)&context->line_buffer[0]); if (!context->ag_indicators[context->parser_item_index].mandatory){ context->ag_indicators[context->parser_item_index].enabled = value; } context->parser_item_index++; break; case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: // indicators are indexed starting with 1 context->parser_item_index = atoi((char *)&context->line_buffer[0]) - 1; printf("Parsed status of the AG indicator %d, status ", context->parser_item_index); break; case HFP_CMD_QUERY_OPERATOR_SELECTION: 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; case HFP_CMD_ERROR: break; case HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR: context->extended_audio_gateway_error = (uint8_t)atoi((char*)context->line_buffer); break; case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR: context->enable_extended_audio_gateway_error_report = (uint8_t)atoi((char*)context->line_buffer); context->send_ok = 1; context->extended_audio_gateway_error = 0; break; default: break; } break; case HFP_PARSER_SECOND_ITEM: 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; case HFP_CMD_GENERIC_STATUS_INDICATOR: context->generic_status_indicators[context->parser_item_index].state = (uint8_t)atoi((char*)context->line_buffer); break; case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: context->ag_indicators[context->parser_item_index].status = (uint8_t)atoi((char*)context->line_buffer); context->ag_indicators[context->parser_item_index].status_changed = 1; break; case HFP_CMD_INDICATOR: if (context->retrieve_ag_indicators == 1){ context->ag_indicators[context->parser_item_index].min_range = atoi((char *)context->line_buffer); printf("%s, ", context->line_buffer); } break; default: break; } break; case HFP_PARSER_THIRD_ITEM: 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; case HFP_CMD_INDICATOR: if (context->retrieve_ag_indicators == 1){ context->ag_indicators[context->parser_item_index].max_range = atoi((char *)context->line_buffer); context->parser_item_index++; context->ag_indicators_nr = context->parser_item_index; printf("%s)\n", context->line_buffer); } break; default: break; } break; } hfp_parser_next_state(context, byte); }
void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree){ int value; // TODO: handle space inside word if (byte == ' ' && context->parser_state > HFP_PARSER_CMD_HEADER) return; if (!hfp_parser_found_separator(context, byte)){ hfp_parser_store_byte(context, byte); return; } if (hfp_parser_is_end_of_line(byte)) { if (hfp_parser_is_buffer_empty(context)){ context->parser_state = HFP_PARSER_CMD_HEADER; } } if (hfp_parser_is_buffer_empty(context)) return; switch (context->parser_state){ case HFP_PARSER_CMD_HEADER: // header if (byte == '='){ context->keep_separator = 1; hfp_parser_store_byte(context, byte); return; } if (byte == '?'){ context->keep_separator = 0; hfp_parser_store_byte(context, byte); return; } // printf(" parse header 2 %s, keep separator $ %d\n", context->line_buffer, context->keep_separator); if (hfp_parser_is_end_of_header(byte) || context->keep_separator == 1){ // printf(" parse header 3 %s, keep separator $ %d\n", context->line_buffer, context->keep_separator); char * line_buffer = (char *)context->line_buffer; context->command = parse_command(line_buffer, isHandsFree); /* resolve command name according to context */ if (context->command == HFP_CMD_UNKNOWN){ switch(context->state){ case HFP_W4_LIST_GENERIC_STATUS_INDICATORS: context->command = HFP_CMD_LIST_GENERIC_STATUS_INDICATORS; break; case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS: context->command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS; break; case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS: context->command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE; break; case HFP_W4_RETRIEVE_INDICATORS_STATUS: context->command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS; break; case HFP_W4_RETRIEVE_INDICATORS: context->command = HFP_CMD_RETRIEVE_AG_INDICATORS; break; default: break; } } } break; case HFP_PARSER_CMD_SEQUENCE: // parse comma separated sequence, ignore breacktes switch (context->command){ case HFP_CMD_HF_CONFIRMED_CODEC: context->codec_confirmed = atoi((char*)context->line_buffer); log_info("hfp parse HFP_CMD_HF_CONFIRMED_CODEC %d\n", context->codec_confirmed); break; case HFP_CMD_AG_SUGGESTED_CODEC: context->suggested_codec = atoi((char*)context->line_buffer); log_info("hfp parse HFP_CMD_AG_SUGGESTED_CODEC %d\n", context->suggested_codec); break; case HFP_CMD_SUPPORTED_FEATURES: context->remote_supported_features = atoi((char*)context->line_buffer); log_info("Parsed supported feature %d\n", context->remote_supported_features); break; case HFP_CMD_AVAILABLE_CODECS: log_info("Parsed codec %s\n", context->line_buffer); context->remote_codecs[context->parser_item_index] = (uint16_t)atoi((char*)context->line_buffer); context->parser_item_index++; context->remote_codecs_nr = context->parser_item_index; break; case HFP_CMD_RETRIEVE_AG_INDICATORS: strcpy((char *)context->ag_indicators[context->parser_item_index].name, (char *)context->line_buffer); context->ag_indicators[context->parser_item_index].index = context->parser_item_index+1; log_info("Indicator %d: %s (", context->ag_indicators_nr+1, context->line_buffer); break; case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS: log_info("Parsed Indicator %d with status: %s\n", context->parser_item_index+1, context->line_buffer); context->ag_indicators[context->parser_item_index].status = atoi((char *) context->line_buffer); context->parser_item_index++; break; case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE: context->parser_item_index++; if (context->parser_item_index != 4) break; log_info("Parsed Enable indicators: %s\n", context->line_buffer); value = atoi((char *)&context->line_buffer[0]); context->enable_status_update_for_ag_indicators = (uint8_t) value; break; case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES: log_info("Parsed Support call hold: %s\n", context->line_buffer); if (context->line_size > 2 ) break; strcpy((char *)context->remote_call_services[context->remote_call_services_nr].name, (char *)context->line_buffer); context->remote_call_services_nr++; break; case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS: case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS: log_info("Parsed Generic status indicator: %s\n", context->line_buffer); context->generic_status_indicators[context->parser_item_index].uuid = (uint16_t)atoi((char*)context->line_buffer); context->parser_item_index++; context->generic_status_indicators_nr = context->parser_item_index; break; case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: // HF parses inital AG gen. ind. state log_info("Parsed List generic status indicator %s state: ", context->line_buffer); context->parser_item_index = (uint8_t)atoi((char*)context->line_buffer); break; case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE: // AG parses new gen. ind. state log_info("Parsed Enable ag indicator state: %s\n", context->line_buffer); value = atoi((char *)&context->line_buffer[0]); if (!context->ag_indicators[context->parser_item_index].mandatory){ context->ag_indicators[context->parser_item_index].enabled = value; } context->parser_item_index++; break; case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: // indicators are indexed starting with 1 context->parser_item_index = atoi((char *)&context->line_buffer[0]) - 1; printf("Parsed status of the AG indicator %d, status ", context->parser_item_index); break; case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: context->network_operator.mode = atoi((char *)&context->line_buffer[0]); log_info("Parsed network operator mode: %d, ", context->network_operator.mode); break; case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: if (context->line_buffer[0] == '3'){ log_info("Parsed Set network operator format : %s, ", context->line_buffer); break; } // TODO emit ERROR, wrong format log_info("ERROR Set network operator format: index %s not supported\n", context->line_buffer); break; case HFP_CMD_ERROR: break; case HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR: context->extended_audio_gateway_error = (uint8_t)atoi((char*)context->line_buffer); break; case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR: context->enable_extended_audio_gateway_error_report = (uint8_t)atoi((char*)context->line_buffer); context->ok_pending = 1; context->extended_audio_gateway_error = 0; break; default: break; } break; case HFP_PARSER_SECOND_ITEM: switch (context->command){ case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: printf("format %s, ", context->line_buffer); context->network_operator.format = atoi((char *)&context->line_buffer[0]); break; case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: printf("format %s \n", context->line_buffer); context->network_operator.format = atoi((char *)&context->line_buffer[0]); break; case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS: case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS: case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: context->generic_status_indicators[context->parser_item_index].state = (uint8_t)atoi((char*)context->line_buffer); break; case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: context->ag_indicators[context->parser_item_index].status = (uint8_t)atoi((char*)context->line_buffer); printf("%d \n", context->ag_indicators[context->parser_item_index].status); context->ag_indicators[context->parser_item_index].status_changed = 1; break; case HFP_CMD_RETRIEVE_AG_INDICATORS: context->ag_indicators[context->parser_item_index].min_range = atoi((char *)context->line_buffer); log_info("%s, ", context->line_buffer); break; default: break; } break; case HFP_PARSER_THIRD_ITEM: switch (context->command){ case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: strcpy(context->network_operator.name, (char *)context->line_buffer); log_info("name %s\n", context->line_buffer); break; case HFP_CMD_RETRIEVE_AG_INDICATORS: context->ag_indicators[context->parser_item_index].max_range = atoi((char *)context->line_buffer); context->parser_item_index++; context->ag_indicators_nr = context->parser_item_index; log_info("%s)\n", context->line_buffer); break; default: break; } break; } hfp_parser_next_state(context, byte); }