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 ---