hfp.c (5ebff8020d95919f5a4fa00a07ae0d456deae24b) | hfp.c (471dea41ab395d4c7fcbf32edf8a18b239742ccb) |
---|---|
1/* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 80 unchanged lines hidden (view full) --- 89 90static hfp_sdp_query_context_t hfp_sdp_query_context; 91static btstack_context_callback_registration_t hfp_sdp_query_request; 92 93 94 95 96 | 1/* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 80 unchanged lines hidden (view full) --- 89 90static hfp_sdp_query_context_t hfp_sdp_query_context; 91static btstack_context_callback_registration_t hfp_sdp_query_request; 92 93 94 95 96 |
97// custom commands 98static btstack_linked_list_t hfp_custom_commands_ag; |
|
97 98// prototypes 99static hfp_link_settings_t hfp_next_link_setting_for_connection(hfp_link_settings_t current_setting, hfp_connection_t * hfp_connection, uint8_t eSCO_S4_supported); 100static void parse_sequence(hfp_connection_t * context); 101 102static const char * hfp_hf_features[] = { 103 "EC and/or NR function", 104 "Three-way calling", --- 1036 unchanged lines hidden (view full) --- 1141 { "+VGS:", HFP_CMD_SET_SPEAKER_GAIN}, 1142 { "+VGS=", HFP_CMD_SET_SPEAKER_GAIN}, 1143 { "ERROR", HFP_CMD_ERROR}, 1144 { "NOP", HFP_CMD_NONE}, // dummy command used by unit tests 1145 { "OK", HFP_CMD_OK }, 1146 { "RING", HFP_CMD_RING }, 1147}; 1148 | 99 100// prototypes 101static hfp_link_settings_t hfp_next_link_setting_for_connection(hfp_link_settings_t current_setting, hfp_connection_t * hfp_connection, uint8_t eSCO_S4_supported); 102static void parse_sequence(hfp_connection_t * context); 103 104static const char * hfp_hf_features[] = { 105 "EC and/or NR function", 106 "Three-way calling", --- 1036 unchanged lines hidden (view full) --- 1143 { "+VGS:", HFP_CMD_SET_SPEAKER_GAIN}, 1144 { "+VGS=", HFP_CMD_SET_SPEAKER_GAIN}, 1145 { "ERROR", HFP_CMD_ERROR}, 1146 { "NOP", HFP_CMD_NONE}, // dummy command used by unit tests 1147 { "OK", HFP_CMD_OK }, 1148 { "RING", HFP_CMD_RING }, 1149}; 1150 |
1151static const hfp_custom_at_command_t * hfp_custom_command_lookup(const char * text){ 1152 btstack_linked_list_iterator_t it; 1153 btstack_linked_list_iterator_init(&it, &hfp_custom_commands_ag); 1154 while (btstack_linked_list_iterator_has_next(&it)) { 1155 hfp_custom_at_command_t *at_command = (hfp_custom_at_command_t *) btstack_linked_list_iterator_next(&it); 1156 int match = strcmp(text, at_command->command); 1157 if (match == 0) { 1158 return at_command; 1159 } 1160 } 1161 return NULL; 1162} 1163 |
|
1149static hfp_command_t parse_command(const char * line_buffer, int isHandsFree){ 1150 1151 // table lookup based on role 1152 uint16_t num_entries; 1153 hfp_command_entry_t * table; 1154 if (isHandsFree == 0){ 1155 table = hfp_ag_commmand_table; 1156 num_entries = sizeof(hfp_ag_commmand_table) / sizeof(hfp_command_entry_t); --- 22 unchanged lines hidden (view full) --- 1179 1180 // note: if parser in CMD_HEADER state would treats digits and maybe '+' as separator, match on "ATD" would work. 1181 // note: phone number is currently expected in line_buffer[3..] 1182 // prefix match on 'ATD', AG only 1183 if ((isHandsFree == 0) && (strncmp(line_buffer, HFP_CALL_PHONE_NUMBER, strlen(HFP_CALL_PHONE_NUMBER)) == 0)){ 1184 return HFP_CMD_CALL_PHONE_NUMBER; 1185 } 1186 | 1164static hfp_command_t parse_command(const char * line_buffer, int isHandsFree){ 1165 1166 // table lookup based on role 1167 uint16_t num_entries; 1168 hfp_command_entry_t * table; 1169 if (isHandsFree == 0){ 1170 table = hfp_ag_commmand_table; 1171 num_entries = sizeof(hfp_ag_commmand_table) / sizeof(hfp_command_entry_t); --- 22 unchanged lines hidden (view full) --- 1194 1195 // note: if parser in CMD_HEADER state would treats digits and maybe '+' as separator, match on "ATD" would work. 1196 // note: phone number is currently expected in line_buffer[3..] 1197 // prefix match on 'ATD', AG only 1198 if ((isHandsFree == 0) && (strncmp(line_buffer, HFP_CALL_PHONE_NUMBER, strlen(HFP_CALL_PHONE_NUMBER)) == 0)){ 1199 return HFP_CMD_CALL_PHONE_NUMBER; 1200 } 1201 |
1202 // check for custom commands, AG only 1203 if (isHandsFree == 0) { 1204 const hfp_custom_at_command_t * custom_at_command = hfp_custom_command_lookup(line_buffer); 1205 if (custom_at_command != NULL){ 1206 return HFP_CMD_CUSTOM_MESSAGE; 1207 } 1208 } 1209 |
|
1187 // Valid looking, but unknown commands/responses 1188 if ((isHandsFree == 0) && (strncmp(line_buffer, "AT+", 3) == 0)){ 1189 return HFP_CMD_UNKNOWN; 1190 } 1191 1192 if ((isHandsFree != 0) && (strncmp(line_buffer, "+", 1) == 0)){ 1193 return HFP_CMD_UNKNOWN; 1194 } --- 9 unchanged lines hidden (view full) --- 1204static int hfp_parser_is_buffer_empty(hfp_connection_t * hfp_connection){ 1205 return hfp_connection->line_size == 0; 1206} 1207 1208static int hfp_parser_is_end_of_line(uint8_t byte){ 1209 return (byte == '\n') || (byte == '\r'); 1210} 1211 | 1210 // Valid looking, but unknown commands/responses 1211 if ((isHandsFree == 0) && (strncmp(line_buffer, "AT+", 3) == 0)){ 1212 return HFP_CMD_UNKNOWN; 1213 } 1214 1215 if ((isHandsFree != 0) && (strncmp(line_buffer, "+", 1) == 0)){ 1216 return HFP_CMD_UNKNOWN; 1217 } --- 9 unchanged lines hidden (view full) --- 1227static int hfp_parser_is_buffer_empty(hfp_connection_t * hfp_connection){ 1228 return hfp_connection->line_size == 0; 1229} 1230 1231static int hfp_parser_is_end_of_line(uint8_t byte){ 1232 return (byte == '\n') || (byte == '\r'); 1233} 1234 |
1212static void hfp_parser_reset_line_buffer(hfp_connection_t *hfp_connection) { | 1235void hfp_parser_reset_line_buffer(hfp_connection_t *hfp_connection) { |
1213 hfp_connection->line_size = 0; 1214 // we don't set the first byte to '\0' to allow access to last argument e.g. in hfp_hf_handle_rfcommand 1215} 1216 1217static void hfp_parser_store_if_token(hfp_connection_t * hfp_connection, uint8_t byte){ 1218 switch (byte){ 1219 case ',': 1220 case '-': --- 86 unchanged lines hidden (view full) --- 1307 default: 1308 hfp_connection->command = HFP_CMD_UNKNOWN; 1309 break; 1310 } 1311 } 1312 1313 log_info("command string '%s', handsfree %u -> cmd id %u", (char *)hfp_connection->line_buffer, isHandsFree, hfp_connection->command); 1314 | 1236 hfp_connection->line_size = 0; 1237 // we don't set the first byte to '\0' to allow access to last argument e.g. in hfp_hf_handle_rfcommand 1238} 1239 1240static void hfp_parser_store_if_token(hfp_connection_t * hfp_connection, uint8_t byte){ 1241 switch (byte){ 1242 case ',': 1243 case '-': --- 86 unchanged lines hidden (view full) --- 1330 default: 1331 hfp_connection->command = HFP_CMD_UNKNOWN; 1332 break; 1333 } 1334 } 1335 1336 log_info("command string '%s', handsfree %u -> cmd id %u", (char *)hfp_connection->line_buffer, isHandsFree, hfp_connection->command); 1337 |
1338 // store command id for custom command and just store rest of line 1339 if (hfp_connection->command == HFP_CMD_CUSTOM_MESSAGE){ 1340 const hfp_custom_at_command_t * at_command = hfp_custom_command_lookup((const char *)hfp_connection->line_buffer); 1341 hfp_connection->ag_custom_at_command_id = at_command->command_id; 1342 hfp_connection->parser_state = HFP_PARSER_CUSTOM_COMMAND; 1343 return true; 1344 } 1345 |
|
1315 // next state 1316 hfp_connection->found_equal_sign = false; 1317 hfp_parser_reset_line_buffer(hfp_connection); 1318 hfp_connection->parser_state = HFP_PARSER_CMD_SEQUENCE; 1319 1320 return processed; 1321 1322 case HFP_PARSER_CMD_SEQUENCE: --- 111 unchanged lines hidden (view full) --- 1434 1435 hfp_parser_reset_line_buffer(hfp_connection); 1436 1437 if (hfp_connection->command == HFP_CMD_RETRIEVE_AG_INDICATORS){ 1438 hfp_connection->parser_state = HFP_PARSER_CMD_SEQUENCE; 1439 } 1440 return true; 1441 | 1346 // next state 1347 hfp_connection->found_equal_sign = false; 1348 hfp_parser_reset_line_buffer(hfp_connection); 1349 hfp_connection->parser_state = HFP_PARSER_CMD_SEQUENCE; 1350 1351 return processed; 1352 1353 case HFP_PARSER_CMD_SEQUENCE: --- 111 unchanged lines hidden (view full) --- 1465 1466 hfp_parser_reset_line_buffer(hfp_connection); 1467 1468 if (hfp_connection->command == HFP_CMD_RETRIEVE_AG_INDICATORS){ 1469 hfp_connection->parser_state = HFP_PARSER_CMD_SEQUENCE; 1470 } 1471 return true; 1472 |
1473 case HFP_PARSER_CUSTOM_COMMAND: 1474 hfp_parser_store_byte(hfp_connection, byte); 1475 return true; 1476 |
|
1442 default: 1443 btstack_assert(false); 1444 return true; 1445 } 1446} 1447 1448void hfp_parse(hfp_connection_t * hfp_connection, uint8_t byte, int isHandsFree){ 1449 bool processed = false; --- 520 unchanged lines hidden (view full) --- 1970void hfp_deinit(void){ 1971 hfp_allowed_sco_packet_types = 0; 1972 hfp_connections = NULL; 1973 hfp_hf_callback = NULL; 1974 hfp_ag_callback = NULL; 1975 hfp_hf_rfcomm_packet_handler = NULL; 1976 hfp_ag_rfcomm_packet_handler = NULL; 1977 hfp_sco_establishment_active = NULL; | 1477 default: 1478 btstack_assert(false); 1479 return true; 1480 } 1481} 1482 1483void hfp_parse(hfp_connection_t * hfp_connection, uint8_t byte, int isHandsFree){ 1484 bool processed = false; --- 520 unchanged lines hidden (view full) --- 2005void hfp_deinit(void){ 2006 hfp_allowed_sco_packet_types = 0; 2007 hfp_connections = NULL; 2008 hfp_hf_callback = NULL; 2009 hfp_ag_callback = NULL; 2010 hfp_hf_rfcomm_packet_handler = NULL; 2011 hfp_ag_rfcomm_packet_handler = NULL; 2012 hfp_sco_establishment_active = NULL; |
2013 hfp_custom_commands_ag = NULL; |
|
1978 (void) memset(&hfp_sdp_query_context, 0, sizeof(hfp_sdp_query_context_t)); 1979 (void) memset(&hfp_sdp_query_request, 0, sizeof(btstack_context_callback_registration_t)); 1980} 1981 1982void hfp_set_sco_packet_types(uint16_t packet_types){ 1983 hfp_allowed_sco_packet_types = packet_types; 1984} 1985 --- 58 unchanged lines hidden (view full) --- 2044 printable[i++] = packet[pos]; 2045 break; 2046 } 2047 } 2048 printable[i] = 0; 2049 log_info("%s: '%s'", tag, printable); 2050#endif 2051} | 2014 (void) memset(&hfp_sdp_query_context, 0, sizeof(hfp_sdp_query_context_t)); 2015 (void) memset(&hfp_sdp_query_request, 0, sizeof(btstack_context_callback_registration_t)); 2016} 2017 2018void hfp_set_sco_packet_types(uint16_t packet_types){ 2019 hfp_allowed_sco_packet_types = packet_types; 2020} 2021 --- 58 unchanged lines hidden (view full) --- 2080 printable[i++] = packet[pos]; 2081 break; 2082 } 2083 } 2084 printable[i] = 0; 2085 log_info("%s: '%s'", tag, printable); 2086#endif 2087} |
2088 2089void hfp_register_custom_ag_command(hfp_custom_at_command_t * custom_at_command){ 2090 btstack_linked_list_add(&hfp_custom_commands_ag, (btstack_linked_item_t *) custom_at_command); 2091} |
|