hfp.c (0e2df43f5cbae3fc71139523458b98f30307d21b) | hfp.c (a0ffb263e02c613f9155d5035f68cb0ad7b80d74) |
---|---|
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 --- 96 unchanged lines hidden (view full) --- 105static btstack_linked_list_t hfp_connections = NULL; 106static void parse_sequence(hfp_connection_t * context); 107static hfp_callback_t hfp_callback; 108 109void hfp_set_callback(hfp_callback_t callback){ 110 hfp_callback = callback; 111} 112 | 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 --- 96 unchanged lines hidden (view full) --- 105static btstack_linked_list_t hfp_connections = NULL; 106static void parse_sequence(hfp_connection_t * context); 107static hfp_callback_t hfp_callback; 108 109void hfp_set_callback(hfp_callback_t callback){ 110 hfp_callback = callback; 111} 112 |
113hfp_generic_status_indicator_t * get_hfp_generic_status_indicators(void){ 114 return (hfp_generic_status_indicator_t *) &hfp_generic_status_indicators; 115} 116int get_hfp_generic_status_indicators_nr(void){ 117 return hfp_generic_status_indicators_nr; 118} 119void set_hfp_generic_status_indicators(hfp_generic_status_indicator_t * indicators, int indicator_nr){ 120 if (indicator_nr > HFP_MAX_NUM_HF_INDICATORS) return; 121 hfp_generic_status_indicators_nr = indicator_nr; 122 memcpy(hfp_generic_status_indicators, indicators, indicator_nr * sizeof(hfp_generic_status_indicator_t)); 123} 124 | |
125const char * hfp_hf_feature(int index){ 126 if (index > HFP_HF_FEATURES_SIZE){ 127 return hfp_hf_features[HFP_HF_FEATURES_SIZE]; 128 } 129 return hfp_hf_features[index]; 130} 131 132const char * hfp_ag_feature(int index){ --- 9 unchanged lines hidden (view full) --- 142 int err = rfcomm_send(cid, (uint8_t*) command, strlen(command)); 143 if (err){ 144 log_error("rfcomm_send -> error 0x%02x \n", err); 145 } 146 return 1; 147} 148 149#if 0 | 113const char * hfp_hf_feature(int index){ 114 if (index > HFP_HF_FEATURES_SIZE){ 115 return hfp_hf_features[HFP_HF_FEATURES_SIZE]; 116 } 117 return hfp_hf_features[index]; 118} 119 120const char * hfp_ag_feature(int index){ --- 9 unchanged lines hidden (view full) --- 130 int err = rfcomm_send(cid, (uint8_t*) command, strlen(command)); 131 if (err){ 132 log_error("rfcomm_send -> error 0x%02x \n", err); 133 } 134 return 1; 135} 136 137#if 0 |
150void hfp_set_codec(hfp_connection_t * context, uint8_t *packet, uint16_t size){ | 138void hfp_set_codec(hfp_connection_t * hfp_connection, uint8_t *packet, uint16_t size){ |
151 // parse available codecs 152 int pos = 0; 153 int i; 154 for (i=0; i<size; i++){ 155 pos+=8; | 139 // parse available codecs 140 int pos = 0; 141 int i; 142 for (i=0; i<size; i++){ 143 pos+=8; |
156 if (packet[pos] > context->negotiated_codec){ 157 context->negotiated_codec = packet[pos]; | 144 if (packet[pos] > hfp_connection->negotiated_codec){ 145 hfp_connection->negotiated_codec = packet[pos]; |
158 } 159 } | 146 } 147 } |
160 printf("Negotiated Codec 0x%02x\n", context->negotiated_codec); | 148 printf("Negotiated Codec 0x%02x\n", hfp_connection->negotiated_codec); |
161} 162#endif 163 164// UTILS 165int get_bit(uint16_t bitmap, int position){ 166 return (bitmap >> position) & 1; 167} 168 --- 29 unchanged lines hidden (view full) --- 198 } 199 200 if (i<values_nr){ 201 offset += snprintf(buffer+offset, buffer_size-offset, "%d", get_bit(values,i)); 202 } 203 return offset; 204} 205 | 149} 150#endif 151 152// UTILS 153int get_bit(uint16_t bitmap, int position){ 154 return (bitmap >> position) & 1; 155} 156 --- 29 unchanged lines hidden (view full) --- 186 } 187 188 if (i<values_nr){ 189 offset += snprintf(buffer+offset, buffer_size-offset, "%d", get_bit(values,i)); 190 } 191 return offset; 192} 193 |
194void hfp_emit_simple_event(hfp_callback_t callback, uint8_t event_subtype){ 195 if (!callback) return; 196 uint8_t event[3]; 197 event[0] = HCI_EVENT_HFP_META; 198 event[1] = sizeof(event) - 2; 199 event[2] = event_subtype; 200 (*callback)(event, sizeof(event)); 201} 202 |
|
206void hfp_emit_event(hfp_callback_t callback, uint8_t event_subtype, uint8_t value){ 207 if (!callback) return; 208 uint8_t event[4]; 209 event[0] = HCI_EVENT_HFP_META; 210 event[1] = sizeof(event) - 2; 211 event[2] = event_subtype; 212 event[3] = value; // status 0 == OK 213 (*callback)(event, sizeof(event)); --- 25 unchanged lines hidden (view full) --- 239btstack_linked_list_t * hfp_get_connections(){ 240 return (btstack_linked_list_t *) &hfp_connections; 241} 242 243hfp_connection_t * get_hfp_connection_context_for_rfcomm_cid(uint16_t cid){ 244 btstack_linked_list_iterator_t it; 245 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 246 while (btstack_linked_list_iterator_has_next(&it)){ | 203void hfp_emit_event(hfp_callback_t callback, uint8_t event_subtype, uint8_t value){ 204 if (!callback) return; 205 uint8_t event[4]; 206 event[0] = HCI_EVENT_HFP_META; 207 event[1] = sizeof(event) - 2; 208 event[2] = event_subtype; 209 event[3] = value; // status 0 == OK 210 (*callback)(event, sizeof(event)); --- 25 unchanged lines hidden (view full) --- 236btstack_linked_list_t * hfp_get_connections(){ 237 return (btstack_linked_list_t *) &hfp_connections; 238} 239 240hfp_connection_t * get_hfp_connection_context_for_rfcomm_cid(uint16_t cid){ 241 btstack_linked_list_iterator_t it; 242 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 243 while (btstack_linked_list_iterator_has_next(&it)){ |
247 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 248 if (connection->rfcomm_cid == cid){ 249 return connection; | 244 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 245 if (hfp_connection->rfcomm_cid == cid){ 246 return hfp_connection; |
250 } 251 } 252 return NULL; 253} 254 255hfp_connection_t * get_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr){ 256 btstack_linked_list_iterator_t it; 257 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 258 while (btstack_linked_list_iterator_has_next(&it)){ | 247 } 248 } 249 return NULL; 250} 251 252hfp_connection_t * get_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr){ 253 btstack_linked_list_iterator_t it; 254 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 255 while (btstack_linked_list_iterator_has_next(&it)){ |
259 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 260 if (memcmp(connection->remote_addr, bd_addr, 6) == 0) { 261 return connection; | 256 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 257 if (memcmp(hfp_connection->remote_addr, bd_addr, 6) == 0) { 258 return hfp_connection; |
262 } 263 } 264 return NULL; 265} 266 267hfp_connection_t * get_hfp_connection_context_for_sco_handle(uint16_t handle){ 268 btstack_linked_list_iterator_t it; 269 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 270 while (btstack_linked_list_iterator_has_next(&it)){ | 259 } 260 } 261 return NULL; 262} 263 264hfp_connection_t * get_hfp_connection_context_for_sco_handle(uint16_t handle){ 265 btstack_linked_list_iterator_t it; 266 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 267 while (btstack_linked_list_iterator_has_next(&it)){ |
271 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 272 if (connection->sco_handle == handle){ 273 return connection; | 268 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 269 if (hfp_connection->sco_handle == handle){ 270 return hfp_connection; |
274 } 275 } 276 return NULL; 277} 278 | 271 } 272 } 273 return NULL; 274} 275 |
279void hfp_reset_context_flags(hfp_connection_t * context){ 280 if (!context) return; 281 context->ok_pending = 0; 282 context->send_error = 0; | 276void hfp_reset_context_flags(hfp_connection_t * hfp_connection){ 277 if (!hfp_connection) return; 278 hfp_connection->ok_pending = 0; 279 hfp_connection->send_error = 0; |
283 | 280 |
284 context->keep_byte = 0; | 281 hfp_connection->keep_byte = 0; |
285 | 282 |
286 context->change_status_update_for_individual_ag_indicators = 0; 287 context->operator_name_changed = 0; | 283 hfp_connection->change_status_update_for_individual_ag_indicators = 0; 284 hfp_connection->operator_name_changed = 0; |
288 | 285 |
289 context->enable_extended_audio_gateway_error_report = 0; 290 context->extended_audio_gateway_error = 0; | 286 hfp_connection->enable_extended_audio_gateway_error_report = 0; 287 hfp_connection->extended_audio_gateway_error = 0; |
291 | 288 |
292 // establish codecs connection 293 context->suggested_codec = 0; 294 context->negotiated_codec = 0; 295 context->codec_confirmed = 0; | 289 // establish codecs hfp_connection 290 hfp_connection->suggested_codec = 0; 291 hfp_connection->negotiated_codec = 0; 292 hfp_connection->codec_confirmed = 0; |
296 | 293 |
297 context->establish_audio_connection = 0; | 294 hfp_connection->establish_audio_connection = 0; 295 hfp_connection->call_waiting_notification_enabled = 0; 296 hfp_connection->command = HFP_CMD_NONE; 297 hfp_connection->enable_status_update_for_ag_indicators = 0xFF; |
298} 299 300static hfp_connection_t * create_hfp_connection_context(){ | 298} 299 300static hfp_connection_t * create_hfp_connection_context(){ |
301 hfp_connection_t * context = btstack_memory_hfp_connection_get(); 302 if (!context) return NULL; | 301 hfp_connection_t * hfp_connection = btstack_memory_hfp_connection_get(); 302 if (!hfp_connection) return NULL; |
303 // init state | 303 // init state |
304 memset(context,0, sizeof(hfp_connection_t)); | 304 memset(hfp_connection,0, sizeof(hfp_connection_t)); |
305 | 305 |
306 context->state = HFP_IDLE; 307 context->call_state = HFP_CALL_IDLE; 308 context->codecs_state = HFP_CODECS_IDLE; | 306 hfp_connection->state = HFP_IDLE; 307 hfp_connection->call_state = HFP_CALL_IDLE; 308 hfp_connection->codecs_state = HFP_CODECS_IDLE; |
309 | 309 |
310 context->parser_state = HFP_PARSER_CMD_HEADER; 311 context->command = HFP_CMD_NONE; 312 context->negotiated_codec = 0; | 310 hfp_connection->parser_state = HFP_PARSER_CMD_HEADER; 311 hfp_connection->command = HFP_CMD_NONE; |
313 | 312 |
314 context->enable_status_update_for_ag_indicators = 0xFF; | 313 hfp_reset_context_flags(hfp_connection); |
315 | 314 |
316 context->generic_status_indicators_nr = hfp_generic_status_indicators_nr; 317 memcpy(context->generic_status_indicators, hfp_generic_status_indicators, hfp_generic_status_indicators_nr * sizeof(hfp_generic_status_indicator_t)); 318 319 btstack_linked_list_add(&hfp_connections, (btstack_linked_item_t*)context); 320 return context; | 315 btstack_linked_list_add(&hfp_connections, (linked_item_t*)hfp_connection); 316 return hfp_connection; |
321} 322 | 317} 318 |
323static void remove_hfp_connection_context(hfp_connection_t * context){ 324 btstack_linked_list_remove(&hfp_connections, (btstack_linked_item_t*)context); | 319static void remove_hfp_connection_context(hfp_connection_t * hfp_connection){ 320 btstack_linked_list_remove(&hfp_connections, (btstack_linked_item_t*) hfp_connection); |
325} 326 327static hfp_connection_t * provide_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr){ | 321} 322 323static hfp_connection_t * provide_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr){ |
328 hfp_connection_t * context = get_hfp_connection_context_for_bd_addr(bd_addr); 329 if (context) return context; 330 context = create_hfp_connection_context(); 331 printf("created context for address %s\n", bd_addr_to_str(bd_addr)); 332 memcpy(context->remote_addr, bd_addr, 6); 333 return context; | 324 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr); 325 if (hfp_connection) return hfp_connection; 326 hfp_connection = create_hfp_connection_context(); 327 printf("created hfp_connection for address %s\n", bd_addr_to_str(bd_addr)); 328 memcpy(hfp_connection->remote_addr, bd_addr, 6); 329 return hfp_connection; |
334} 335 336/* @param network. 337 * 0 == no ability to reject a call. 338 * 1 == ability to reject a call. 339 */ 340 341/* @param suported_features --- 79 unchanged lines hidden (view full) --- 421 422static hfp_connection_t * connection_doing_sdp_query = NULL; 423 424static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 425 hfp_handle_hci_event(packet_type, packet, size); 426} 427 428static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ | 330} 331 332/* @param network. 333 * 0 == no ability to reject a call. 334 * 1 == ability to reject a call. 335 */ 336 337/* @param suported_features --- 79 unchanged lines hidden (view full) --- 417 418static hfp_connection_t * connection_doing_sdp_query = NULL; 419 420static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 421 hfp_handle_hci_event(packet_type, packet, size); 422} 423 424static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ |
429 hfp_connection_t * connection = connection_doing_sdp_query; | 425 hfp_connection_t * hfp_connection = connection_doing_sdp_query; |
430 | 426 |
431 if ( connection->state != HFP_W4_SDP_EVENT_QUERY_COMPLETE) return; | 427 if ( hfp_connection->state != HFP_W4_SDP_EVENT_QUERY_COMPLETE) return; |
432 433 switch (hci_event_packet_get_type(packet)){ 434 case SDP_EVENT_QUERY_RFCOMM_SERVICE: | 428 429 switch (hci_event_packet_get_type(packet)){ 430 case SDP_EVENT_QUERY_RFCOMM_SERVICE: |
435 if (!connection) { | 431 if (!hfp_connection) { |
436 log_error("handle_query_rfcomm_event alloc connection for RFCOMM port %u failed", sdp_event_query_rfcomm_service_get_rfcomm_channel(packet)); 437 return; 438 } | 432 log_error("handle_query_rfcomm_event alloc connection for RFCOMM port %u failed", sdp_event_query_rfcomm_service_get_rfcomm_channel(packet)); 433 return; 434 } |
439 connection->rfcomm_channel_nr = sdp_event_query_rfcomm_service_get_rfcomm_channel(packet); | 435 hfp_connection->rfcomm_channel_nr = sdp_event_query_rfcomm_service_get_rfcomm_channel(packet); |
440 break; 441 case SDP_EVENT_QUERY_COMPLETE: 442 connection_doing_sdp_query = NULL; | 436 break; 437 case SDP_EVENT_QUERY_COMPLETE: 438 connection_doing_sdp_query = NULL; |
443 if (connection->rfcomm_channel_nr > 0){ 444 connection->state = HFP_W4_RFCOMM_CONNECTED; 445 log_info("HFP: SDP_EVENT_QUERY_COMPLETE context %p, addr %s, state %d", connection, bd_addr_to_str( connection->remote_addr), connection->state); 446 rfcomm_create_channel(handle_hci_event, connection->remote_addr, connection->rfcomm_channel_nr, NULL); | 439 if (hfp_connection->rfcomm_channel_nr > 0){ 440 hfp_connection->state = HFP_W4_RFCOMM_CONNECTED; 441 log_info("HFP: SDP_EVENT_QUERY_COMPLETE context %p, addr %s, state %d", hfp_connection, bd_addr_to_str( hfp_connection->remote_addr), hfp_connection->state); 442 rfcomm_create_channel(handle_hci_event, hfp_connection->remote_addr, hfp_connection->rfcomm_channel_nr, NULL); |
447 break; 448 } 449 log_info("rfcomm service not found, status %u.", sdp_event_query_complete_get_status(packet)); 450 break; 451 default: 452 break; 453 } 454} 455 456void hfp_handle_hci_event(uint8_t packet_type, uint8_t *packet, uint16_t size){ 457 bd_addr_t event_addr; 458 uint16_t rfcomm_cid, handle; | 443 break; 444 } 445 log_info("rfcomm service not found, status %u.", sdp_event_query_complete_get_status(packet)); 446 break; 447 default: 448 break; 449 } 450} 451 452void hfp_handle_hci_event(uint8_t packet_type, uint8_t *packet, uint16_t size){ 453 bd_addr_t event_addr; 454 uint16_t rfcomm_cid, handle; |
459 hfp_connection_t * context = NULL; | 455 hfp_connection_t * hfp_connection = NULL; |
460 461 // printf("AG packet_handler type %u, event type %x, size %u\n", packet_type, hci_event_packet_get_type(packet), size); 462 463 switch (hci_event_packet_get_type(packet)) { 464 465 case RFCOMM_EVENT_INCOMING_CONNECTION: 466 // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) 467 reverse_bd_addr(&packet[2], event_addr); --- 271 unchanged lines hidden (view full) --- 739 return HFP_CMD_AVAILABLE_CODECS; 740 } 741 742 if (strncmp(line_buffer+offset, HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS, strlen(HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS)) == 0){ 743 return HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE; 744 } 745 746 if (strncmp(line_buffer+offset, HFP_ENABLE_CLIP, strlen(HFP_ENABLE_CLIP)) == 0){ | 456 457 // printf("AG packet_handler type %u, event type %x, size %u\n", packet_type, hci_event_packet_get_type(packet), size); 458 459 switch (hci_event_packet_get_type(packet)) { 460 461 case RFCOMM_EVENT_INCOMING_CONNECTION: 462 // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) 463 reverse_bd_addr(&packet[2], event_addr); --- 271 unchanged lines hidden (view full) --- 735 return HFP_CMD_AVAILABLE_CODECS; 736 } 737 738 if (strncmp(line_buffer+offset, HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS, strlen(HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS)) == 0){ 739 return HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE; 740 } 741 742 if (strncmp(line_buffer+offset, HFP_ENABLE_CLIP, strlen(HFP_ENABLE_CLIP)) == 0){ |
743 if (isHandsFree) return HFP_CMD_AG_SENT_CLIP_INFORMATION; |
|
747 return HFP_CMD_ENABLE_CLIP; 748 } 749 750 if (strncmp(line_buffer+offset, HFP_ENABLE_CALL_WAITING_NOTIFICATION, strlen(HFP_ENABLE_CALL_WAITING_NOTIFICATION)) == 0){ | 744 return HFP_CMD_ENABLE_CLIP; 745 } 746 747 if (strncmp(line_buffer+offset, HFP_ENABLE_CALL_WAITING_NOTIFICATION, strlen(HFP_ENABLE_CALL_WAITING_NOTIFICATION)) == 0){ |
748 if (isHandsFree) return HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE; |
|
751 return HFP_CMD_ENABLE_CALL_WAITING_NOTIFICATION; 752 } 753 754 if (strncmp(line_buffer+offset, HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, strlen(HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES)) == 0){ 755 756 if (isHandsFree) return HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES; 757 758 if (strncmp(line_buffer+strlen(HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES)+offset, "=?", 2) == 0){ --- 67 unchanged lines hidden (view full) --- 826 827 if (strncmp(line_buffer+offset, "NOP", 3) == 0){ 828 return HFP_CMD_NONE; 829 } 830 831 return HFP_CMD_NONE; 832} 833 | 749 return HFP_CMD_ENABLE_CALL_WAITING_NOTIFICATION; 750 } 751 752 if (strncmp(line_buffer+offset, HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, strlen(HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES)) == 0){ 753 754 if (isHandsFree) return HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES; 755 756 if (strncmp(line_buffer+strlen(HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES)+offset, "=?", 2) == 0){ --- 67 unchanged lines hidden (view full) --- 824 825 if (strncmp(line_buffer+offset, "NOP", 3) == 0){ 826 return HFP_CMD_NONE; 827 } 828 829 return HFP_CMD_NONE; 830} 831 |
834static void hfp_parser_store_byte(hfp_connection_t * context, uint8_t byte){ | 832static void hfp_parser_store_byte(hfp_connection_t * hfp_connection, uint8_t byte){ |
835 // printf("hfp_parser_store_byte %c at pos %u\n", (char) byte, context->line_size); 836 // TODO: add limit | 833 // printf("hfp_parser_store_byte %c at pos %u\n", (char) byte, context->line_size); 834 // TODO: add limit |
837 context->line_buffer[context->line_size++] = byte; 838 context->line_buffer[context->line_size] = 0; | 835 hfp_connection->line_buffer[hfp_connection->line_size++] = byte; 836 hfp_connection->line_buffer[hfp_connection->line_size] = 0; |
839} | 837} |
840static int hfp_parser_is_buffer_empty(hfp_connection_t * context){ 841 return context->line_size == 0; | 838static int hfp_parser_is_buffer_empty(hfp_connection_t * hfp_connection){ 839 return hfp_connection->line_size == 0; |
842} 843 844static int hfp_parser_is_end_of_line(uint8_t byte){ 845 return byte == '\n' || byte == '\r'; 846} 847 848static int hfp_parser_is_end_of_header(uint8_t byte){ 849 return hfp_parser_is_end_of_line(byte) || byte == ':' || byte == '?'; 850} 851 | 840} 841 842static int hfp_parser_is_end_of_line(uint8_t byte){ 843 return byte == '\n' || byte == '\r'; 844} 845 846static int hfp_parser_is_end_of_header(uint8_t byte){ 847 return hfp_parser_is_end_of_line(byte) || byte == ':' || byte == '?'; 848} 849 |
852static int hfp_parser_found_separator(hfp_connection_t * context, uint8_t byte){ 853 if (context->keep_byte == 1) return 1; | 850static int hfp_parser_found_separator(hfp_connection_t * hfp_connection, uint8_t byte){ 851 if (hfp_connection->keep_byte == 1) return 1; |
854 855 int found_separator = byte == ',' || byte == '\n'|| byte == '\r'|| 856 byte == ')' || byte == '(' || byte == ':' || 857 byte == '-' || byte == '"' || byte == '?'|| byte == '='; 858 return found_separator; 859} 860 | 852 853 int found_separator = byte == ',' || byte == '\n'|| byte == '\r'|| 854 byte == ')' || byte == '(' || byte == ':' || 855 byte == '-' || byte == '"' || byte == '?'|| byte == '='; 856 return found_separator; 857} 858 |
861static void hfp_parser_next_state(hfp_connection_t * context, uint8_t byte){ 862 context->line_size = 0; | 859static void hfp_parser_next_state(hfp_connection_t * hfp_connection, uint8_t byte){ 860 hfp_connection->line_size = 0; |
863 if (hfp_parser_is_end_of_line(byte)){ | 861 if (hfp_parser_is_end_of_line(byte)){ |
864 context->parser_item_index = 0; 865 context->parser_state = HFP_PARSER_CMD_HEADER; | 862 hfp_connection->parser_item_index = 0; 863 hfp_connection->parser_state = HFP_PARSER_CMD_HEADER; |
866 return; 867 } | 864 return; 865 } |
868 switch (context->parser_state){ | 866 switch (hfp_connection->parser_state){ |
869 case HFP_PARSER_CMD_HEADER: | 867 case HFP_PARSER_CMD_HEADER: |
870 context->parser_state = HFP_PARSER_CMD_SEQUENCE; 871 if (context->keep_byte == 1){ 872 hfp_parser_store_byte(context, byte); 873 context->keep_byte = 0; | 868 hfp_connection->parser_state = HFP_PARSER_CMD_SEQUENCE; 869 if (hfp_connection->keep_byte == 1){ 870 hfp_parser_store_byte(hfp_connection, byte); 871 hfp_connection->keep_byte = 0; |
874 } 875 break; 876 case HFP_PARSER_CMD_SEQUENCE: | 872 } 873 break; 874 case HFP_PARSER_CMD_SEQUENCE: |
877 switch (context->command){ | 875 switch (hfp_connection->command){ |
878 case HFP_CMD_AG_SENT_PHONE_NUMBER: | 876 case HFP_CMD_AG_SENT_PHONE_NUMBER: |
877 case HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE: 878 case HFP_CMD_AG_SENT_CLIP_INFORMATION: |
|
879 case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: 880 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: 881 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: 882 case HFP_CMD_RETRIEVE_AG_INDICATORS: 883 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: 884 case HFP_CMD_HF_INDICATOR_STATUS: | 879 case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: 880 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: 881 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: 882 case HFP_CMD_RETRIEVE_AG_INDICATORS: 883 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: 884 case HFP_CMD_HF_INDICATOR_STATUS: |
885 context->parser_state = HFP_PARSER_SECOND_ITEM; | 885 hfp_connection->parser_state = HFP_PARSER_SECOND_ITEM; |
886 break; 887 default: 888 break; 889 } 890 break; 891 case HFP_PARSER_SECOND_ITEM: | 886 break; 887 default: 888 break; 889 } 890 break; 891 case HFP_PARSER_SECOND_ITEM: |
892 context->parser_state = HFP_PARSER_THIRD_ITEM; | 892 hfp_connection->parser_state = HFP_PARSER_THIRD_ITEM; |
893 break; 894 case HFP_PARSER_THIRD_ITEM: | 893 break; 894 case HFP_PARSER_THIRD_ITEM: |
895 if (context->command == HFP_CMD_RETRIEVE_AG_INDICATORS){ 896 context->parser_state = HFP_PARSER_CMD_SEQUENCE; | 895 if (hfp_connection->command == HFP_CMD_RETRIEVE_AG_INDICATORS){ 896 hfp_connection->parser_state = HFP_PARSER_CMD_SEQUENCE; |
897 break; 898 } | 897 break; 898 } |
899 context->parser_state = HFP_PARSER_CMD_HEADER; | 899 hfp_connection->parser_state = HFP_PARSER_CMD_HEADER; |
900 break; 901 } 902} 903 | 900 break; 901 } 902} 903 |
904void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree){ | 904void hfp_parse(hfp_connection_t * hfp_connection, uint8_t byte, int isHandsFree){ |
905 // handle ATD<dial_string>; | 905 // handle ATD<dial_string>; |
906 if (strncmp((const char*)context->line_buffer, HFP_CALL_PHONE_NUMBER, strlen(HFP_CALL_PHONE_NUMBER)) == 0){ | 906 if (strncmp((const char*)hfp_connection->line_buffer, HFP_CALL_PHONE_NUMBER, strlen(HFP_CALL_PHONE_NUMBER)) == 0){ |
907 // check for end-of-line or ';' 908 if (byte == ';' || hfp_parser_is_end_of_line(byte)){ | 907 // check for end-of-line or ';' 908 if (byte == ';' || hfp_parser_is_end_of_line(byte)){ |
909 context->line_buffer[context->line_size] = 0; 910 context->line_size = 0; 911 context->command = HFP_CMD_CALL_PHONE_NUMBER; | 909 hfp_connection->line_buffer[hfp_connection->line_size] = 0; 910 hfp_connection->line_size = 0; 911 hfp_connection->command = HFP_CMD_CALL_PHONE_NUMBER; |
912 } else { | 912 } else { |
913 context->line_buffer[context->line_size++] = byte; | 913 hfp_connection->line_buffer[hfp_connection->line_size++] = byte; |
914 } 915 return; 916 } 917 918 // TODO: handle space inside word | 914 } 915 return; 916 } 917 918 // TODO: handle space inside word |
919 if (byte == ' ' && context->parser_state > HFP_PARSER_CMD_HEADER) return; | 919 if (byte == ' ' && hfp_connection->parser_state > HFP_PARSER_CMD_HEADER) return; |
920 | 920 |
921 if (byte == ',' && context->command == HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE){ 922 if (context->line_size == 0){ 923 context->line_buffer[0] = 0; 924 context->ignore_value = 1; 925 parse_sequence(context); | 921 if (byte == ',' && hfp_connection->command == HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE){ 922 if (hfp_connection->line_size == 0){ 923 hfp_connection->line_buffer[0] = 0; 924 hfp_connection->ignore_value = 1; 925 parse_sequence(hfp_connection); |
926 return; 927 } 928 } 929 | 926 return; 927 } 928 } 929 |
930 if (!hfp_parser_found_separator(context, byte)){ 931 hfp_parser_store_byte(context, byte); | 930 if (!hfp_parser_found_separator(hfp_connection, byte)){ 931 hfp_parser_store_byte(hfp_connection, byte); |
932 return; 933 } 934 935 if (hfp_parser_is_end_of_line(byte)) { | 932 return; 933 } 934 935 if (hfp_parser_is_end_of_line(byte)) { |
936 if (hfp_parser_is_buffer_empty(context)){ 937 context->parser_state = HFP_PARSER_CMD_HEADER; | 936 if (hfp_parser_is_buffer_empty(hfp_connection)){ 937 hfp_connection->parser_state = HFP_PARSER_CMD_HEADER; |
938 } 939 } | 938 } 939 } |
940 if (hfp_parser_is_buffer_empty(context)) return; | 940 if (hfp_parser_is_buffer_empty(hfp_connection)) return; |
941 | 941 |
942 switch (context->parser_state){ | 942 switch (hfp_connection->parser_state){ |
943 case HFP_PARSER_CMD_HEADER: // header 944 if (byte == '='){ | 943 case HFP_PARSER_CMD_HEADER: // header 944 if (byte == '='){ |
945 context->keep_byte = 1; 946 hfp_parser_store_byte(context, byte); | 945 hfp_connection->keep_byte = 1; 946 hfp_parser_store_byte(hfp_connection, byte); |
947 return; 948 } 949 950 if (byte == '?'){ | 947 return; 948 } 949 950 if (byte == '?'){ |
951 context->keep_byte = 0; 952 hfp_parser_store_byte(context, byte); | 951 hfp_connection->keep_byte = 0; 952 hfp_parser_store_byte(hfp_connection, byte); |
953 return; 954 } 955 956 if (byte == ','){ | 953 return; 954 } 955 956 if (byte == ','){ |
957 context->resolve_byte = 1; | 957 hfp_connection->resolve_byte = 1; |
958 } 959 | 958 } 959 |
960 // printf(" parse header 2 %s, keep separator $ %d\n", context->line_buffer, context->keep_byte); 961 if (hfp_parser_is_end_of_header(byte) || context->keep_byte == 1){ 962 // printf(" parse header 3 %s, keep separator $ %d\n", context->line_buffer, context->keep_byte); 963 char * line_buffer = (char *)context->line_buffer; 964 context->command = parse_command(line_buffer, isHandsFree); | 960 // printf(" parse header 2 %s, keep separator $ %d\n", hfp_connection->line_buffer, hfp_connection->keep_byte); 961 if (hfp_parser_is_end_of_header(byte) || hfp_connection->keep_byte == 1){ 962 // printf(" parse header 3 %s, keep separator $ %d\n", hfp_connection->line_buffer, hfp_connection->keep_byte); 963 char * line_buffer = (char *)hfp_connection->line_buffer; 964 hfp_connection->command = parse_command(line_buffer, isHandsFree); |
965 | 965 |
966 /* resolve command name according to context */ 967 if (context->command == HFP_CMD_UNKNOWN){ 968 switch(context->state){ | 966 /* resolve command name according to hfp_connection */ 967 if (hfp_connection->command == HFP_CMD_UNKNOWN){ 968 switch(hfp_connection->state){ |
969 case HFP_W4_LIST_GENERIC_STATUS_INDICATORS: | 969 case HFP_W4_LIST_GENERIC_STATUS_INDICATORS: |
970 context->command = HFP_CMD_LIST_GENERIC_STATUS_INDICATORS; | 970 hfp_connection->command = HFP_CMD_LIST_GENERIC_STATUS_INDICATORS; |
971 break; 972 case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS: | 971 break; 972 case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS: |
973 context->command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS; | 973 hfp_connection->command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS; |
974 break; 975 case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS: | 974 break; 975 case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS: |
976 context->command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE; | 976 hfp_connection->command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE; |
977 break; 978 case HFP_W4_RETRIEVE_INDICATORS_STATUS: | 977 break; 978 case HFP_W4_RETRIEVE_INDICATORS_STATUS: |
979 context->command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS; | 979 hfp_connection->command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS; |
980 break; 981 case HFP_W4_RETRIEVE_INDICATORS: | 980 break; 981 case HFP_W4_RETRIEVE_INDICATORS: |
982 context->send_ag_indicators_segment = 0; 983 context->command = HFP_CMD_RETRIEVE_AG_INDICATORS; | 982 hfp_connection->send_ag_indicators_segment = 0; 983 hfp_connection->command = HFP_CMD_RETRIEVE_AG_INDICATORS; |
984 break; 985 default: 986 break; 987 } 988 } 989 } 990 break; 991 992 case HFP_PARSER_CMD_SEQUENCE: | 984 break; 985 default: 986 break; 987 } 988 } 989 } 990 break; 991 992 case HFP_PARSER_CMD_SEQUENCE: |
993 parse_sequence(context); | 993 parse_sequence(hfp_connection); |
994 break; 995 case HFP_PARSER_SECOND_ITEM: | 994 break; 995 case HFP_PARSER_SECOND_ITEM: |
996 switch (context->command){ | 996 switch (hfp_connection->command){ |
997 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: | 997 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: |
998 log_info("format %s, ", context->line_buffer); 999 context->network_operator.format = atoi((char *)&context->line_buffer[0]); | 998 log_info("format %s, ", hfp_connection->line_buffer); 999 hfp_connection->network_operator.format = atoi((char *)&hfp_connection->line_buffer[0]); |
1000 break; 1001 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: | 1000 break; 1001 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: |
1002 log_info("format %s \n", context->line_buffer); 1003 context->network_operator.format = atoi((char *)&context->line_buffer[0]); | 1002 log_info("format %s \n", hfp_connection->line_buffer); 1003 hfp_connection->network_operator.format = atoi((char *)&hfp_connection->line_buffer[0]); |
1004 break; 1005 case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS: 1006 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS: 1007 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: | 1004 break; 1005 case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS: 1006 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS: 1007 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: |
1008 context->generic_status_indicators[context->parser_item_index].state = (uint8_t)atoi((char*)context->line_buffer); | 1008 hfp_connection->generic_status_indicators[hfp_connection->parser_item_index].state = (uint8_t)atoi((char*)hfp_connection->line_buffer); |
1009 break; 1010 case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: | 1009 break; 1010 case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: |
1011 context->ag_indicators[context->parser_item_index].status = (uint8_t)atoi((char*)context->line_buffer); 1012 log_info("%d \n", context->ag_indicators[context->parser_item_index].status); 1013 context->ag_indicators[context->parser_item_index].status_changed = 1; | 1011 hfp_connection->ag_indicators[hfp_connection->parser_item_index].status = (uint8_t)atoi((char*)hfp_connection->line_buffer); 1012 log_info("%d \n", hfp_connection->ag_indicators[hfp_connection->parser_item_index].status); 1013 hfp_connection->ag_indicators[hfp_connection->parser_item_index].status_changed = 1; |
1014 break; 1015 case HFP_CMD_RETRIEVE_AG_INDICATORS: | 1014 break; 1015 case HFP_CMD_RETRIEVE_AG_INDICATORS: |
1016 context->ag_indicators[context->parser_item_index].min_range = atoi((char *)context->line_buffer); 1017 log_info("%s, ", context->line_buffer); | 1016 hfp_connection->ag_indicators[hfp_connection->parser_item_index].min_range = atoi((char *)hfp_connection->line_buffer); 1017 log_info("%s, ", hfp_connection->line_buffer); |
1018 break; 1019 case HFP_CMD_AG_SENT_PHONE_NUMBER: | 1018 break; 1019 case HFP_CMD_AG_SENT_PHONE_NUMBER: |
1020 context->bnip_type = (uint8_t)atoi((char*)context->line_buffer); | 1020 case HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE: 1021 case HFP_CMD_AG_SENT_CLIP_INFORMATION: 1022 hfp_connection->bnip_type = (uint8_t)atoi((char*)hfp_connection->line_buffer); |
1021 break; 1022 default: 1023 break; 1024 } 1025 break; 1026 1027 case HFP_PARSER_THIRD_ITEM: | 1023 break; 1024 default: 1025 break; 1026 } 1027 break; 1028 1029 case HFP_PARSER_THIRD_ITEM: |
1028 switch (context->command){ | 1030 switch (hfp_connection->command){ |
1029 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: | 1031 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: |
1030 strcpy(context->network_operator.name, (char *)context->line_buffer); 1031 log_info("name %s\n", context->line_buffer); | 1032 strcpy(hfp_connection->network_operator.name, (char *)hfp_connection->line_buffer); 1033 log_info("name %s\n", hfp_connection->line_buffer); |
1032 break; 1033 case HFP_CMD_RETRIEVE_AG_INDICATORS: | 1034 break; 1035 case HFP_CMD_RETRIEVE_AG_INDICATORS: |
1034 context->ag_indicators[context->parser_item_index].max_range = atoi((char *)context->line_buffer); 1035 context->parser_item_index++; 1036 context->ag_indicators_nr = context->parser_item_index; 1037 log_info("%s)\n", context->line_buffer); | 1036 hfp_connection->ag_indicators[hfp_connection->parser_item_index].max_range = atoi((char *)hfp_connection->line_buffer); 1037 hfp_connection->parser_item_index++; 1038 hfp_connection->ag_indicators_nr = hfp_connection->parser_item_index; 1039 log_info("%s)\n", hfp_connection->line_buffer); |
1038 break; 1039 default: 1040 break; 1041 } 1042 break; 1043 } | 1040 break; 1041 default: 1042 break; 1043 } 1044 break; 1045 } |
1044 hfp_parser_next_state(context, byte); | 1046 hfp_parser_next_state(hfp_connection, byte); |
1045 | 1047 |
1046 if (context->resolve_byte && context->command == HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE){ 1047 context->resolve_byte = 0; 1048 context->ignore_value = 1; 1049 parse_sequence(context); 1050 context->line_buffer[0] = 0; 1051 context->line_size = 0; | 1048 if (hfp_connection->resolve_byte && hfp_connection->command == HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE){ 1049 hfp_connection->resolve_byte = 0; 1050 hfp_connection->ignore_value = 1; 1051 parse_sequence(hfp_connection); 1052 hfp_connection->line_buffer[0] = 0; 1053 hfp_connection->line_size = 0; |
1052 } 1053} 1054 | 1054 } 1055} 1056 |
1055static void parse_sequence(hfp_connection_t * context){ | 1057static void parse_sequence(hfp_connection_t * hfp_connection){ |
1056 int value; | 1058 int value; |
1057 switch (context->command){ | 1059 switch (hfp_connection->command){ |
1058 case HFP_CMD_SET_GENERIC_STATUS_INDICATOR_STATUS: | 1060 case HFP_CMD_SET_GENERIC_STATUS_INDICATOR_STATUS: |
1059 value = atoi((char *)&context->line_buffer[0]); | 1061 value = atoi((char *)&hfp_connection->line_buffer[0]); |
1060 int i; | 1062 int i; |
1061 switch (context->parser_item_index){ | 1063 switch (hfp_connection->parser_item_index){ |
1062 case 0: | 1064 case 0: |
1063 for (i=0;i<context->generic_status_indicators_nr;i++){ 1064 if (context->generic_status_indicators[i].uuid == value){ 1065 context->parser_indicator_index = i; | 1065 for (i=0;i<hfp_connection->generic_status_indicators_nr;i++){ 1066 if (hfp_connection->generic_status_indicators[i].uuid == value){ 1067 hfp_connection->parser_indicator_index = i; |
1066 break; 1067 } 1068 } 1069 break; 1070 case 1: | 1068 break; 1069 } 1070 } 1071 break; 1072 case 1: |
1071 if (context->parser_indicator_index <0) break; 1072 context->generic_status_indicators[context->parser_indicator_index].state = value; | 1073 if (hfp_connection->parser_indicator_index <0) break; 1074 hfp_connection->generic_status_indicators[hfp_connection->parser_indicator_index].state = value; |
1073 log_info("HFP_CMD_SET_GENERIC_STATUS_INDICATOR_STATUS set indicator at index %u, to %u\n", | 1075 log_info("HFP_CMD_SET_GENERIC_STATUS_INDICATOR_STATUS set indicator at index %u, to %u\n", |
1074 context->parser_item_index, value); | 1076 hfp_connection->parser_item_index, value); |
1075 break; 1076 default: 1077 break; 1078 } | 1077 break; 1078 default: 1079 break; 1080 } |
1079 context->parser_item_index++; | 1081 hfp_connection->parser_item_index++; |
1080 break; 1081 1082 case HFP_CMD_GET_SUBSCRIBER_NUMBER_INFORMATION: | 1082 break; 1083 1084 case HFP_CMD_GET_SUBSCRIBER_NUMBER_INFORMATION: |
1083 switch(context->parser_item_index){ | 1085 switch(hfp_connection->parser_item_index){ |
1084 case 0: | 1086 case 0: |
1085 strncpy(context->bnip_number, (char *)context->line_buffer, sizeof(context->bnip_number)); 1086 context->bnip_number[sizeof(context->bnip_number)-1] = 0; | 1087 strncpy(hfp_connection->bnip_number, (char *)hfp_connection->line_buffer, sizeof(hfp_connection->bnip_number)); 1088 hfp_connection->bnip_number[sizeof(hfp_connection->bnip_number)-1] = 0; |
1087 break; 1088 case 1: | 1089 break; 1090 case 1: |
1089 value = atoi((char *)&context->line_buffer[0]); 1090 context->bnip_type = value; | 1091 value = atoi((char *)&hfp_connection->line_buffer[0]); 1092 hfp_connection->bnip_type = value; |
1091 break; 1092 default: 1093 break; 1094 } | 1093 break; 1094 default: 1095 break; 1096 } |
1095 context->parser_item_index++; | 1097 hfp_connection->parser_item_index++; |
1096 break; 1097 case HFP_CMD_LIST_CURRENT_CALLS: | 1098 break; 1099 case HFP_CMD_LIST_CURRENT_CALLS: |
1098 switch(context->parser_item_index){ | 1100 switch(hfp_connection->parser_item_index){ |
1099 case 0: | 1101 case 0: |
1100 value = atoi((char *)&context->line_buffer[0]); 1101 context->clcc_idx = value; | 1102 value = atoi((char *)&hfp_connection->line_buffer[0]); 1103 hfp_connection->clcc_idx = value; |
1102 break; 1103 case 1: | 1104 break; 1105 case 1: |
1104 value = atoi((char *)&context->line_buffer[0]); 1105 context->clcc_dir = value; | 1106 value = atoi((char *)&hfp_connection->line_buffer[0]); 1107 hfp_connection->clcc_dir = value; |
1106 break; 1107 case 2: | 1108 break; 1109 case 2: |
1108 value = atoi((char *)&context->line_buffer[0]); 1109 context->clcc_status = value; | 1110 value = atoi((char *)&hfp_connection->line_buffer[0]); 1111 hfp_connection->clcc_status = value; |
1110 break; 1111 case 3: | 1112 break; 1113 case 3: |
1112 value = atoi((char *)&context->line_buffer[0]); 1113 context->clcc_mpty = value; | 1114 value = atoi((char *)&hfp_connection->line_buffer[0]); 1115 hfp_connection->clcc_mpty = value; |
1114 break; 1115 case 4: | 1116 break; 1117 case 4: |
1116 strncpy(context->bnip_number, (char *)context->line_buffer, sizeof(context->bnip_number)); 1117 context->bnip_number[sizeof(context->bnip_number)-1] = 0; | 1118 strncpy(hfp_connection->bnip_number, (char *)hfp_connection->line_buffer, sizeof(hfp_connection->bnip_number)); 1119 hfp_connection->bnip_number[sizeof(hfp_connection->bnip_number)-1] = 0; |
1118 break; 1119 case 5: | 1120 break; 1121 case 5: |
1120 value = atoi((char *)&context->line_buffer[0]); 1121 context->bnip_type = value; | 1122 value = atoi((char *)&hfp_connection->line_buffer[0]); 1123 hfp_connection->bnip_type = value; |
1122 break; 1123 default: 1124 break; 1125 } | 1124 break; 1125 default: 1126 break; 1127 } |
1126 context->parser_item_index++; | 1128 hfp_connection->parser_item_index++; |
1127 break; 1128 case HFP_CMD_SET_MICROPHONE_GAIN: | 1129 break; 1130 case HFP_CMD_SET_MICROPHONE_GAIN: |
1129 value = atoi((char *)&context->line_buffer[0]); 1130 context->microphone_gain = value; | 1131 value = atoi((char *)&hfp_connection->line_buffer[0]); 1132 hfp_connection->microphone_gain = value; |
1131 log_info("hfp parse HFP_CMD_SET_MICROPHONE_GAIN %d\n", value); 1132 break; 1133 case HFP_CMD_SET_SPEAKER_GAIN: | 1133 log_info("hfp parse HFP_CMD_SET_MICROPHONE_GAIN %d\n", value); 1134 break; 1135 case HFP_CMD_SET_SPEAKER_GAIN: |
1134 value = atoi((char *)&context->line_buffer[0]); 1135 context->speaker_gain = value; | 1136 value = atoi((char *)&hfp_connection->line_buffer[0]); 1137 hfp_connection->speaker_gain = value; |
1136 log_info("hfp parse HFP_CMD_SET_SPEAKER_GAIN %d\n", value); 1137 break; 1138 case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION: | 1138 log_info("hfp parse HFP_CMD_SET_SPEAKER_GAIN %d\n", value); 1139 break; 1140 case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION: |
1139 value = atoi((char *)&context->line_buffer[0]); 1140 context->ag_activate_voice_recognition = value; | 1141 value = atoi((char *)&hfp_connection->line_buffer[0]); 1142 hfp_connection->ag_activate_voice_recognition = value; |
1141 log_info("hfp parse HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION %d\n", value); 1142 break; 1143 case HFP_CMD_TURN_OFF_EC_AND_NR: | 1143 log_info("hfp parse HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION %d\n", value); 1144 break; 1145 case HFP_CMD_TURN_OFF_EC_AND_NR: |
1144 value = atoi((char *)&context->line_buffer[0]); 1145 context->ag_echo_and_noise_reduction = value; | 1146 value = atoi((char *)&hfp_connection->line_buffer[0]); 1147 hfp_connection->ag_echo_and_noise_reduction = value; |
1146 log_info("hfp parse HFP_CMD_TURN_OFF_EC_AND_NR %d\n", value); 1147 break; 1148 case HFP_CMD_CHANGE_IN_BAND_RING_TONE_SETTING: | 1148 log_info("hfp parse HFP_CMD_TURN_OFF_EC_AND_NR %d\n", value); 1149 break; 1150 case HFP_CMD_CHANGE_IN_BAND_RING_TONE_SETTING: |
1149 value = atoi((char *)&context->line_buffer[0]); 1150 context->remote_supported_features = store_bit(context->remote_supported_features, HFP_AGSF_IN_BAND_RING_TONE, value); | 1151 value = atoi((char *)&hfp_connection->line_buffer[0]); 1152 hfp_connection->remote_supported_features = store_bit(hfp_connection->remote_supported_features, HFP_AGSF_IN_BAND_RING_TONE, value); |
1151 log_info("hfp parse HFP_CHANGE_IN_BAND_RING_TONE_SETTING %d\n", value); 1152 break; 1153 case HFP_CMD_HF_CONFIRMED_CODEC: | 1153 log_info("hfp parse HFP_CHANGE_IN_BAND_RING_TONE_SETTING %d\n", value); 1154 break; 1155 case HFP_CMD_HF_CONFIRMED_CODEC: |
1154 context->codec_confirmed = atoi((char*)context->line_buffer); 1155 log_info("hfp parse HFP_CMD_HF_CONFIRMED_CODEC %d\n", context->codec_confirmed); | 1156 hfp_connection->codec_confirmed = atoi((char*)hfp_connection->line_buffer); 1157 log_info("hfp parse HFP_CMD_HF_CONFIRMED_CODEC %d\n", hfp_connection->codec_confirmed); |
1156 break; 1157 case HFP_CMD_AG_SUGGESTED_CODEC: | 1158 break; 1159 case HFP_CMD_AG_SUGGESTED_CODEC: |
1158 context->suggested_codec = atoi((char*)context->line_buffer); 1159 log_info("hfp parse HFP_CMD_AG_SUGGESTED_CODEC %d\n", context->suggested_codec); | 1160 hfp_connection->suggested_codec = atoi((char*)hfp_connection->line_buffer); 1161 log_info("hfp parse HFP_CMD_AG_SUGGESTED_CODEC %d\n", hfp_connection->suggested_codec); |
1160 break; 1161 case HFP_CMD_SUPPORTED_FEATURES: | 1162 break; 1163 case HFP_CMD_SUPPORTED_FEATURES: |
1162 context->remote_supported_features = atoi((char*)context->line_buffer); 1163 log_info("Parsed supported feature %d\n", context->remote_supported_features); | 1164 hfp_connection->remote_supported_features = atoi((char*)hfp_connection->line_buffer); 1165 log_info("Parsed supported feature %d\n", hfp_connection->remote_supported_features); |
1164 break; 1165 case HFP_CMD_AVAILABLE_CODECS: | 1166 break; 1167 case HFP_CMD_AVAILABLE_CODECS: |
1166 log_info("Parsed codec %s\n", context->line_buffer); 1167 context->remote_codecs[context->parser_item_index] = (uint16_t)atoi((char*)context->line_buffer); 1168 context->parser_item_index++; 1169 context->remote_codecs_nr = context->parser_item_index; | 1168 log_info("Parsed codec %s\n", hfp_connection->line_buffer); 1169 hfp_connection->remote_codecs[hfp_connection->parser_item_index] = (uint16_t)atoi((char*)hfp_connection->line_buffer); 1170 hfp_connection->parser_item_index++; 1171 hfp_connection->remote_codecs_nr = hfp_connection->parser_item_index; |
1170 break; 1171 case HFP_CMD_RETRIEVE_AG_INDICATORS: | 1172 break; 1173 case HFP_CMD_RETRIEVE_AG_INDICATORS: |
1172 strcpy((char *)context->ag_indicators[context->parser_item_index].name, (char *)context->line_buffer); 1173 context->ag_indicators[context->parser_item_index].index = context->parser_item_index+1; 1174 log_info("Indicator %d: %s (", context->ag_indicators_nr+1, context->line_buffer); | 1174 strcpy((char *)hfp_connection->ag_indicators[hfp_connection->parser_item_index].name, (char *)hfp_connection->line_buffer); 1175 hfp_connection->ag_indicators[hfp_connection->parser_item_index].index = hfp_connection->parser_item_index+1; 1176 log_info("Indicator %d: %s (", hfp_connection->ag_indicators_nr+1, hfp_connection->line_buffer); |
1175 break; 1176 case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS: | 1177 break; 1178 case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS: |
1177 log_info("Parsed Indicator %d with status: %s\n", context->parser_item_index+1, context->line_buffer); 1178 context->ag_indicators[context->parser_item_index].status = atoi((char *) context->line_buffer); 1179 context->parser_item_index++; | 1179 log_info("Parsed Indicator %d with status: %s\n", hfp_connection->parser_item_index+1, hfp_connection->line_buffer); 1180 hfp_connection->ag_indicators[hfp_connection->parser_item_index].status = atoi((char *) hfp_connection->line_buffer); 1181 hfp_connection->parser_item_index++; |
1180 break; 1181 case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE: | 1182 break; 1183 case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE: |
1182 context->parser_item_index++; 1183 if (context->parser_item_index != 4) break; 1184 log_info("Parsed Enable indicators: %s\n", context->line_buffer); 1185 value = atoi((char *)&context->line_buffer[0]); 1186 context->enable_status_update_for_ag_indicators = (uint8_t) value; | 1184 hfp_connection->parser_item_index++; 1185 if (hfp_connection->parser_item_index != 4) break; 1186 log_info("Parsed Enable indicators: %s\n", hfp_connection->line_buffer); 1187 value = atoi((char *)&hfp_connection->line_buffer[0]); 1188 hfp_connection->enable_status_update_for_ag_indicators = (uint8_t) value; |
1187 break; 1188 case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES: | 1189 break; 1190 case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES: |
1189 log_info("Parsed Support call hold: %s\n", context->line_buffer); 1190 if (context->line_size > 2 ) break; 1191 strcpy((char *)context->remote_call_services[context->remote_call_services_nr].name, (char *)context->line_buffer); 1192 context->remote_call_services_nr++; | 1191 log_info("Parsed Support call hold: %s\n", hfp_connection->line_buffer); 1192 if (hfp_connection->line_size > 2 ) break; 1193 strcpy((char *)hfp_connection->remote_call_services[hfp_connection->remote_call_services_nr].name, (char *)hfp_connection->line_buffer); 1194 hfp_connection->remote_call_services_nr++; |
1193 break; 1194 case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS: 1195 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS: | 1195 break; 1196 case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS: 1197 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS: |
1196 log_info("Parsed Generic status indicator: %s\n", context->line_buffer); 1197 context->generic_status_indicators[context->parser_item_index].uuid = (uint16_t)atoi((char*)context->line_buffer); 1198 context->parser_item_index++; 1199 context->generic_status_indicators_nr = context->parser_item_index; | 1198 log_info("Parsed Generic status indicator: %s\n", hfp_connection->line_buffer); 1199 hfp_connection->generic_status_indicators[hfp_connection->parser_item_index].uuid = (uint16_t)atoi((char*)hfp_connection->line_buffer); 1200 hfp_connection->parser_item_index++; 1201 hfp_connection->generic_status_indicators_nr = hfp_connection->parser_item_index; |
1200 break; 1201 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: 1202 // HF parses inital AG gen. ind. state | 1202 break; 1203 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: 1204 // HF parses inital AG gen. ind. state |
1203 log_info("Parsed List generic status indicator %s state: ", context->line_buffer); 1204 context->parser_item_index = (uint8_t)atoi((char*)context->line_buffer); | 1205 log_info("Parsed List generic status indicator %s state: ", hfp_connection->line_buffer); 1206 hfp_connection->parser_item_index = (uint8_t)atoi((char*)hfp_connection->line_buffer); |
1205 break; 1206 case HFP_CMD_HF_INDICATOR_STATUS: | 1207 break; 1208 case HFP_CMD_HF_INDICATOR_STATUS: |
1207 context->parser_indicator_index = (uint8_t)atoi((char*)context->line_buffer); 1208 log_info("Parsed HF indicator index %u", context->parser_indicator_index); | 1209 hfp_connection->parser_indicator_index = (uint8_t)atoi((char*)hfp_connection->line_buffer); 1210 log_info("Parsed HF indicator index %u", hfp_connection->parser_indicator_index); |
1209 break; 1210 case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE: 1211 // AG parses new gen. ind. state | 1211 break; 1212 case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE: 1213 // AG parses new gen. ind. state |
1212 if (context->ignore_value){ 1213 context->ignore_value = 0; 1214 log_info("Parsed Enable AG indicator pos %u('%s') - unchanged (stays %u)\n", context->parser_item_index, 1215 context->ag_indicators[context->parser_item_index].name, context->ag_indicators[context->parser_item_index].enabled); | 1214 if (hfp_connection->ignore_value){ 1215 hfp_connection->ignore_value = 0; 1216 log_info("Parsed Enable AG indicator pos %u('%s') - unchanged (stays %u)\n", hfp_connection->parser_item_index, 1217 hfp_connection->ag_indicators[hfp_connection->parser_item_index].name, hfp_connection->ag_indicators[hfp_connection->parser_item_index].enabled); |
1216 } | 1218 } |
1217 else if (context->ag_indicators[context->parser_item_index].mandatory){ | 1219 else if (hfp_connection->ag_indicators[hfp_connection->parser_item_index].mandatory){ |
1218 log_info("Parsed Enable AG indicator pos %u('%s') - ignore (mandatory)\n", | 1220 log_info("Parsed Enable AG indicator pos %u('%s') - ignore (mandatory)\n", |
1219 context->parser_item_index, context->ag_indicators[context->parser_item_index].name); | 1221 hfp_connection->parser_item_index, hfp_connection->ag_indicators[hfp_connection->parser_item_index].name); |
1220 } else { | 1222 } else { |
1221 value = atoi((char *)&context->line_buffer[0]); 1222 context->ag_indicators[context->parser_item_index].enabled = value; 1223 log_info("Parsed Enable AG indicator pos %u('%s'): %u\n", context->parser_item_index, 1224 context->ag_indicators[context->parser_item_index].name, value); | 1223 value = atoi((char *)&hfp_connection->line_buffer[0]); 1224 hfp_connection->ag_indicators[hfp_connection->parser_item_index].enabled = value; 1225 log_info("Parsed Enable AG indicator pos %u('%s'): %u\n", hfp_connection->parser_item_index, 1226 hfp_connection->ag_indicators[hfp_connection->parser_item_index].name, value); |
1225 } | 1227 } |
1226 context->parser_item_index++; | 1228 hfp_connection->parser_item_index++; |
1227 break; 1228 case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: 1229 // indicators are indexed starting with 1 | 1229 break; 1230 case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: 1231 // indicators are indexed starting with 1 |
1230 context->parser_item_index = atoi((char *)&context->line_buffer[0]) - 1; 1231 log_info("Parsed status of the AG indicator %d, status ", context->parser_item_index); | 1232 hfp_connection->parser_item_index = atoi((char *)&hfp_connection->line_buffer[0]) - 1; 1233 log_info("Parsed status of the AG indicator %d, status ", hfp_connection->parser_item_index); |
1232 break; 1233 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: | 1234 break; 1235 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: |
1234 context->network_operator.mode = atoi((char *)&context->line_buffer[0]); 1235 log_info("Parsed network operator mode: %d, ", context->network_operator.mode); | 1236 hfp_connection->network_operator.mode = atoi((char *)&hfp_connection->line_buffer[0]); 1237 log_info("Parsed network operator mode: %d, ", hfp_connection->network_operator.mode); |
1236 break; 1237 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: | 1238 break; 1239 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: |
1238 if (context->line_buffer[0] == '3'){ 1239 log_info("Parsed Set network operator format : %s, ", context->line_buffer); | 1240 if (hfp_connection->line_buffer[0] == '3'){ 1241 log_info("Parsed Set network operator format : %s, ", hfp_connection->line_buffer); |
1240 break; 1241 } 1242 // TODO emit ERROR, wrong format | 1242 break; 1243 } 1244 // TODO emit ERROR, wrong format |
1243 log_info("ERROR Set network operator format: index %s not supported\n", context->line_buffer); | 1245 log_info("ERROR Set network operator format: index %s not supported\n", hfp_connection->line_buffer); |
1244 break; 1245 case HFP_CMD_ERROR: 1246 break; 1247 case HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR: | 1246 break; 1247 case HFP_CMD_ERROR: 1248 break; 1249 case HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR: |
1248 context->extended_audio_gateway_error = (uint8_t)atoi((char*)context->line_buffer); | 1250 hfp_connection->extended_audio_gateway_error = 1; 1251 hfp_connection->extended_audio_gateway_error_value = (uint8_t)atoi((char*)hfp_connection->line_buffer); |
1249 break; 1250 case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR: | 1252 break; 1253 case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR: |
1251 context->enable_extended_audio_gateway_error_report = (uint8_t)atoi((char*)context->line_buffer); 1252 context->ok_pending = 1; 1253 context->extended_audio_gateway_error = 0; | 1254 hfp_connection->enable_extended_audio_gateway_error_report = (uint8_t)atoi((char*)hfp_connection->line_buffer); 1255 hfp_connection->ok_pending = 1; 1256 hfp_connection->extended_audio_gateway_error = 0; |
1254 break; 1255 case HFP_CMD_AG_SENT_PHONE_NUMBER: | 1257 break; 1258 case HFP_CMD_AG_SENT_PHONE_NUMBER: |
1256 strncpy(context->bnip_number, (char *)context->line_buffer, sizeof(context->bnip_number)); 1257 context->bnip_number[sizeof(context->bnip_number)-1] = 0; | 1259 case HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE: 1260 case HFP_CMD_AG_SENT_CLIP_INFORMATION: 1261 strncpy(hfp_connection->bnip_number, (char *)hfp_connection->line_buffer, sizeof(hfp_connection->bnip_number)); 1262 hfp_connection->bnip_number[sizeof(hfp_connection->bnip_number)-1] = 0; |
1258 break; 1259 default: 1260 break; 1261 } 1262} 1263 1264void hfp_establish_service_level_connection(bd_addr_t bd_addr, uint16_t service_uuid){ | 1263 break; 1264 default: 1265 break; 1266 } 1267} 1268 1269void hfp_establish_service_level_connection(bd_addr_t bd_addr, uint16_t service_uuid){ |
1265 hfp_connection_t * context = provide_hfp_connection_context_for_bd_addr(bd_addr); 1266 log_info("hfp_connect %s, context %p", bd_addr_to_str(bd_addr), context); | 1270 hfp_connection_t * hfp_connection = provide_hfp_connection_context_for_bd_addr(bd_addr); 1271 log_info("hfp_connect %s, hfp_connection %p", bd_addr_to_str(bd_addr), hfp_connection); |
1267 | 1272 |
1268 if (!context) { | 1273 if (!hfp_connection) { |
1269 log_error("hfp_establish_service_level_connection for addr %s failed", bd_addr_to_str(bd_addr)); 1270 return; 1271 } 1272 | 1274 log_error("hfp_establish_service_level_connection for addr %s failed", bd_addr_to_str(bd_addr)); 1275 return; 1276 } 1277 |
1273 switch (context->state){ | 1278 switch (hfp_connection->state){ |
1274 case HFP_W2_DISCONNECT_RFCOMM: | 1279 case HFP_W2_DISCONNECT_RFCOMM: |
1275 context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; | 1280 hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; |
1276 return; 1277 case HFP_W4_RFCOMM_DISCONNECTED: | 1281 return; 1282 case HFP_W4_RFCOMM_DISCONNECTED: |
1278 context->state = HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART; | 1283 hfp_connection->state = HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART; |
1279 return; 1280 case HFP_IDLE: | 1284 return; 1285 case HFP_IDLE: |
1281 memcpy(context->remote_addr, bd_addr, 6); 1282 context->state = HFP_W4_SDP_EVENT_QUERY_COMPLETE; 1283 connection_doing_sdp_query = context; 1284 context->service_uuid = service_uuid; 1285 sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, context->remote_addr, service_uuid); | 1286 memcpy(hfp_connection->remote_addr, bd_addr, 6); 1287 hfp_connection->state = HFP_W4_SDP_EVENT_QUERY_COMPLETE; 1288 connection_doing_sdp_query = hfp_connection; 1289 hfp_connection->service_uuid = service_uuid; 1290 sdp_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, hfp_connection->remote_addr, service_uuid); |
1286 break; 1287 default: 1288 break; 1289 } 1290} 1291 | 1291 break; 1292 default: 1293 break; 1294 } 1295} 1296 |
1292void hfp_release_service_level_connection(hfp_connection_t * context){ 1293 if (!context) return; 1294 1295 if (context->state < HFP_W4_RFCOMM_CONNECTED){ 1296 context->state = HFP_IDLE; | 1297void hfp_release_service_level_connection(hfp_connection_t * hfp_connection){ 1298 if (!hfp_connection) return; 1299 hfp_release_audio_connection(hfp_connection); 1300 1301 if (hfp_connection->state < HFP_W4_RFCOMM_CONNECTED){ 1302 hfp_connection->state = HFP_IDLE; |
1297 return; 1298 } 1299 | 1303 return; 1304 } 1305 |
1300 if (context->state == HFP_W4_RFCOMM_CONNECTED){ 1301 context->state = HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN; | 1306 if (hfp_connection->state == HFP_W4_RFCOMM_CONNECTED){ 1307 hfp_connection->state = HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN; |
1302 return; 1303 } 1304 | 1308 return; 1309 } 1310 |
1305 if (context->state < HFP_W4_SCO_CONNECTED){ 1306 context->state = HFP_W2_DISCONNECT_RFCOMM; | 1311 if (hfp_connection->state < HFP_W4_SCO_CONNECTED){ 1312 hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM; |
1307 return; 1308 } 1309 | 1313 return; 1314 } 1315 |
1310 if (context->state < HFP_W4_SCO_DISCONNECTED){ 1311 context->state = HFP_W2_DISCONNECT_SCO; | 1316 if (hfp_connection->state < HFP_W4_SCO_DISCONNECTED){ 1317 hfp_connection->state = HFP_W2_DISCONNECT_SCO; |
1312 return; 1313 } 1314 1315 return; 1316} 1317 | 1318 return; 1319 } 1320 1321 return; 1322} 1323 |
1318void hfp_release_audio_connection(hfp_connection_t * context){ 1319 if (!context) return; 1320 if (context->state >= HFP_W2_DISCONNECT_SCO) return; 1321 context->release_audio_connection = 1; | 1324void hfp_release_audio_connection(hfp_connection_t * hfp_connection){ 1325 if (!hfp_connection) return; 1326 if (hfp_connection->state >= HFP_W2_DISCONNECT_SCO) return; 1327 hfp_connection->release_audio_connection = 1; |
1322} 1323 1324static const struct link_settings { 1325 const uint16_t max_latency; 1326 const uint8_t retransmission_effort; 1327 const uint16_t packet_types; 1328} hfp_link_settings [] = { 1329 { 0xffff, 0xff, 0x03c1 }, // HFP_LINK_SETTINGS_D0, HV1 --- 15 unchanged lines hidden --- | 1328} 1329 1330static const struct link_settings { 1331 const uint16_t max_latency; 1332 const uint8_t retransmission_effort; 1333 const uint16_t packet_types; 1334} hfp_link_settings [] = { 1335 { 0xffff, 0xff, 0x03c1 }, // HFP_LINK_SETTINGS_D0, HV1 --- 15 unchanged lines hidden --- |