hfp_ag.c (fc64f94a8301d3d0e398cde6b9b488722d71c2fc) hfp_ag.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

--- 74 unchanged lines hidden (view full) ---

83static uint16_t hfp_supported_features = HFP_DEFAULT_AG_SUPPORTED_FEATURES;
84
85static uint8_t hfp_codecs_nr = 0;
86static uint8_t hfp_codecs[HFP_MAX_NUM_CODECS];
87
88static int hfp_ag_indicators_nr = 0;
89static hfp_ag_indicator_t hfp_ag_indicators[HFP_MAX_NUM_AG_INDICATORS];
90
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

--- 74 unchanged lines hidden (view full) ---

83static uint16_t hfp_supported_features = HFP_DEFAULT_AG_SUPPORTED_FEATURES;
84
85static uint8_t hfp_codecs_nr = 0;
86static uint8_t hfp_codecs[HFP_MAX_NUM_CODECS];
87
88static int hfp_ag_indicators_nr = 0;
89static hfp_ag_indicator_t hfp_ag_indicators[HFP_MAX_NUM_AG_INDICATORS];
90
91static int hfp_generic_status_indicators_nr = 0;
92static hfp_generic_status_indicator_t hfp_generic_status_indicators[HFP_MAX_NUM_HF_INDICATORS];
93
91static int hfp_ag_call_hold_services_nr = 0;
92static char *hfp_ag_call_hold_services[6];
93static hfp_callback_t hfp_callback;
94
95static hfp_response_and_hold_state_t hfp_ag_response_and_hold_state;
96static int hfp_ag_response_and_hold_active = 0;
97
98// Subcriber information entries
99static hfp_phone_number_t * subscriber_numbers = NULL;
100static int subscriber_numbers_count = 0;
101
102static btstack_packet_callback_registration_t hci_event_callback_registration;
103
104
94static int hfp_ag_call_hold_services_nr = 0;
95static char *hfp_ag_call_hold_services[6];
96static hfp_callback_t hfp_callback;
97
98static hfp_response_and_hold_state_t hfp_ag_response_and_hold_state;
99static int hfp_ag_response_and_hold_active = 0;
100
101// Subcriber information entries
102static hfp_phone_number_t * subscriber_numbers = NULL;
103static int subscriber_numbers_count = 0;
104
105static btstack_packet_callback_registration_t hci_event_callback_registration;
106
107
105hfp_ag_indicator_t * get_hfp_ag_indicators(hfp_connection_t * context){
106 // TODO: save only value, and value changed in the context?
107 if (context->ag_indicators_nr != hfp_ag_indicators_nr){
108 context->ag_indicators_nr = hfp_ag_indicators_nr;
109 memcpy(context->ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
108static int hfp_ag_get_ag_indicators_nr(hfp_connection_t * hfp_connection){
109 if (hfp_connection->ag_indicators_nr != hfp_ag_indicators_nr){
110 hfp_connection->ag_indicators_nr = hfp_ag_indicators_nr;
111 memcpy(hfp_connection->ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
110 }
112 }
111 return (hfp_ag_indicator_t *)&(context->ag_indicators);
113 return hfp_connection->ag_indicators_nr;
112}
113
114}
115
116hfp_ag_indicator_t * hfp_ag_get_ag_indicators(hfp_connection_t * hfp_connection){
117 // TODO: save only value, and value changed in the hfp_connection?
118 if (hfp_connection->ag_indicators_nr != hfp_ag_indicators_nr){
119 hfp_connection->ag_indicators_nr = hfp_ag_indicators_nr;
120 memcpy(hfp_connection->ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
121 }
122 return (hfp_ag_indicator_t *)&(hfp_connection->ag_indicators);
123}
124
114static hfp_ag_indicator_t * get_ag_indicator_for_name(const char * name){
115 int i;
116 for (i = 0; i < hfp_ag_indicators_nr; i++){
117 if (strcmp(hfp_ag_indicators[i].name, name) == 0){
118 return &hfp_ag_indicators[i];
119 }
120 }
121 return NULL;

--- 4 unchanged lines hidden (view full) ---

126 for (i = 0; i < hfp_ag_indicators_nr; i++){
127 if (strcmp(hfp_ag_indicators[i].name, name) == 0){
128 return i;
129 }
130 }
131 return -1;
132}
133
125static hfp_ag_indicator_t * get_ag_indicator_for_name(const char * name){
126 int i;
127 for (i = 0; i < hfp_ag_indicators_nr; i++){
128 if (strcmp(hfp_ag_indicators[i].name, name) == 0){
129 return &hfp_ag_indicators[i];
130 }
131 }
132 return NULL;

--- 4 unchanged lines hidden (view full) ---

137 for (i = 0; i < hfp_ag_indicators_nr; i++){
138 if (strcmp(hfp_ag_indicators[i].name, name) == 0){
139 return i;
140 }
141 }
142 return -1;
143}
144
134void set_hfp_ag_indicators(hfp_ag_indicator_t * indicators, int indicator_nr){
135 memcpy(hfp_ag_indicators, indicators, indicator_nr * sizeof(hfp_ag_indicator_t));
136 hfp_ag_indicators_nr = indicator_nr;
137}
138
145
139int get_hfp_ag_indicators_nr(hfp_connection_t * context){
140 if (context->ag_indicators_nr != hfp_ag_indicators_nr){
141 context->ag_indicators_nr = hfp_ag_indicators_nr;
142 memcpy(context->ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t));
143 }
144 return context->ag_indicators_nr;
145}
146
147
148void hfp_ag_register_packet_handler(hfp_callback_t callback){
149 if (callback == NULL){
150 log_error("hfp_ag_register_packet_handler called with NULL callback");
151 return;
152 }
153 hfp_callback = callback;
154 hfp_set_callback(callback);
155}
156
157static int use_in_band_tone(){
158 return get_bit(hfp_supported_features, HFP_AGSF_IN_BAND_RING_TONE);
159}
160
146void hfp_ag_register_packet_handler(hfp_callback_t callback){
147 if (callback == NULL){
148 log_error("hfp_ag_register_packet_handler called with NULL callback");
149 return;
150 }
151 hfp_callback = callback;
152 hfp_set_callback(callback);
153}
154
155static int use_in_band_tone(){
156 return get_bit(hfp_supported_features, HFP_AGSF_IN_BAND_RING_TONE);
157}
158
161static int has_codec_negotiation_feature(hfp_connection_t * connection){
162 int hf = get_bit(connection->remote_supported_features, HFP_HFSF_CODEC_NEGOTIATION);
159static int has_codec_negotiation_feature(hfp_connection_t * hfp_connection){
160 int hf = get_bit(hfp_connection->remote_supported_features, HFP_HFSF_CODEC_NEGOTIATION);
163 int ag = get_bit(hfp_supported_features, HFP_AGSF_CODEC_NEGOTIATION);
164 return hf && ag;
165}
166
161 int ag = get_bit(hfp_supported_features, HFP_AGSF_CODEC_NEGOTIATION);
162 return hf && ag;
163}
164
167static int has_call_waiting_and_3way_calling_feature(hfp_connection_t * connection){
168 int hf = get_bit(connection->remote_supported_features, HFP_HFSF_THREE_WAY_CALLING);
165static int has_call_waiting_and_3way_calling_feature(hfp_connection_t * hfp_connection){
166 int hf = get_bit(hfp_connection->remote_supported_features, HFP_HFSF_THREE_WAY_CALLING);
169 int ag = get_bit(hfp_supported_features, HFP_AGSF_THREE_WAY_CALLING);
170 return hf && ag;
171}
172
167 int ag = get_bit(hfp_supported_features, HFP_AGSF_THREE_WAY_CALLING);
168 return hf && ag;
169}
170
173static int has_hf_indicators_feature(hfp_connection_t * connection){
174 int hf = get_bit(connection->remote_supported_features, HFP_HFSF_HF_INDICATORS);
171static int has_hf_indicators_feature(hfp_connection_t * hfp_connection){
172 int hf = get_bit(hfp_connection->remote_supported_features, HFP_HFSF_HF_INDICATORS);
175 int ag = get_bit(hfp_supported_features, HFP_AGSF_HF_INDICATORS);
176 return hf && ag;
177}
178
179void hfp_ag_create_sdp_record(uint8_t * service, uint32_t service_record_handle, int rfcomm_channel_nr, const char * name, uint8_t ability_to_reject_call, uint16_t supported_features){
180 if (!name){
181 name = default_hfp_ag_service_name;
182 }

--- 47 unchanged lines hidden (view full) ---

230static int hfp_ag_send_phone_number_for_voice_tag_cmd(uint16_t cid){
231 char buffer[50];
232 sprintf(buffer, "\r\n%s: %s\r\n", HFP_PHONE_NUMBER_FOR_VOICE_TAG, hfp_gsm_clip_number());
233 return send_str_over_rfcomm(cid, buffer);
234}
235
236static int hfp_ag_send_call_waiting_notification(uint16_t cid){
237 char buffer[50];
173 int ag = get_bit(hfp_supported_features, HFP_AGSF_HF_INDICATORS);
174 return hf && ag;
175}
176
177void hfp_ag_create_sdp_record(uint8_t * service, uint32_t service_record_handle, int rfcomm_channel_nr, const char * name, uint8_t ability_to_reject_call, uint16_t supported_features){
178 if (!name){
179 name = default_hfp_ag_service_name;
180 }

--- 47 unchanged lines hidden (view full) ---

228static int hfp_ag_send_phone_number_for_voice_tag_cmd(uint16_t cid){
229 char buffer[50];
230 sprintf(buffer, "\r\n%s: %s\r\n", HFP_PHONE_NUMBER_FOR_VOICE_TAG, hfp_gsm_clip_number());
231 return send_str_over_rfcomm(cid, buffer);
232}
233
234static int hfp_ag_send_call_waiting_notification(uint16_t cid){
235 char buffer[50];
238 sprintf(buffer, "\r\n+CCWA: \"%s\",%u\r\n", hfp_gsm_clip_number(), hfp_gsm_clip_type());
236 sprintf(buffer, "\r\n%s: \"%s\",%u\r\n", HFP_ENABLE_CALL_WAITING_NOTIFICATION, hfp_gsm_clip_number(), hfp_gsm_clip_type());
239 return send_str_over_rfcomm(cid, buffer);
240}
241
242static int hfp_ag_error(uint16_t cid){
243 char buffer[10];
244 sprintf(buffer, "\r\nERROR\r\n");
245 return send_str_over_rfcomm(cid, buffer);
246}

--- 14 unchanged lines hidden (view full) ---

261 if (i < 1000000) return 6;
262 if (i < 10000000) return 7;
263 if (i < 100000000) return 8;
264 if (i < 1000000000) return 9;
265 return 10;
266}
267
268// get size for indicator string
237 return send_str_over_rfcomm(cid, buffer);
238}
239
240static int hfp_ag_error(uint16_t cid){
241 char buffer[10];
242 sprintf(buffer, "\r\nERROR\r\n");
243 return send_str_over_rfcomm(cid, buffer);
244}

--- 14 unchanged lines hidden (view full) ---

259 if (i < 1000000) return 6;
260 if (i < 10000000) return 7;
261 if (i < 100000000) return 8;
262 if (i < 1000000000) return 9;
263 return 10;
264}
265
266// get size for indicator string
269static int hfp_ag_indicators_string_size(hfp_connection_t * context, int i){
267static int hfp_ag_indicators_string_size(hfp_connection_t * hfp_connection, int i){
270 // template: ("$NAME",($MIN,$MAX))
268 // template: ("$NAME",($MIN,$MAX))
271 return 8 + strlen(get_hfp_ag_indicators(context)[i].name)
272 + string_len_for_uint32(get_hfp_ag_indicators(context)[i].min_range)
273 + string_len_for_uint32(get_hfp_ag_indicators(context)[i].min_range);
269 return 8 + strlen(hfp_ag_get_ag_indicators(hfp_connection)[i].name)
270 + string_len_for_uint32(hfp_ag_get_ag_indicators(hfp_connection)[i].min_range)
271 + string_len_for_uint32(hfp_ag_get_ag_indicators(hfp_connection)[i].min_range);
274}
275
276// store indicator
272}
273
274// store indicator
277static void hfp_ag_indicators_string_store(hfp_connection_t * context, int i, uint8_t * buffer){
275static void hfp_ag_indicators_string_store(hfp_connection_t * hfp_connection, int i, uint8_t * buffer){
278 sprintf((char *) buffer, "(\"%s\",(%d,%d)),",
276 sprintf((char *) buffer, "(\"%s\",(%d,%d)),",
279 get_hfp_ag_indicators(context)[i].name,
280 get_hfp_ag_indicators(context)[i].min_range,
281 get_hfp_ag_indicators(context)[i].max_range);
277 hfp_ag_get_ag_indicators(hfp_connection)[i].name,
278 hfp_ag_get_ag_indicators(hfp_connection)[i].min_range,
279 hfp_ag_get_ag_indicators(hfp_connection)[i].max_range);
282}
283
284// structure: header [indicator [comma indicator]] footer
280}
281
282// structure: header [indicator [comma indicator]] footer
285static int hfp_ag_indicators_cmd_generator_num_segments(hfp_connection_t * context){
286 int num_indicators = get_hfp_ag_indicators_nr(context);
283static int hfp_ag_indicators_cmd_generator_num_segments(hfp_connection_t * hfp_connection){
284 int num_indicators = hfp_ag_get_ag_indicators_nr(hfp_connection);
287 if (!num_indicators) return 2;
288 return 3 + (num_indicators-1) * 2;
289}
290
291// get size of individual segment for hfp_ag_retrieve_indicators_cmd
285 if (!num_indicators) return 2;
286 return 3 + (num_indicators-1) * 2;
287}
288
289// get size of individual segment for hfp_ag_retrieve_indicators_cmd
292static int hfp_ag_indicators_cmd_generator_get_segment_len(hfp_connection_t * context, int index){
290static int hfp_ag_indicators_cmd_generator_get_segment_len(hfp_connection_t * hfp_connection, int index){
293 if (index == 0) {
294 return strlen(HFP_INDICATOR) + 3; // "\n\r%s:""
295 }
296 index--;
291 if (index == 0) {
292 return strlen(HFP_INDICATOR) + 3; // "\n\r%s:""
293 }
294 index--;
297 int num_indicators = get_hfp_ag_indicators_nr(context);
295 int num_indicators = hfp_ag_get_ag_indicators_nr(hfp_connection);
298 int indicator_index = index >> 1;
299 if ((index & 1) == 0){
296 int indicator_index = index >> 1;
297 if ((index & 1) == 0){
300 return hfp_ag_indicators_string_size(context, indicator_index);
298 return hfp_ag_indicators_string_size(hfp_connection, indicator_index);
301 }
302 if (indicator_index == num_indicators - 1){
303 return 8; // "\r\n\r\nOK\r\n"
304 }
305 return 1; // comma
306}
307
299 }
300 if (indicator_index == num_indicators - 1){
301 return 8; // "\r\n\r\nOK\r\n"
302 }
303 return 1; // comma
304}
305
308static void hgp_ag_indicators_cmd_generator_store_segment(hfp_connection_t * context, int index, uint8_t * buffer){
306static void hgp_ag_indicators_cmd_generator_store_segment(hfp_connection_t * hfp_connection, int index, uint8_t * buffer){
309 if (index == 0){
310 *buffer++ = '\r';
311 *buffer++ = '\n';
312 int len = strlen(HFP_INDICATOR);
313 memcpy(buffer, HFP_INDICATOR, len);
314 buffer += len;
315 *buffer++ = ':';
316 return;
317 }
318 index--;
307 if (index == 0){
308 *buffer++ = '\r';
309 *buffer++ = '\n';
310 int len = strlen(HFP_INDICATOR);
311 memcpy(buffer, HFP_INDICATOR, len);
312 buffer += len;
313 *buffer++ = ':';
314 return;
315 }
316 index--;
319 int num_indicators = get_hfp_ag_indicators_nr(context);
317 int num_indicators = hfp_ag_get_ag_indicators_nr(hfp_connection);
320 int indicator_index = index >> 1;
321 if ((index & 1) == 0){
318 int indicator_index = index >> 1;
319 if ((index & 1) == 0){
322 hfp_ag_indicators_string_store(context, indicator_index, buffer);
320 hfp_ag_indicators_string_store(hfp_connection, indicator_index, buffer);
323 return;
324 }
325 if (indicator_index == num_indicators-1){
326 memcpy(buffer, "\r\n\r\nOK\r\n", 8);
327 return;
328 }
329 *buffer = ',';
330}
331
332static int hfp_hf_indicators_join(char * buffer, int buffer_size){
333 if (buffer_size < hfp_ag_indicators_nr * 3) return 0;
334 int i;
335 int offset = 0;
321 return;
322 }
323 if (indicator_index == num_indicators-1){
324 memcpy(buffer, "\r\n\r\nOK\r\n", 8);
325 return;
326 }
327 *buffer = ',';
328}
329
330static int hfp_hf_indicators_join(char * buffer, int buffer_size){
331 if (buffer_size < hfp_ag_indicators_nr * 3) return 0;
332 int i;
333 int offset = 0;
336 for (i = 0; i < get_hfp_generic_status_indicators_nr()-1; i++) {
337 offset += snprintf(buffer+offset, buffer_size-offset, "%d,", get_hfp_generic_status_indicators()[i].uuid);
334 for (i = 0; i < hfp_generic_status_indicators_nr-1; i++) {
335 offset += snprintf(buffer+offset, buffer_size-offset, "%d,", hfp_generic_status_indicators[i].uuid);
338 }
336 }
339 if (i < get_hfp_generic_status_indicators_nr()){
340 offset += snprintf(buffer+offset, buffer_size-offset, "%d,", get_hfp_generic_status_indicators()[i].uuid);
337 if (i < hfp_generic_status_indicators_nr){
338 offset += snprintf(buffer+offset, buffer_size-offset, "%d,", hfp_generic_status_indicators[i].uuid);
341 }
342 return offset;
343}
344
345static int hfp_hf_indicators_initial_status_join(char * buffer, int buffer_size){
339 }
340 return offset;
341}
342
343static int hfp_hf_indicators_initial_status_join(char * buffer, int buffer_size){
346 if (buffer_size < get_hfp_generic_status_indicators_nr() * 3) return 0;
344 if (buffer_size < hfp_generic_status_indicators_nr * 3) return 0;
347 int i;
348 int offset = 0;
345 int i;
346 int offset = 0;
349 for (i = 0; i < get_hfp_generic_status_indicators_nr(); i++) {
350 offset += snprintf(buffer+offset, buffer_size-offset, "\r\n%s:%d,%d\r\n", HFP_GENERIC_STATUS_INDICATOR, get_hfp_generic_status_indicators()[i].uuid, get_hfp_generic_status_indicators()[i].state);
347 for (i = 0; i < hfp_generic_status_indicators_nr; i++) {
348 offset += snprintf(buffer+offset, buffer_size-offset, "\r\n%s:%d,%d\r\n", HFP_GENERIC_STATUS_INDICATOR, hfp_generic_status_indicators[i].uuid, hfp_generic_status_indicators[i].state);
351 }
352 return offset;
353}
354
355static int hfp_ag_indicators_status_join(char * buffer, int buffer_size){
356 if (buffer_size < hfp_ag_indicators_nr * 3) return 0;
357 int i;
358 int offset = 0;

--- 14 unchanged lines hidden (view full) ---

373 offset += snprintf(buffer+offset, buffer_size-offset, "%s,", hfp_ag_call_hold_services[i]);
374 }
375 if (i<hfp_ag_call_hold_services_nr){
376 offset += snprintf(buffer+offset, buffer_size-offset, "%s)", hfp_ag_call_hold_services[i]);
377 }
378 return offset;
379}
380
349 }
350 return offset;
351}
352
353static int hfp_ag_indicators_status_join(char * buffer, int buffer_size){
354 if (buffer_size < hfp_ag_indicators_nr * 3) return 0;
355 int i;
356 int offset = 0;

--- 14 unchanged lines hidden (view full) ---

371 offset += snprintf(buffer+offset, buffer_size-offset, "%s,", hfp_ag_call_hold_services[i]);
372 }
373 if (i<hfp_ag_call_hold_services_nr){
374 offset += snprintf(buffer+offset, buffer_size-offset, "%s)", hfp_ag_call_hold_services[i]);
375 }
376 return offset;
377}
378
381static int hfp_ag_cmd_via_generator(uint16_t cid, hfp_connection_t * context,
379static int hfp_ag_cmd_via_generator(uint16_t cid, hfp_connection_t * hfp_connection,
382 int start_segment, int num_segments,
380 int start_segment, int num_segments,
383 int (*get_segment_len)(hfp_connection_t * context, int segment),
384 void (*store_segment) (hfp_connection_t * context, int segment, uint8_t * buffer)){
381 int (*get_segment_len)(hfp_connection_t * hfp_connection, int segment),
382 void (*store_segment) (hfp_connection_t * hfp_connection, int segment, uint8_t * buffer)){
385
386 // assumes: can send now == true
387 // assumes: num segments > 0
388 rfcomm_reserve_packet_buffer();
389 int mtu = rfcomm_get_max_frame_size(cid);
390 uint8_t * data = rfcomm_get_outgoing_buffer();
391 int offset = 0;
392 int segment = start_segment;
393 while (segment < num_segments){
383
384 // assumes: can send now == true
385 // assumes: num segments > 0
386 rfcomm_reserve_packet_buffer();
387 int mtu = rfcomm_get_max_frame_size(cid);
388 uint8_t * data = rfcomm_get_outgoing_buffer();
389 int offset = 0;
390 int segment = start_segment;
391 while (segment < num_segments){
394 int segment_len = get_segment_len(context, segment);
392 int segment_len = get_segment_len(hfp_connection, segment);
395 if (offset + segment_len <= mtu){
393 if (offset + segment_len <= mtu){
396 store_segment(context, segment, data+offset);
394 store_segment(hfp_connection, segment, data+offset);
397 offset += segment_len;
398 segment++;
399 }
400 }
401 rfcomm_send_prepared(cid, offset);
402 return segment;
403}
404
405// returns next segment to store
395 offset += segment_len;
396 segment++;
397 }
398 }
399 rfcomm_send_prepared(cid, offset);
400 return segment;
401}
402
403// returns next segment to store
406static int hfp_ag_retrieve_indicators_cmd_via_generator(uint16_t cid, hfp_connection_t * context, int start_segment){
407 int num_segments = hfp_ag_indicators_cmd_generator_num_segments(context);
408 return hfp_ag_cmd_via_generator(cid, context, start_segment, num_segments,
404static int hfp_ag_retrieve_indicators_cmd_via_generator(uint16_t cid, hfp_connection_t * hfp_connection, int start_segment){
405 int num_segments = hfp_ag_indicators_cmd_generator_num_segments(hfp_connection);
406 return hfp_ag_cmd_via_generator(cid, hfp_connection, start_segment, num_segments,
409 hfp_ag_indicators_cmd_generator_get_segment_len, hgp_ag_indicators_cmd_generator_store_segment);
410}
411
412static int hfp_ag_retrieve_indicators_status_cmd(uint16_t cid){
413 char buffer[40];
414 int offset = snprintf(buffer, sizeof(buffer), "\r\n%s:", HFP_INDICATOR);
415 offset += hfp_ag_indicators_status_join(buffer+offset, sizeof(buffer)-offset);
416

--- 92 unchanged lines hidden (view full) ---

509
510static int hfp_ag_set_response_and_hold(uint16_t cid, int state){
511 char buffer[30];
512 sprintf(buffer, "\r\n%s: %d\r\n", HFP_RESPONSE_AND_HOLD, state);
513 return send_str_over_rfcomm(cid, buffer);
514}
515
516
407 hfp_ag_indicators_cmd_generator_get_segment_len, hgp_ag_indicators_cmd_generator_store_segment);
408}
409
410static int hfp_ag_retrieve_indicators_status_cmd(uint16_t cid){
411 char buffer[40];
412 int offset = snprintf(buffer, sizeof(buffer), "\r\n%s:", HFP_INDICATOR);
413 offset += hfp_ag_indicators_status_join(buffer+offset, sizeof(buffer)-offset);
414

--- 92 unchanged lines hidden (view full) ---

507
508static int hfp_ag_set_response_and_hold(uint16_t cid, int state){
509 char buffer[30];
510 sprintf(buffer, "\r\n%s: %d\r\n", HFP_RESPONSE_AND_HOLD, state);
511 return send_str_over_rfcomm(cid, buffer);
512}
513
514
517static uint8_t hfp_ag_suggest_codec(hfp_connection_t *context){
515static uint8_t hfp_ag_suggest_codec(hfp_connection_t *hfp_connection){
518 int i,j;
519 uint8_t codec = HFP_CODEC_CVSD;
520 for (i = 0; i < hfp_codecs_nr; i++){
516 int i,j;
517 uint8_t codec = HFP_CODEC_CVSD;
518 for (i = 0; i < hfp_codecs_nr; i++){
521 for (j = 0; j < context->remote_codecs_nr; j++){
522 if (context->remote_codecs[j] == hfp_codecs[i]){
523 codec = context->remote_codecs[j];
519 for (j = 0; j < hfp_connection->remote_codecs_nr; j++){
520 if (hfp_connection->remote_codecs[j] == hfp_codecs[i]){
521 codec = hfp_connection->remote_codecs[j];
524 continue;
525 }
526 }
527 }
528 return codec;
529}
530
522 continue;
523 }
524 }
525 }
526 return codec;
527}
528
531static int codecs_exchange_state_machine(hfp_connection_t * context){
529static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){
532 /* events ( == commands):
533 HFP_CMD_AVAILABLE_CODECS == received AT+BAC with list of codecs
534 HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
535 hf_trigger_codec_connection_setup == received BCC
536 ag_trigger_codec_connection_setup == received from AG to send BCS
537 HFP_CMD_HF_CONFIRMED_CODEC == received AT+BCS
538 */
539
530 /* events ( == commands):
531 HFP_CMD_AVAILABLE_CODECS == received AT+BAC with list of codecs
532 HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
533 hf_trigger_codec_connection_setup == received BCC
534 ag_trigger_codec_connection_setup == received from AG to send BCS
535 HFP_CMD_HF_CONFIRMED_CODEC == received AT+BCS
536 */
537
540 switch (context->codecs_state){
538 switch (hfp_connection->codecs_state){
541 case HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE:
539 case HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE:
542 context->command = HFP_CMD_AG_SEND_COMMON_CODEC;
540 hfp_connection->command = HFP_CMD_AG_SEND_COMMON_CODEC;
543 break;
544 case HFP_CODECS_AG_RESEND_COMMON_CODEC:
541 break;
542 case HFP_CODECS_AG_RESEND_COMMON_CODEC:
545 context->command = HFP_CMD_AG_SEND_COMMON_CODEC;
543 hfp_connection->command = HFP_CMD_AG_SEND_COMMON_CODEC;
546 break;
547 default:
548 break;
549 }
550
551 // printf(" -> State machine: CC\n");
552
544 break;
545 default:
546 break;
547 }
548
549 // printf(" -> State machine: CC\n");
550
553 switch (context->command){
551 switch (hfp_connection->command){
554 case HFP_CMD_AVAILABLE_CODECS:
555 //printf("HFP_CODECS_RECEIVED_LIST \n");
552 case HFP_CMD_AVAILABLE_CODECS:
553 //printf("HFP_CODECS_RECEIVED_LIST \n");
556 if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED){
557 context->codecs_state = HFP_CODECS_RECEIVED_LIST;
558 hfp_ag_ok(context->rfcomm_cid);
554 if (hfp_connection->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED){
555 hfp_connection->codecs_state = HFP_CODECS_RECEIVED_LIST;
556 hfp_ag_ok(hfp_connection->rfcomm_cid);
559 return 1;
560 }
561
557 return 1;
558 }
559
562 switch (context->codecs_state){
560 switch (hfp_connection->codecs_state){
563 case HFP_CODECS_AG_SENT_COMMON_CODEC:
564 case HFP_CODECS_EXCHANGED:
561 case HFP_CODECS_AG_SENT_COMMON_CODEC:
562 case HFP_CODECS_EXCHANGED:
565 context->codecs_state = HFP_CODECS_AG_RESEND_COMMON_CODEC;
563 hfp_connection->codecs_state = HFP_CODECS_AG_RESEND_COMMON_CODEC;
566 break;
567 default:
568 break;
569 }
564 break;
565 default:
566 break;
567 }
570 hfp_ag_ok(context->rfcomm_cid);
568 hfp_ag_ok(hfp_connection->rfcomm_cid);
571 return 1;
572
573 case HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
574 //printf(" HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP \n");
569 return 1;
570
571 case HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP:
572 //printf(" HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP \n");
575 context->codecs_state = HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE;
576 hfp_ag_ok(context->rfcomm_cid);
573 hfp_connection->codecs_state = HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE;
574 hfp_ag_ok(hfp_connection->rfcomm_cid);
577 return 1;
578
579 case HFP_CMD_AG_SEND_COMMON_CODEC:
580 //printf(" HFP_CMD_AG_SEND_COMMON_CODEC \n");
575 return 1;
576
577 case HFP_CMD_AG_SEND_COMMON_CODEC:
578 //printf(" HFP_CMD_AG_SEND_COMMON_CODEC \n");
581 context->codecs_state = HFP_CODECS_AG_SENT_COMMON_CODEC;
582 context->suggested_codec = hfp_ag_suggest_codec(context);
583 hfp_ag_cmd_suggest_codec(context->rfcomm_cid, context->suggested_codec);
579 hfp_connection->codecs_state = HFP_CODECS_AG_SENT_COMMON_CODEC;
580 hfp_connection->suggested_codec = hfp_ag_suggest_codec(hfp_connection);
581 hfp_ag_cmd_suggest_codec(hfp_connection->rfcomm_cid, hfp_connection->suggested_codec);
584 return 1;
585
586 case HFP_CMD_HF_CONFIRMED_CODEC:
587 //printf("HFP_CMD_HF_CONFIRMED_CODEC \n");
582 return 1;
583
584 case HFP_CMD_HF_CONFIRMED_CODEC:
585 //printf("HFP_CMD_HF_CONFIRMED_CODEC \n");
588 if (context->codec_confirmed != context->suggested_codec){
589 context->codecs_state = HFP_CODECS_ERROR;
590 hfp_ag_error(context->rfcomm_cid);
586 if (hfp_connection->codec_confirmed != hfp_connection->suggested_codec){
587 hfp_connection->codecs_state = HFP_CODECS_ERROR;
588 hfp_ag_error(hfp_connection->rfcomm_cid);
591 return 1;
592 }
589 return 1;
590 }
593 context->negotiated_codec = context->codec_confirmed;
594 context->codecs_state = HFP_CODECS_EXCHANGED;
591 hfp_connection->negotiated_codec = hfp_connection->codec_confirmed;
592 hfp_connection->codecs_state = HFP_CODECS_EXCHANGED;
595 hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0);
593 hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0);
596 hfp_ag_ok(context->rfcomm_cid);
594 hfp_ag_ok(hfp_connection->rfcomm_cid);
597 return 1;
598 default:
599 break;
600 }
601 return 0;
602}
603
595 return 1;
596 default:
597 break;
598 }
599 return 0;
600}
601
604static void hfp_init_link_settings(hfp_connection_t * context){
602static void hfp_init_link_settings(hfp_connection_t * hfp_connection){
605 // determine highest possible link setting
603 // determine highest possible link setting
606 context->link_setting = HFP_LINK_SETTINGS_D1;
607 if (hci_remote_esco_supported(context->acl_handle)){
608 context->link_setting = HFP_LINK_SETTINGS_S3;
609 if ((context->remote_supported_features & (1<<HFP_HFSF_ESCO_S4))
604 hfp_connection->link_setting = HFP_LINK_SETTINGS_D1;
605 if (hci_remote_esco_supported(hfp_connection->acl_handle)){
606 hfp_connection->link_setting = HFP_LINK_SETTINGS_S3;
607 if ((hfp_connection->remote_supported_features & (1<<HFP_HFSF_ESCO_S4))
610 && (hfp_supported_features & (1<<HFP_AGSF_ESCO_S4))){
608 && (hfp_supported_features & (1<<HFP_AGSF_ESCO_S4))){
611 context->link_setting = HFP_LINK_SETTINGS_S4;
609 hfp_connection->link_setting = HFP_LINK_SETTINGS_S4;
612 }
613 }
614}
615
610 }
611 }
612}
613
616static void hfp_ag_slc_established(hfp_connection_t * context){
617 context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
614static void hfp_ag_slc_established(hfp_connection_t * hfp_connection){
615 hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
618 hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
619
616 hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0);
617
620 hfp_init_link_settings(context);
618 hfp_init_link_settings(hfp_connection);
621
619
622 // if active call exist, set per-connection state active, too (when audio is on)
620 // if active call exist, set per-hfp_connection state active, too (when audio is on)
623 if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
621 if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
624 context->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE;
622 hfp_connection->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE;
625 }
626 // if AG is ringing, also start ringing on the HF
627 if (hfp_gsm_call_status() == HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS &&
628 hfp_gsm_callsetup_status() == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){
623 }
624 // if AG is ringing, also start ringing on the HF
625 if (hfp_gsm_call_status() == HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS &&
626 hfp_gsm_callsetup_status() == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){
629 hfp_ag_hf_start_ringing(context);
627 hfp_ag_hf_start_ringing(hfp_connection);
630 }
631}
632
628 }
629}
630
633static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * context){
634 if (context->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
631static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * hfp_connection){
632 if (hfp_connection->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
635 int done = 0;
636 // printf(" -> State machine: SLC\n");
633 int done = 0;
634 // printf(" -> State machine: SLC\n");
637 switch(context->command){
635 switch(hfp_connection->command){
638 case HFP_CMD_SUPPORTED_FEATURES:
636 case HFP_CMD_SUPPORTED_FEATURES:
639 switch(context->state){
637 switch(hfp_connection->state){
640 case HFP_W4_EXCHANGE_SUPPORTED_FEATURES:
641 case HFP_EXCHANGE_SUPPORTED_FEATURES:
638 case HFP_W4_EXCHANGE_SUPPORTED_FEATURES:
639 case HFP_EXCHANGE_SUPPORTED_FEATURES:
642 if (has_codec_negotiation_feature(context)){
643 context->state = HFP_W4_NOTIFY_ON_CODECS;
640 if (has_codec_negotiation_feature(hfp_connection)){
641 hfp_connection->state = HFP_W4_NOTIFY_ON_CODECS;
644 } else {
642 } else {
645 context->state = HFP_W4_RETRIEVE_INDICATORS;
643 hfp_connection->state = HFP_W4_RETRIEVE_INDICATORS;
646 }
644 }
647 hfp_ag_exchange_supported_features_cmd(context->rfcomm_cid);
645 hfp_ag_exchange_supported_features_cmd(hfp_connection->rfcomm_cid);
648 return 1;
649 default:
650 break;
651 }
652 break;
653 case HFP_CMD_AVAILABLE_CODECS:
646 return 1;
647 default:
648 break;
649 }
650 break;
651 case HFP_CMD_AVAILABLE_CODECS:
654 done = codecs_exchange_state_machine(context);
652 done = codecs_exchange_state_machine(hfp_connection);
655
653
656 if (context->codecs_state == HFP_CODECS_RECEIVED_LIST){
657 context->state = HFP_W4_RETRIEVE_INDICATORS;
654 if (hfp_connection->codecs_state == HFP_CODECS_RECEIVED_LIST){
655 hfp_connection->state = HFP_W4_RETRIEVE_INDICATORS;
658 }
659 return done;
660
661 case HFP_CMD_RETRIEVE_AG_INDICATORS:
656 }
657 return done;
658
659 case HFP_CMD_RETRIEVE_AG_INDICATORS:
662 if (context->state == HFP_W4_RETRIEVE_INDICATORS) {
663 context->command = HFP_CMD_NONE; // prevent reentrance
664 int next_segment = hfp_ag_retrieve_indicators_cmd_via_generator(context->rfcomm_cid, context, context->send_ag_indicators_segment);
665 if (next_segment < hfp_ag_indicators_cmd_generator_num_segments(context)){
660 if (hfp_connection->state == HFP_W4_RETRIEVE_INDICATORS) {
661 hfp_connection->command = HFP_CMD_NONE; // prevent reentrance
662 int next_segment = hfp_ag_retrieve_indicators_cmd_via_generator(hfp_connection->rfcomm_cid, hfp_connection, hfp_connection->send_ag_indicators_segment);
663 if (next_segment < hfp_ag_indicators_cmd_generator_num_segments(hfp_connection)){
666 // prepare sending of next segment
664 // prepare sending of next segment
667 context->send_ag_indicators_segment = next_segment;
668 context->command = HFP_CMD_RETRIEVE_AG_INDICATORS;
665 hfp_connection->send_ag_indicators_segment = next_segment;
666 hfp_connection->command = HFP_CMD_RETRIEVE_AG_INDICATORS;
669 } else {
670 // done, go to next state
667 } else {
668 // done, go to next state
671 context->send_ag_indicators_segment = 0;
672 context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
669 hfp_connection->send_ag_indicators_segment = 0;
670 hfp_connection->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
673 }
674 return 1;
675 }
676 break;
677
678 case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
671 }
672 return 1;
673 }
674 break;
675
676 case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
679 if (context->state != HFP_W4_RETRIEVE_INDICATORS_STATUS) break;
680 context->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE;
681 hfp_ag_retrieve_indicators_status_cmd(context->rfcomm_cid);
677 if (hfp_connection->state != HFP_W4_RETRIEVE_INDICATORS_STATUS) break;
678 hfp_connection->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE;
679 hfp_ag_retrieve_indicators_status_cmd(hfp_connection->rfcomm_cid);
682 return 1;
683
684 case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE:
680 return 1;
681
682 case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE:
685 if (context->state != HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE) break;
686 if (has_call_waiting_and_3way_calling_feature(context)){
687 context->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL;
688 } else if (has_hf_indicators_feature(context)){
689 context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
683 if (hfp_connection->state != HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE) break;
684 if (has_call_waiting_and_3way_calling_feature(hfp_connection)){
685 hfp_connection->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL;
686 } else if (has_hf_indicators_feature(hfp_connection)){
687 hfp_connection->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
690 } else {
688 } else {
691 hfp_ag_slc_established(context);
689 hfp_ag_slc_established(hfp_connection);
692 }
690 }
693 hfp_ag_set_indicator_status_update_cmd(context->rfcomm_cid, 1);
691 hfp_ag_set_indicator_status_update_cmd(hfp_connection->rfcomm_cid, 1);
694 return 1;
695
696 case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES:
692 return 1;
693
694 case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES:
697 if (context->state != HFP_W4_RETRIEVE_CAN_HOLD_CALL) break;
698 if (has_hf_indicators_feature(context)){
699 context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
695 if (hfp_connection->state != HFP_W4_RETRIEVE_CAN_HOLD_CALL) break;
696 if (has_hf_indicators_feature(hfp_connection)){
697 hfp_connection->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
700 }
698 }
701 hfp_ag_retrieve_can_hold_call_cmd(context->rfcomm_cid);
702 if (!has_hf_indicators_feature(context)){
703 hfp_ag_slc_established(context);
699 hfp_ag_retrieve_can_hold_call_cmd(hfp_connection->rfcomm_cid);
700 if (!has_hf_indicators_feature(hfp_connection)){
701 hfp_ag_slc_established(hfp_connection);
704 }
705 return 1;
706
707 case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS:
702 }
703 return 1;
704
705 case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS:
708 if (context->state != HFP_W4_LIST_GENERIC_STATUS_INDICATORS) break;
709 context->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS;
710 hfp_ag_list_supported_generic_status_indicators_cmd(context->rfcomm_cid);
706 if (hfp_connection->state != HFP_W4_LIST_GENERIC_STATUS_INDICATORS) break;
707 hfp_connection->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS;
708 hfp_ag_list_supported_generic_status_indicators_cmd(hfp_connection->rfcomm_cid);
711 return 1;
712
713 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS:
709 return 1;
710
711 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS:
714 if (context->state != HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS) break;
715 context->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
716 hfp_ag_retrieve_supported_generic_status_indicators_cmd(context->rfcomm_cid);
712 if (hfp_connection->state != HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS) break;
713 hfp_connection->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS;
714 hfp_ag_retrieve_supported_generic_status_indicators_cmd(hfp_connection->rfcomm_cid);
717 return 1;
718
719 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE:
715 return 1;
716
717 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE:
720 if (context->state != HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS) break;
721 hfp_ag_slc_established(context);
722 hfp_ag_retrieve_initital_supported_generic_status_indicators_cmd(context->rfcomm_cid);
718 if (hfp_connection->state != HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS) break;
719 hfp_ag_slc_established(hfp_connection);
720 hfp_ag_retrieve_initital_supported_generic_status_indicators_cmd(hfp_connection->rfcomm_cid);
723 return 1;
724 default:
725 break;
726 }
727 return done;
728}
729
721 return 1;
722 default:
723 break;
724 }
725 return done;
726}
727
730static int hfp_ag_run_for_context_service_level_connection_queries(hfp_connection_t * context){
731 // if (context->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
728static int hfp_ag_run_for_context_service_level_connection_queries(hfp_connection_t * hfp_connection){
729 // if (hfp_connection->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
732
730
733 int done = codecs_exchange_state_machine(context);
731 int done = codecs_exchange_state_machine(hfp_connection);
734 if (done) return done;
735
736 // printf(" -> State machine: SLC Queries\n");
732 if (done) return done;
733
734 // printf(" -> State machine: SLC Queries\n");
737 switch(context->command){
735 switch(hfp_connection->command){
738 case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION:
736 case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION:
739 hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION, context->ag_activate_voice_recognition);
740 hfp_ag_activate_voice_recognition_cmd(context->rfcomm_cid, context->ag_activate_voice_recognition);
737 hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION, hfp_connection->ag_activate_voice_recognition);
738 hfp_ag_activate_voice_recognition_cmd(hfp_connection->rfcomm_cid, hfp_connection->ag_activate_voice_recognition);
741 return 1;
742 case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION:
743 if (get_bit(hfp_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION)){
739 return 1;
740 case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION:
741 if (get_bit(hfp_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION)){
744 hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION, context->ag_activate_voice_recognition);
745 hfp_ag_ok(context->rfcomm_cid);
746 hfp_ag_setup_audio_connection(context);
742 hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION, hfp_connection->ag_activate_voice_recognition);
743 hfp_ag_ok(hfp_connection->rfcomm_cid);
744 hfp_ag_setup_audio_connection(hfp_connection);
747 } else {
745 } else {
748 hfp_ag_error(context->rfcomm_cid);
746 hfp_ag_error(hfp_connection->rfcomm_cid);
749 }
750 return 1;
751 case HFP_CMD_CHANGE_IN_BAND_RING_TONE_SETTING:
747 }
748 return 1;
749 case HFP_CMD_CHANGE_IN_BAND_RING_TONE_SETTING:
752 hfp_ag_change_in_band_ring_tone_setting_cmd(context->rfcomm_cid);
750 hfp_ag_change_in_band_ring_tone_setting_cmd(hfp_connection->rfcomm_cid);
753 return 1;
754 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME:
751 return 1;
752 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME:
755 hfp_ag_report_network_operator_name_cmd(context->rfcomm_cid, context->network_operator);
753 hfp_ag_report_network_operator_name_cmd(hfp_connection->rfcomm_cid, hfp_connection->network_operator);
756 return 1;
757 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT:
754 return 1;
755 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT:
758 if (context->network_operator.format != 0){
759 hfp_ag_error(context->rfcomm_cid);
756 if (hfp_connection->network_operator.format != 0){
757 hfp_ag_error(hfp_connection->rfcomm_cid);
760 } else {
758 } else {
761 hfp_ag_ok(context->rfcomm_cid);
759 hfp_ag_ok(hfp_connection->rfcomm_cid);
762 }
763 return 1;
764 case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE:
760 }
761 return 1;
762 case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE:
765 hfp_ag_ok(context->rfcomm_cid);
763 hfp_ag_ok(hfp_connection->rfcomm_cid);
766 return 1;
767 case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR:
764 return 1;
765 case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR:
768 if (context->extended_audio_gateway_error){
769 context->extended_audio_gateway_error = 0;
770 hfp_ag_report_extended_audio_gateway_error(context->rfcomm_cid, context->extended_audio_gateway_error);
766 if (hfp_connection->extended_audio_gateway_error){
767 hfp_connection->extended_audio_gateway_error = 0;
768 hfp_ag_report_extended_audio_gateway_error(hfp_connection->rfcomm_cid, hfp_connection->extended_audio_gateway_error_value);
771 return 1;
772 }
773 case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE:
769 return 1;
770 }
771 case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE:
774 hfp_ag_ok(context->rfcomm_cid);
772 hfp_ag_ok(hfp_connection->rfcomm_cid);
775 return 1;
776 default:
777 break;
778 }
779 return 0;
780}
781
773 return 1;
774 default:
775 break;
776 }
777 return 0;
778}
779
782static int hfp_ag_run_for_audio_connection(hfp_connection_t * context){
783 if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED ||
784 context->state > HFP_W2_DISCONNECT_SCO) return 0;
780static int hfp_ag_run_for_audio_connection(hfp_connection_t * hfp_connection){
781 if (hfp_connection->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED ||
782 hfp_connection->state > HFP_W2_DISCONNECT_SCO) return 0;
785
786
783
784
787 if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED && context->release_audio_connection){
788 context->state = HFP_W4_SCO_DISCONNECTED;
789 context->release_audio_connection = 0;
790 gap_disconnect(context->sco_handle);
785 if (hfp_connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED && hfp_connection->release_audio_connection){
786 hfp_connection->state = HFP_W4_SCO_DISCONNECTED;
787 hfp_connection->release_audio_connection = 0;
788 gap_disconnect(hfp_connection->sco_handle);
791 return 1;
792 }
793
789 return 1;
790 }
791
794 if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return 0;
792 if (hfp_connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return 0;
795
796 // run codecs exchange
793
794 // run codecs exchange
797 int done = codecs_exchange_state_machine(context);
795 int done = codecs_exchange_state_machine(hfp_connection);
798 if (done) return done;
796 if (done) return done;
799 // printf(" -> State machine: Audio Connection\n");
797 // printf(" -> State machine: Audio hfp_connection\n");
800
798
801 if (context->codecs_state != HFP_CODECS_EXCHANGED) return done;
802 if (context->establish_audio_connection){
803 context->state = HFP_W4_SCO_CONNECTED;
804 context->establish_audio_connection = 0;
805 hfp_setup_synchronous_connection(context->acl_handle, context->link_setting);
799 if (hfp_connection->codecs_state != HFP_CODECS_EXCHANGED) return done;
800 if (hfp_connection->establish_audio_connection){
801 hfp_connection->state = HFP_W4_SCO_CONNECTED;
802 hfp_connection->establish_audio_connection = 0;
803 hfp_setup_synchronous_connection(hfp_connection->acl_handle, context->link_setting);
806 return 1;
807 }
808 return 0;
809}
810
811static hfp_connection_t * hfp_ag_context_for_timer(btstack_timer_source_t * ts){
812 btstack_linked_list_iterator_t it;
813 btstack_linked_list_iterator_init(&it, hfp_get_connections());
814
815 while (btstack_linked_list_iterator_has_next(&it)){
804 return 1;
805 }
806 return 0;
807}
808
809static hfp_connection_t * hfp_ag_context_for_timer(btstack_timer_source_t * ts){
810 btstack_linked_list_iterator_t it;
811 btstack_linked_list_iterator_init(&it, hfp_get_connections());
812
813 while (btstack_linked_list_iterator_has_next(&it)){
816 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
817 if ( &connection->hfp_timeout == ts) {
818 return connection;
814 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
815 if ( & hfp_connection->hfp_timeout == ts) {
816 return hfp_connection;
819 }
820 }
821 return NULL;
822}
823
824static void hfp_timeout_handler(btstack_timer_source_t * timer){
825 hfp_connection_t * context = hfp_ag_context_for_timer(timer);
826 if (!context) return;
827
817 }
818 }
819 return NULL;
820}
821
822static void hfp_timeout_handler(btstack_timer_source_t * timer){
823 hfp_connection_t * context = hfp_ag_context_for_timer(timer);
824 if (!context) return;
825
828 log_info("HFP start ring timeout, con handle 0x%02x", context->acl_handle);
829 context->ag_ring = 1;
830 context->ag_send_clip = hfp_gsm_clip_type() && context->clip_enabled;
826 log_info("HFP start ring timeout, con handle 0x%02x", hfp_connection->con_handle);
827 hfp_connection->ag_ring = 1;
828 hfp_connection->ag_send_clip = hfp_gsm_clip_type() && hfp_connection->clip_enabled;
831
829
832 btstack_run_loop_set_timer(&context->hfp_timeout, 2000); // 5 seconds timeout
833 btstack_run_loop_add_timer(&context->hfp_timeout);
830 btstack_run_loop_set_timer(& hfp_connection->hfp_timeout, 2000); // 2 seconds timeout
831 btstack_run_loop_add_timer(& hfp_connection->hfp_timeout);
834
832
835 hfp_run_for_context(context);
833 hfp_run_for_context(hfp_connection);
836}
837
834}
835
838static void hfp_timeout_start(hfp_connection_t * context){
839 btstack_run_loop_remove_timer(&context->hfp_timeout);
840 btstack_run_loop_set_timer_handler(&context->hfp_timeout, hfp_timeout_handler);
841 btstack_run_loop_set_timer(&context->hfp_timeout, 2000); // 5 seconds timeout
842 btstack_run_loop_add_timer(&context->hfp_timeout);
836static void hfp_timeout_start(hfp_connection_t * hfp_connection){
837 btstack_run_loop_remove_timer(& hfp_connection->hfp_timeout);
838 btstack_run_loop_set_timer_handler(& hfp_connection->hfp_timeout, hfp_timeout_handler);
839 btstack_run_loop_set_timer(& hfp_connection->hfp_timeout, 2000); // 2 seconds timeout
840 btstack_run_loop_add_timer(& hfp_connection->hfp_timeout);
843}
844
841}
842
845static void hfp_timeout_stop(hfp_connection_t * context){
846 log_info("HFP stop ring timeout, con handle 0x%02x", context->acl_handle);
847 btstack_run_loop_remove_timer(&context->hfp_timeout);
843static void hfp_timeout_stop(hfp_connection_t * hfp_connection){
844 log_info("HFP stop ring timeout, con handle 0x%02x", hfp_connection->acl_handle);
845 btstack_run_loop_remove_timer(& hfp_connection->hfp_timeout);
848}
849
850//
851// transitition implementations for hfp_ag_call_state_machine
852//
853
846}
847
848//
849// transitition implementations for hfp_ag_call_state_machine
850//
851
854static void hfp_ag_hf_start_ringing(hfp_connection_t * context){
852static void hfp_ag_hf_start_ringing(hfp_connection_t * hfp_connection){
855 if (use_in_band_tone()){
853 if (use_in_band_tone()){
856 context->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING;
857 hfp_ag_establish_audio_connection(context->remote_addr);
854 hfp_connection->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING;
855 hfp_ag_establish_audio_connection(hfp_connection->remote_addr);
858 } else {
856 } else {
859 hfp_timeout_start(context);
860 context->ag_ring = 1;
861 context->ag_send_clip = hfp_gsm_clip_type() && context->clip_enabled;
862 context->call_state = HFP_CALL_RINGING;
863 hfp_emit_event(hfp_callback, HFP_SUBEVENT_START_RINGINIG, 0);
857 hfp_timeout_start(hfp_connection);
858 hfp_connection->ag_ring = 1;
859 hfp_connection->ag_send_clip = hfp_gsm_clip_type() && hfp_connection->clip_enabled;
860 hfp_connection->call_state = HFP_CALL_RINGING;
861 hfp_emit_simple_event(hfp_callback, HFP_SUBEVENT_START_RINGINIG);
864 }
865}
866
862 }
863}
864
867static void hfp_ag_hf_stop_ringing(hfp_connection_t * context){
868 context->ag_ring = 0;
869 context->ag_send_clip = 0;
870 hfp_timeout_stop(context);
871 hfp_emit_event(hfp_callback, HFP_SUBEVENT_STOP_RINGINIG, 0);
865static void hfp_ag_hf_stop_ringing(hfp_connection_t * hfp_connection){
866 hfp_connection->ag_ring = 0;
867 hfp_connection->ag_send_clip = 0;
868 hfp_timeout_stop(hfp_connection);
869 hfp_emit_simple_event(hfp_callback, HFP_SUBEVENT_STOP_RINGINIG);
872}
873
874static void hfp_ag_trigger_incoming_call(void){
875 int indicator_index = get_ag_indicator_index_for_name("callsetup");
876 if (indicator_index < 0) return;
877
878 btstack_linked_list_iterator_t it;
879 btstack_linked_list_iterator_init(&it, hfp_get_connections());
880 while (btstack_linked_list_iterator_has_next(&it)){
870}
871
872static void hfp_ag_trigger_incoming_call(void){
873 int indicator_index = get_ag_indicator_index_for_name("callsetup");
874 if (indicator_index < 0) return;
875
876 btstack_linked_list_iterator_t it;
877 btstack_linked_list_iterator_init(&it, hfp_get_connections());
878 while (btstack_linked_list_iterator_has_next(&it)){
881 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
882 hfp_ag_establish_service_level_connection(connection->remote_addr);
883 if (connection->call_state == HFP_CALL_IDLE){
884 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1);
879 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
880 hfp_ag_establish_service_level_connection(hfp_connection->remote_addr);
881 if (hfp_connection->call_state == HFP_CALL_IDLE){
882 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, indicator_index, 1);
885 hfp_ag_hf_start_ringing(connection);
886 }
883 hfp_ag_hf_start_ringing(connection);
884 }
887 if (connection->call_state == HFP_CALL_ACTIVE){
888 connection->call_state = HFP_CALL_W2_SEND_CALL_WAITING;
885 if (hfp_connection->call_state == HFP_CALL_ACTIVE){
886 hfp_connection->call_state = HFP_CALL_W2_SEND_CALL_WAITING;
889 }
887 }
890 hfp_run_for_context(connection);
888 hfp_run_for_context(hfp_connection);
891 }
892}
893
894static void hfp_ag_transfer_callsetup_state(void){
895 int indicator_index = get_ag_indicator_index_for_name("callsetup");
896 if (indicator_index < 0) return;
897
898 btstack_linked_list_iterator_t it;
899 btstack_linked_list_iterator_init(&it, hfp_get_connections());
900 while (btstack_linked_list_iterator_has_next(&it)){
889 }
890}
891
892static void hfp_ag_transfer_callsetup_state(void){
893 int indicator_index = get_ag_indicator_index_for_name("callsetup");
894 if (indicator_index < 0) return;
895
896 btstack_linked_list_iterator_t it;
897 btstack_linked_list_iterator_init(&it, hfp_get_connections());
898 while (btstack_linked_list_iterator_has_next(&it)){
901 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
902 hfp_ag_establish_service_level_connection(connection->remote_addr);
903 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1);
904 hfp_run_for_context(connection);
899 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
900 hfp_ag_establish_service_level_connection(hfp_connection->remote_addr);
901 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, indicator_index, 1);
902 hfp_run_for_context(hfp_connection);
905 }
906}
907
908static void hfp_ag_transfer_call_state(void){
909 int indicator_index = get_ag_indicator_index_for_name("call");
910 if (indicator_index < 0) return;
911
912 btstack_linked_list_iterator_t it;
913 btstack_linked_list_iterator_init(&it, hfp_get_connections());
914 while (btstack_linked_list_iterator_has_next(&it)){
903 }
904}
905
906static void hfp_ag_transfer_call_state(void){
907 int indicator_index = get_ag_indicator_index_for_name("call");
908 if (indicator_index < 0) return;
909
910 btstack_linked_list_iterator_t it;
911 btstack_linked_list_iterator_init(&it, hfp_get_connections());
912 while (btstack_linked_list_iterator_has_next(&it)){
915 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
916 hfp_ag_establish_service_level_connection(connection->remote_addr);
917 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1);
918 hfp_run_for_context(connection);
913 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
914 hfp_ag_establish_service_level_connection(hfp_connection->remote_addr);
915 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, indicator_index, 1);
916 hfp_run_for_context(hfp_connection);
919 }
920}
921
922static void hfp_ag_transfer_callheld_state(void){
923 int indicator_index = get_ag_indicator_index_for_name("callheld");
924 if (indicator_index < 0) return;
925
926 btstack_linked_list_iterator_t it;
927 btstack_linked_list_iterator_init(&it, hfp_get_connections());
928 while (btstack_linked_list_iterator_has_next(&it)){
917 }
918}
919
920static void hfp_ag_transfer_callheld_state(void){
921 int indicator_index = get_ag_indicator_index_for_name("callheld");
922 if (indicator_index < 0) return;
923
924 btstack_linked_list_iterator_t it;
925 btstack_linked_list_iterator_init(&it, hfp_get_connections());
926 while (btstack_linked_list_iterator_has_next(&it)){
929 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
930 hfp_ag_establish_service_level_connection(connection->remote_addr);
931 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1);
932 hfp_run_for_context(connection);
927 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
928 hfp_ag_establish_service_level_connection(hfp_connection->remote_addr);
929 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, indicator_index, 1);
930 hfp_run_for_context(hfp_connection);
933 }
934}
935
936static void hfp_ag_hf_accept_call(hfp_connection_t * source){
937
938 int call_indicator_index = get_ag_indicator_index_for_name("call");
939 int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup");
940
941 btstack_linked_list_iterator_t it;
942 btstack_linked_list_iterator_init(&it, hfp_get_connections());
943 while (btstack_linked_list_iterator_has_next(&it)){
931 }
932}
933
934static void hfp_ag_hf_accept_call(hfp_connection_t * source){
935
936 int call_indicator_index = get_ag_indicator_index_for_name("call");
937 int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup");
938
939 btstack_linked_list_iterator_t it;
940 btstack_linked_list_iterator_init(&it, hfp_get_connections());
941 while (btstack_linked_list_iterator_has_next(&it)){
944 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
945 if (connection->call_state != HFP_CALL_RINGING &&
946 connection->call_state != HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING) continue;
942 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
943 if (hfp_connection->call_state != HFP_CALL_RINGING &&
944 hfp_connection->call_state != HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING) continue;
947
945
948 hfp_ag_hf_stop_ringing(connection);
949 if (connection == source){
950 connection->ok_pending = 1;
946 hfp_ag_hf_stop_ringing(hfp_connection);
947 if (hfp_connection == source){
948 hfp_connection->ok_pending = 1;
951
952 if (use_in_band_tone()){
949
950 if (use_in_band_tone()){
953 connection->call_state = HFP_CALL_ACTIVE;
951 hfp_connection->call_state = HFP_CALL_ACTIVE;
954 } else {
952 } else {
955 connection->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE;
956 hfp_ag_establish_audio_connection(connection->remote_addr);
953 hfp_connection->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE;
954 hfp_ag_establish_audio_connection(hfp_connection->remote_addr);
957 }
958
955 }
956
959 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, call_indicator_index, 1);
960 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
957 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, call_indicator_index, 1);
958 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
961
962 } else {
959
960 } else {
963 connection->call_state = HFP_CALL_IDLE;
961 hfp_connection->call_state = HFP_CALL_IDLE;
964 }
962 }
965 hfp_run_for_context(connection);
963 hfp_run_for_context(hfp_connection);
966 }
967}
968
969static void hfp_ag_ag_accept_call(void){
970
971 int call_indicator_index = get_ag_indicator_index_for_name("call");
972 int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup");
973
974 btstack_linked_list_iterator_t it;
975 btstack_linked_list_iterator_init(&it, hfp_get_connections());
976 while (btstack_linked_list_iterator_has_next(&it)){
964 }
965}
966
967static void hfp_ag_ag_accept_call(void){
968
969 int call_indicator_index = get_ag_indicator_index_for_name("call");
970 int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup");
971
972 btstack_linked_list_iterator_t it;
973 btstack_linked_list_iterator_init(&it, hfp_get_connections());
974 while (btstack_linked_list_iterator_has_next(&it)){
977 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
978 if (connection->call_state != HFP_CALL_RINGING) continue;
975 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
976 if (hfp_connection->call_state != HFP_CALL_RINGING) continue;
979
977
980 hfp_ag_hf_stop_ringing(connection);
981 connection->call_state = HFP_CALL_TRIGGER_AUDIO_CONNECTION;
978 hfp_ag_hf_stop_ringing(hfp_connection);
979 hfp_connection->call_state = HFP_CALL_TRIGGER_AUDIO_CONNECTION;
982
980
983 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, call_indicator_index, 1);
984 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
981 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, call_indicator_index, 1);
982 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
985
983
986 hfp_run_for_context(connection);
984 hfp_run_for_context(hfp_connection);
987 break; // only single
988 }
989}
990
991static void hfp_ag_trigger_reject_call(void){
992 int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup");
993 btstack_linked_list_iterator_t it;
994 btstack_linked_list_iterator_init(&it, hfp_get_connections());

--- 9 unchanged lines hidden (view full) ---

1004}
1005
1006static void hfp_ag_trigger_terminate_call(void){
1007 int call_indicator_index = get_ag_indicator_index_for_name("call");
1008
1009 btstack_linked_list_iterator_t it;
1010 btstack_linked_list_iterator_init(&it, hfp_get_connections());
1011 while (btstack_linked_list_iterator_has_next(&it)){
985 break; // only single
986 }
987}
988
989static void hfp_ag_trigger_reject_call(void){
990 int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup");
991 btstack_linked_list_iterator_t it;
992 btstack_linked_list_iterator_init(&it, hfp_get_connections());

--- 9 unchanged lines hidden (view full) ---

1002}
1003
1004static void hfp_ag_trigger_terminate_call(void){
1005 int call_indicator_index = get_ag_indicator_index_for_name("call");
1006
1007 btstack_linked_list_iterator_t it;
1008 btstack_linked_list_iterator_init(&it, hfp_get_connections());
1009 while (btstack_linked_list_iterator_has_next(&it)){
1012 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
1010 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
1013 hfp_ag_establish_service_level_connection(connection->remote_addr);
1011 hfp_ag_establish_service_level_connection(connection->remote_addr);
1014 if (connection->call_state == HFP_CALL_IDLE) continue;
1015 connection->call_state = HFP_CALL_IDLE;
1016 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, call_indicator_index, 1);
1017 connection->release_audio_connection = 1;
1018 hfp_run_for_context(connection);
1012 if (hfp_connection->call_state == HFP_CALL_IDLE) continue;
1013 hfp_connection->call_state = HFP_CALL_IDLE;
1014 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, call_indicator_index, 1);
1015 hfp_connection->release_audio_connection = 1;
1016 hfp_run_for_context(hfp_connection);
1019 }
1017 }
1020 hfp_emit_event(hfp_callback, HFP_SUBEVENT_CALL_TERMINATED, 0);
1018 hfp_emit_simple_event(hfp_callback, HFP_SUBEVENT_CALL_TERMINATED);
1021}
1022
1023static void hfp_ag_set_callsetup_indicator(){
1024 hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("callsetup");
1025 if (!indicator){
1026 log_error("hfp_ag_set_callsetup_indicator: callsetup indicator is missing");
1027 };
1028 indicator->status = hfp_gsm_callsetup_status();

--- 14 unchanged lines hidden (view full) ---

1043 };
1044 indicator->status = hfp_gsm_call_status();
1045}
1046
1047static void hfp_ag_stop_ringing(void){
1048 btstack_linked_list_iterator_t it;
1049 btstack_linked_list_iterator_init(&it, hfp_get_connections());
1050 while (btstack_linked_list_iterator_has_next(&it)){
1019}
1020
1021static void hfp_ag_set_callsetup_indicator(){
1022 hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("callsetup");
1023 if (!indicator){
1024 log_error("hfp_ag_set_callsetup_indicator: callsetup indicator is missing");
1025 };
1026 indicator->status = hfp_gsm_callsetup_status();

--- 14 unchanged lines hidden (view full) ---

1041 };
1042 indicator->status = hfp_gsm_call_status();
1043}
1044
1045static void hfp_ag_stop_ringing(void){
1046 btstack_linked_list_iterator_t it;
1047 btstack_linked_list_iterator_init(&it, hfp_get_connections());
1048 while (btstack_linked_list_iterator_has_next(&it)){
1051 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
1052 if (connection->call_state != HFP_CALL_RINGING &&
1053 connection->call_state != HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING) continue;
1054 hfp_ag_hf_stop_ringing(connection);
1049 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
1050 if (hfp_connection->call_state != HFP_CALL_RINGING &&
1051 hfp_connection->call_state != HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING) continue;
1052 hfp_ag_hf_stop_ringing(hfp_connection);
1055 }
1056}
1057
1058static hfp_connection_t * hfp_ag_connection_for_call_state(hfp_call_state_t call_state){
1059 btstack_linked_list_iterator_t it;
1060 btstack_linked_list_iterator_init(&it, hfp_get_connections());
1061 while (btstack_linked_list_iterator_has_next(&it)){
1053 }
1054}
1055
1056static hfp_connection_t * hfp_ag_connection_for_call_state(hfp_call_state_t call_state){
1057 btstack_linked_list_iterator_t it;
1058 btstack_linked_list_iterator_init(&it, hfp_get_connections());
1059 while (btstack_linked_list_iterator_has_next(&it)){
1062 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
1063 if (connection->call_state == call_state) return connection;
1060 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
1061 if (hfp_connection->call_state == call_state) return hfp_connection;
1064 }
1065 return NULL;
1066}
1067
1068static void hfp_ag_send_response_and_hold_state(hfp_response_and_hold_state_t state){
1069 btstack_linked_list_iterator_t it;
1070 btstack_linked_list_iterator_init(&it, hfp_get_connections());
1071 while (btstack_linked_list_iterator_has_next(&it)){
1062 }
1063 return NULL;
1064}
1065
1066static void hfp_ag_send_response_and_hold_state(hfp_response_and_hold_state_t state){
1067 btstack_linked_list_iterator_t it;
1068 btstack_linked_list_iterator_init(&it, hfp_get_connections());
1069 while (btstack_linked_list_iterator_has_next(&it)){
1072 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
1073 connection->send_response_and_hold_status = state + 1;
1070 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
1071 hfp_connection->send_response_and_hold_status = state + 1;
1074 }
1075}
1076
1072 }
1073}
1074
1077static int call_setup_state_machine(hfp_connection_t * connection){
1075static int call_setup_state_machine(hfp_connection_t * hfp_connection){
1078 int indicator_index;
1076 int indicator_index;
1079 switch (connection->call_state){
1077 switch (hfp_connection->call_state){
1080 case HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING:
1078 case HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING:
1081 if (connection->state != HFP_AUDIO_CONNECTION_ESTABLISHED) return 0;
1082 // we got event: audio connection established
1083 hfp_timeout_start(connection);
1084 connection->ag_ring = 1;
1085 connection->ag_send_clip = hfp_gsm_clip_type() && connection->clip_enabled;
1086 connection->call_state = HFP_CALL_RINGING;
1087 connection->call_state = HFP_CALL_RINGING;
1088 hfp_emit_event(hfp_callback, HFP_SUBEVENT_START_RINGINIG, 0);
1079 if (hfp_connection->state != HFP_AUDIO_CONNECTION_ESTABLISHED) return 0;
1080 // we got event: audio hfp_connection established
1081 hfp_timeout_start(hfp_connection);
1082 hfp_connection->ag_ring = 1;
1083 hfp_connection->ag_send_clip = hfp_gsm_clip_type() && hfp_connection->clip_enabled;
1084 hfp_connection->call_state = HFP_CALL_RINGING;
1085 hfp_connection->call_state = HFP_CALL_RINGING;
1086 hfp_emit_simple_event(hfp_callback, HFP_SUBEVENT_START_RINGINIG);
1089 break;
1090 case HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE:
1087 break;
1088 case HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE:
1091 if (connection->state != HFP_AUDIO_CONNECTION_ESTABLISHED) return 0;
1092 // we got event: audio connection established
1093 connection->call_state = HFP_CALL_ACTIVE;
1089 if (hfp_connection->state != HFP_AUDIO_CONNECTION_ESTABLISHED) return 0;
1090 // we got event: audio hfp_connection established
1091 hfp_connection->call_state = HFP_CALL_ACTIVE;
1094 break;
1095 case HFP_CALL_W2_SEND_CALL_WAITING:
1092 break;
1093 case HFP_CALL_W2_SEND_CALL_WAITING:
1096 connection->call_state = HFP_CALL_W4_CHLD;
1097 hfp_ag_send_call_waiting_notification(connection->rfcomm_cid);
1094 hfp_connection->call_state = HFP_CALL_W4_CHLD;
1095 hfp_ag_send_call_waiting_notification(hfp_connection->rfcomm_cid);
1098 indicator_index = get_ag_indicator_index_for_name("callsetup");
1096 indicator_index = get_ag_indicator_index_for_name("callsetup");
1099 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1);
1097 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, indicator_index, 1);
1100 break;
1101 default:
1102 break;
1103 }
1104 return 0;
1105}
1098 break;
1099 default:
1100 break;
1101 }
1102 return 0;
1103}
1106// connection is used to identify originating HF
1107static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connection){
1104// hfp_connection is used to identify originating HF
1105static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * hfp_connection){
1108 int indicator_index;
1109 int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup");
1110 int callheld_indicator_index = get_ag_indicator_index_for_name("callheld");
1111 int call_indicator_index = get_ag_indicator_index_for_name("call");
1112
1113 //printf("hfp_ag_call_sm event %d \n", event);
1114 switch (event){
1115 case HFP_AG_INCOMING_CALL:

--- 60 unchanged lines hidden (view full) ---

1176 switch (hfp_gsm_call_status()){
1177 case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT:
1178 switch (hfp_gsm_callheld_status()){
1179 case HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED:
1180 printf("AG: joining held call with active call\n");
1181 hfp_gsm_handle_event(HFP_AG_HELD_CALL_JOINED_BY_AG);
1182 hfp_ag_set_callheld_indicator();
1183 hfp_ag_transfer_callheld_state();
1106 int indicator_index;
1107 int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup");
1108 int callheld_indicator_index = get_ag_indicator_index_for_name("callheld");
1109 int call_indicator_index = get_ag_indicator_index_for_name("call");
1110
1111 //printf("hfp_ag_call_sm event %d \n", event);
1112 switch (event){
1113 case HFP_AG_INCOMING_CALL:

--- 60 unchanged lines hidden (view full) ---

1174 switch (hfp_gsm_call_status()){
1175 case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT:
1176 switch (hfp_gsm_callheld_status()){
1177 case HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED:
1178 printf("AG: joining held call with active call\n");
1179 hfp_gsm_handle_event(HFP_AG_HELD_CALL_JOINED_BY_AG);
1180 hfp_ag_set_callheld_indicator();
1181 hfp_ag_transfer_callheld_state();
1184 hfp_emit_event(hfp_callback, HFP_SUBEVENT_CONFERENCE_CALL, 0);
1182 hfp_emit_simple_event(hfp_callback, HFP_SUBEVENT_CONFERENCE_CALL);
1185 break;
1186 default:
1187 break;
1188 }
1189 break;
1190 default:
1191 break;
1192 }
1193 break;
1194
1195 case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF:
1196 switch (hfp_gsm_call_status()){
1197 case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:
1198 switch (hfp_gsm_callsetup_status()){
1199 case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS:
1200 hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF);
1201 hfp_ag_set_callsetup_indicator();
1202 hfp_ag_set_call_indicator();
1183 break;
1184 default:
1185 break;
1186 }
1187 break;
1188 default:
1189 break;
1190 }
1191 break;
1192
1193 case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF:
1194 switch (hfp_gsm_call_status()){
1195 case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:
1196 switch (hfp_gsm_callsetup_status()){
1197 case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS:
1198 hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF);
1199 hfp_ag_set_callsetup_indicator();
1200 hfp_ag_set_call_indicator();
1203 hfp_ag_hf_accept_call(connection);
1201 hfp_ag_hf_accept_call(hfp_connection);
1204 printf("HF answers call, accept call by GSM\n");
1202 printf("HF answers call, accept call by GSM\n");
1205 hfp_emit_event(hfp_callback, HFP_CMD_CALL_ANSWERED, 0);
1203 hfp_emit_simple_event(hfp_callback, HFP_SUBEVENT_CALL_ANSWERED);
1206 break;
1207 default:
1208 break;
1209 }
1210 break;
1211 default:
1212 break;
1213 }

--- 30 unchanged lines hidden (view full) ---

1244 case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS:
1245 hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF);
1246 hfp_ag_response_and_hold_active = 1;
1247 hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD;
1248 hfp_ag_send_response_and_hold_state(hfp_ag_response_and_hold_state);
1249 // as with regualr call
1250 hfp_ag_set_call_indicator();
1251 hfp_ag_set_callsetup_indicator();
1204 break;
1205 default:
1206 break;
1207 }
1208 break;
1209 default:
1210 break;
1211 }

--- 30 unchanged lines hidden (view full) ---

1242 case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS:
1243 hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF);
1244 hfp_ag_response_and_hold_active = 1;
1245 hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD;
1246 hfp_ag_send_response_and_hold_state(hfp_ag_response_and_hold_state);
1247 // as with regualr call
1248 hfp_ag_set_call_indicator();
1249 hfp_ag_set_callsetup_indicator();
1252 hfp_ag_hf_accept_call(connection);
1250 hfp_ag_hf_accept_call(hfp_connection);
1253 printf("AG response and hold - hold by HF\n");
1254 break;
1255 default:
1256 break;
1257 }
1258 break;
1259 default:
1260 break;

--- 44 unchanged lines hidden (view full) ---

1305 default:
1306 break;
1307 }
1308 break;
1309 case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT:
1310 hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_HF);
1311 hfp_ag_set_call_indicator();
1312 hfp_ag_transfer_call_state();
1251 printf("AG response and hold - hold by HF\n");
1252 break;
1253 default:
1254 break;
1255 }
1256 break;
1257 default:
1258 break;

--- 44 unchanged lines hidden (view full) ---

1303 default:
1304 break;
1305 }
1306 break;
1307 case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT:
1308 hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_HF);
1309 hfp_ag_set_call_indicator();
1310 hfp_ag_transfer_call_state();
1313 connection->call_state = HFP_CALL_IDLE;
1311 hfp_connection->call_state = HFP_CALL_IDLE;
1314 printf("AG terminate call\n");
1315 break;
1316 }
1317 break;
1318
1319 case HFP_AG_TERMINATE_CALL_BY_AG:
1320 switch (hfp_gsm_call_status()){
1321 case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:

--- 53 unchanged lines hidden (view full) ---

1375 default:
1376 break;
1377 }
1378 break;
1379
1380 case HFP_AG_OUTGOING_CALL_INITIATED:
1381 // directly reject call if number of free slots is exceeded
1382 if (!hfp_gsm_call_possible()){
1312 printf("AG terminate call\n");
1313 break;
1314 }
1315 break;
1316
1317 case HFP_AG_TERMINATE_CALL_BY_AG:
1318 switch (hfp_gsm_call_status()){
1319 case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:

--- 53 unchanged lines hidden (view full) ---

1373 default:
1374 break;
1375 }
1376 break;
1377
1378 case HFP_AG_OUTGOING_CALL_INITIATED:
1379 // directly reject call if number of free slots is exceeded
1380 if (!hfp_gsm_call_possible()){
1383 connection->send_error = 1;
1384 hfp_run_for_context(connection);
1381 hfp_connection->send_error = 1;
1382 hfp_run_for_context(hfp_connection);
1385 break;
1386 }
1383 break;
1384 }
1387 hfp_gsm_handle_event_with_call_number(HFP_AG_OUTGOING_CALL_INITIATED, (const char *) &connection->line_buffer[3]);
1385 hfp_gsm_handle_event_with_call_number(HFP_AG_OUTGOING_CALL_INITIATED, (const char *) &hfp_connection->line_buffer[3]);
1388
1386
1389 connection->call_state = HFP_CALL_OUTGOING_INITIATED;
1387 hfp_connection->call_state = HFP_CALL_OUTGOING_INITIATED;
1390
1388
1391 hfp_emit_string_event(hfp_callback, HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER, (const char *) &connection->line_buffer[3]);
1389 hfp_emit_string_event(hfp_callback, HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER, (const char *) &hfp_connection->line_buffer[3]);
1392 break;
1393
1394 case HFP_AG_OUTGOING_REDIAL_INITIATED:{
1395 // directly reject call if number of free slots is exceeded
1396 if (!hfp_gsm_call_possible()){
1390 break;
1391
1392 case HFP_AG_OUTGOING_REDIAL_INITIATED:{
1393 // directly reject call if number of free slots is exceeded
1394 if (!hfp_gsm_call_possible()){
1397 connection->send_error = 1;
1398 hfp_run_for_context(connection);
1395 hfp_connection->send_error = 1;
1396 hfp_run_for_context(hfp_connection);
1399 break;
1400 }
1401
1402 hfp_gsm_handle_event(HFP_AG_OUTGOING_REDIAL_INITIATED);
1397 break;
1398 }
1399
1400 hfp_gsm_handle_event(HFP_AG_OUTGOING_REDIAL_INITIATED);
1403 connection->call_state = HFP_CALL_OUTGOING_INITIATED;
1401 hfp_connection->call_state = HFP_CALL_OUTGOING_INITIATED;
1404
1405 printf("\nRedial last number");
1406 char * last_dialed_number = hfp_gsm_last_dialed_number();
1407
1408 if (strlen(last_dialed_number) > 0){
1409 printf("\nLast number exists: accept call");
1410 hfp_emit_string_event(hfp_callback, HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER, last_dialed_number);
1411 } else {
1412 printf("\nLast number missing: reject call");
1413 hfp_ag_outgoing_call_rejected();
1414 }
1415 break;
1416 }
1417 case HFP_AG_OUTGOING_CALL_REJECTED:
1402
1403 printf("\nRedial last number");
1404 char * last_dialed_number = hfp_gsm_last_dialed_number();
1405
1406 if (strlen(last_dialed_number) > 0){
1407 printf("\nLast number exists: accept call");
1408 hfp_emit_string_event(hfp_callback, HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER, last_dialed_number);
1409 } else {
1410 printf("\nLast number missing: reject call");
1411 hfp_ag_outgoing_call_rejected();
1412 }
1413 break;
1414 }
1415 case HFP_AG_OUTGOING_CALL_REJECTED:
1418 connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_INITIATED);
1419 if (!connection){
1420 log_info("hfp_ag_call_sm: did not find outgoing connection in initiated state");
1416 hfp_connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_INITIATED);
1417 if (!hfp_connection){
1418 log_info("hfp_ag_call_sm: did not find outgoing hfp_connection in initiated state");
1421 break;
1422 }
1423
1424 hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_REJECTED);
1419 break;
1420 }
1421
1422 hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_REJECTED);
1425 connection->call_state = HFP_CALL_IDLE;
1426 connection->send_error = 1;
1427 hfp_run_for_context(connection);
1423 hfp_connection->call_state = HFP_CALL_IDLE;
1424 hfp_connection->send_error = 1;
1425 hfp_run_for_context(hfp_connection);
1428 break;
1429
1430 case HFP_AG_OUTGOING_CALL_ACCEPTED:{
1426 break;
1427
1428 case HFP_AG_OUTGOING_CALL_ACCEPTED:{
1431 connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_INITIATED);
1432 if (!connection){
1433 log_info("hfp_ag_call_sm: did not find outgoing connection in initiated state");
1429 hfp_connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_INITIATED);
1430 if (!hfp_connection){
1431 log_info("hfp_ag_call_sm: did not find outgoing hfp_connection in initiated state");
1434 break;
1435 }
1436
1432 break;
1433 }
1434
1437 connection->ok_pending = 1;
1438 connection->call_state = HFP_CALL_OUTGOING_DIALING;
1435 hfp_connection->ok_pending = 1;
1436 hfp_connection->call_state = HFP_CALL_OUTGOING_DIALING;
1439
1440 // trigger callsetup to be
1441 int put_call_on_hold = hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT;
1442 hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ACCEPTED);
1443
1444 hfp_ag_set_callsetup_indicator();
1445 indicator_index = get_ag_indicator_index_for_name("callsetup");
1437
1438 // trigger callsetup to be
1439 int put_call_on_hold = hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT;
1440 hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ACCEPTED);
1441
1442 hfp_ag_set_callsetup_indicator();
1443 indicator_index = get_ag_indicator_index_for_name("callsetup");
1446 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1);
1444 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, indicator_index, 1);
1447
1448 // put current call on hold if active
1449 if (put_call_on_hold){
1450 printf("AG putting current call on hold for new outgoing call\n");
1451 hfp_ag_set_callheld_indicator();
1452 indicator_index = get_ag_indicator_index_for_name("callheld");
1445
1446 // put current call on hold if active
1447 if (put_call_on_hold){
1448 printf("AG putting current call on hold for new outgoing call\n");
1449 hfp_ag_set_callheld_indicator();
1450 indicator_index = get_ag_indicator_index_for_name("callheld");
1453 hfp_ag_transfer_ag_indicators_status_cmd(connection->rfcomm_cid, &hfp_ag_indicators[indicator_index]);
1451 hfp_ag_transfer_ag_indicators_status_cmd(hfp_connection->rfcomm_cid, &hfp_ag_indicators[indicator_index]);
1454 }
1455
1456 // start audio if needed
1452 }
1453
1454 // start audio if needed
1457 hfp_ag_establish_audio_connection(connection->remote_addr);
1455 hfp_ag_establish_audio_connection(hfp_connection->remote_addr);
1458 break;
1459 }
1460 case HFP_AG_OUTGOING_CALL_RINGING:
1456 break;
1457 }
1458 case HFP_AG_OUTGOING_CALL_RINGING:
1461 connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_DIALING);
1462 if (!connection){
1463 log_info("hfp_ag_call_sm: did not find outgoing connection in dialing state");
1459 hfp_connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_DIALING);
1460 if (!hfp_connection){
1461 log_info("hfp_ag_call_sm: did not find outgoing hfp_connection in dialing state");
1464 break;
1465 }
1466
1467 hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_RINGING);
1462 break;
1463 }
1464
1465 hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_RINGING);
1468 connection->call_state = HFP_CALL_OUTGOING_RINGING;
1466 hfp_connection->call_state = HFP_CALL_OUTGOING_RINGING;
1469 hfp_ag_set_callsetup_indicator();
1470 hfp_ag_transfer_callsetup_state();
1471 break;
1472
1473 case HFP_AG_OUTGOING_CALL_ESTABLISHED:{
1474 // get outgoing call
1467 hfp_ag_set_callsetup_indicator();
1468 hfp_ag_transfer_callsetup_state();
1469 break;
1470
1471 case HFP_AG_OUTGOING_CALL_ESTABLISHED:{
1472 // get outgoing call
1475 connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_RINGING);
1476 if (!connection){
1477 connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_DIALING);
1473 hfp_connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_RINGING);
1474 if (!hfp_connection){
1475 hfp_connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_DIALING);
1478 }
1476 }
1479 if (!connection){
1480 log_info("hfp_ag_call_sm: did not find outgoing connection");
1477 if (!hfp_connection){
1478 log_info("hfp_ag_call_sm: did not find outgoing hfp_connection");
1481 break;
1482 }
1483
1484 int CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS = hfp_gsm_callheld_status() == HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS;
1485 hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ESTABLISHED);
1479 break;
1480 }
1481
1482 int CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS = hfp_gsm_callheld_status() == HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS;
1483 hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ESTABLISHED);
1486 connection->call_state = HFP_CALL_ACTIVE;
1484 hfp_connection->call_state = HFP_CALL_ACTIVE;
1487 hfp_ag_set_callsetup_indicator();
1488 hfp_ag_set_call_indicator();
1489 hfp_ag_transfer_call_state();
1490 hfp_ag_transfer_callsetup_state();
1491 if (CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS){
1492 hfp_ag_set_callheld_indicator();
1493 hfp_ag_transfer_callheld_state();
1494 }
1495 break;
1496 }
1497
1498 case HFP_AG_CALL_HOLD_USER_BUSY:
1499 hfp_gsm_handle_event(HFP_AG_CALL_HOLD_USER_BUSY);
1500 hfp_ag_set_callsetup_indicator();
1485 hfp_ag_set_callsetup_indicator();
1486 hfp_ag_set_call_indicator();
1487 hfp_ag_transfer_call_state();
1488 hfp_ag_transfer_callsetup_state();
1489 if (CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS){
1490 hfp_ag_set_callheld_indicator();
1491 hfp_ag_transfer_callheld_state();
1492 }
1493 break;
1494 }
1495
1496 case HFP_AG_CALL_HOLD_USER_BUSY:
1497 hfp_gsm_handle_event(HFP_AG_CALL_HOLD_USER_BUSY);
1498 hfp_ag_set_callsetup_indicator();
1501 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
1502 connection->call_state = HFP_CALL_ACTIVE;
1499 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
1500 hfp_connection->call_state = HFP_CALL_ACTIVE;
1503 printf("AG: Call Waiting, User Busy\n");
1504 break;
1505
1506 case HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{
1507 int call_setup_in_progress = hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
1508 int call_held = hfp_gsm_callheld_status() != HFP_CALLHELD_STATUS_NO_CALLS_HELD;
1509
1510 // Releases all active calls (if any exist) and accepts the other (held or waiting) call.
1511 if (call_held || call_setup_in_progress){
1501 printf("AG: Call Waiting, User Busy\n");
1502 break;
1503
1504 case HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{
1505 int call_setup_in_progress = hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
1506 int call_held = hfp_gsm_callheld_status() != HFP_CALLHELD_STATUS_NO_CALLS_HELD;
1507
1508 // Releases all active calls (if any exist) and accepts the other (held or waiting) call.
1509 if (call_held || call_setup_in_progress){
1512 hfp_gsm_handle_event_with_call_index(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, connection->call_index);
1510 hfp_gsm_handle_event_with_call_index(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, hfp_connection->call_index);
1513
1514 }
1515
1516 if (call_setup_in_progress){
1517 printf("AG: Call Dropped, Accept new call\n");
1518 hfp_ag_set_callsetup_indicator();
1511
1512 }
1513
1514 if (call_setup_in_progress){
1515 printf("AG: Call Dropped, Accept new call\n");
1516 hfp_ag_set_callsetup_indicator();
1519 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
1517 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
1520 } else {
1521 printf("AG: Call Dropped, Resume held call\n");
1522 }
1523 if (call_held){
1524 hfp_ag_set_callheld_indicator();
1518 } else {
1519 printf("AG: Call Dropped, Resume held call\n");
1520 }
1521 if (call_held){
1522 hfp_ag_set_callheld_indicator();
1525 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1);
1523 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1);
1526 }
1527
1524 }
1525
1528 connection->call_state = HFP_CALL_ACTIVE;
1526 hfp_connection->call_state = HFP_CALL_ACTIVE;
1529 break;
1530 }
1531
1532 case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{
1533 // Places all active calls (if any exist) on hold and accepts the other (held or waiting) call.
1534 // only update if callsetup changed
1535 int call_setup_in_progress = hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
1527 break;
1528 }
1529
1530 case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{
1531 // Places all active calls (if any exist) on hold and accepts the other (held or waiting) call.
1532 // only update if callsetup changed
1533 int call_setup_in_progress = hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS;
1536 hfp_gsm_handle_event_with_call_index(HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, connection->call_index);
1534 hfp_gsm_handle_event_with_call_index(HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, hfp_connection->call_index);
1537
1538 if (call_setup_in_progress){
1539 printf("AG: Call on Hold, Accept new call\n");
1540 hfp_ag_set_callsetup_indicator();
1535
1536 if (call_setup_in_progress){
1537 printf("AG: Call on Hold, Accept new call\n");
1538 hfp_ag_set_callsetup_indicator();
1541 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
1539 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
1542 } else {
1543 printf("AG: Swap calls\n");
1544 }
1545
1546 hfp_ag_set_callheld_indicator();
1547 // hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED);
1540 } else {
1541 printf("AG: Swap calls\n");
1542 }
1543
1544 hfp_ag_set_callheld_indicator();
1545 // hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED);
1548 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1);
1549 connection->call_state = HFP_CALL_ACTIVE;
1546 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1);
1547 hfp_connection->call_state = HFP_CALL_ACTIVE;
1550 break;
1551 }
1552
1553 case HFP_AG_CALL_HOLD_ADD_HELD_CALL:
1554 // Adds a held call to the conversation.
1555 if (hfp_gsm_callheld_status() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){
1556 printf("AG: Join 3-way-call\n");
1557 hfp_gsm_handle_event(HFP_AG_CALL_HOLD_ADD_HELD_CALL);
1558 hfp_ag_set_callheld_indicator();
1548 break;
1549 }
1550
1551 case HFP_AG_CALL_HOLD_ADD_HELD_CALL:
1552 // Adds a held call to the conversation.
1553 if (hfp_gsm_callheld_status() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){
1554 printf("AG: Join 3-way-call\n");
1555 hfp_gsm_handle_event(HFP_AG_CALL_HOLD_ADD_HELD_CALL);
1556 hfp_ag_set_callheld_indicator();
1559 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1);
1560 hfp_emit_event(hfp_callback, HFP_SUBEVENT_CONFERENCE_CALL, 0);
1557 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1);
1558 hfp_emit_simple_event(hfp_callback, HFP_SUBEVENT_CONFERENCE_CALL);
1561 }
1559 }
1562 connection->call_state = HFP_CALL_ACTIVE;
1560 hfp_connection->call_state = HFP_CALL_ACTIVE;
1563 break;
1564 case HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS:
1565 // Connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer)
1566 hfp_gsm_handle_event(HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS);
1567 printf("AG: Transfer call -> Connect two calls and disconnect\n");
1568 hfp_ag_set_call_indicator();
1569 hfp_ag_set_callheld_indicator();
1561 break;
1562 case HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS:
1563 // Connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer)
1564 hfp_gsm_handle_event(HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS);
1565 printf("AG: Transfer call -> Connect two calls and disconnect\n");
1566 hfp_ag_set_call_indicator();
1567 hfp_ag_set_callheld_indicator();
1570 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, call_indicator_index, 1);
1571 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1);
1572 connection->call_state = HFP_CALL_IDLE;
1568 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, call_indicator_index, 1);
1569 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1);
1570 hfp_connection->call_state = HFP_CALL_IDLE;
1573 break;
1574
1575 default:
1576 break;
1577 }
1578
1579
1580}
1581
1582
1571 break;
1572
1573 default:
1574 break;
1575 }
1576
1577
1578}
1579
1580
1583static void hfp_ag_send_call_status(hfp_connection_t * connection, int call_index){
1581static void hfp_ag_send_call_status(hfp_connection_t * hfp_connection, int call_index){
1584 hfp_gsm_call_t * active_call = hfp_gsm_call(call_index);
1585 if (!active_call) return;
1586
1587 int idx = active_call->index;
1588 hfp_enhanced_call_dir_t dir = active_call->direction;
1589 hfp_enhanced_call_status_t status = active_call->enhanced_status;
1590 hfp_enhanced_call_mode_t mode = active_call->mode;
1591 hfp_enhanced_call_mpty_t mpty = active_call->mpty;

--- 4 unchanged lines hidden (view full) ---

1596 // TODO: check length of a buffer, to fit the MTU
1597 int offset = snprintf(buffer, sizeof(buffer), "\r\n%s: %d,%d,%d,%d,%d", HFP_LIST_CURRENT_CALLS, idx, dir, status, mode, mpty);
1598 if (number){
1599 offset += snprintf(buffer+offset, sizeof(buffer)-offset, ", \"%s\",%u", number, type);
1600 }
1601 snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n");
1602 printf("hfp_ag_send_current_call_status 000 index %d, dir %d, status %d, mode %d, mpty %d, type %d, number %s\n", idx, dir, status,
1603 mode, mpty, type, number);
1582 hfp_gsm_call_t * active_call = hfp_gsm_call(call_index);
1583 if (!active_call) return;
1584
1585 int idx = active_call->index;
1586 hfp_enhanced_call_dir_t dir = active_call->direction;
1587 hfp_enhanced_call_status_t status = active_call->enhanced_status;
1588 hfp_enhanced_call_mode_t mode = active_call->mode;
1589 hfp_enhanced_call_mpty_t mpty = active_call->mpty;

--- 4 unchanged lines hidden (view full) ---

1594 // TODO: check length of a buffer, to fit the MTU
1595 int offset = snprintf(buffer, sizeof(buffer), "\r\n%s: %d,%d,%d,%d,%d", HFP_LIST_CURRENT_CALLS, idx, dir, status, mode, mpty);
1596 if (number){
1597 offset += snprintf(buffer+offset, sizeof(buffer)-offset, ", \"%s\",%u", number, type);
1598 }
1599 snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n");
1600 printf("hfp_ag_send_current_call_status 000 index %d, dir %d, status %d, mode %d, mpty %d, type %d, number %s\n", idx, dir, status,
1601 mode, mpty, type, number);
1604 send_str_over_rfcomm(connection->rfcomm_cid, buffer);
1602 send_str_over_rfcomm(hfp_connection->rfcomm_cid, buffer);
1605}
1606
1603}
1604
1607static void hfp_run_for_context(hfp_connection_t *context){
1608 if (!context) return;
1609 if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return;
1605static void hfp_run_for_context(hfp_connection_t *hfp_connection){
1606 if (!hfp_connection) return;
1607 if (!rfcomm_can_send_packet_now(hfp_connection->rfcomm_cid)) return;
1610
1608
1611 if (context->send_status_of_current_calls){
1612 context->ok_pending = 0;
1613 if (context->next_call_index < hfp_gsm_get_number_of_calls()){
1614 context->next_call_index++;
1615 hfp_ag_send_call_status(context, context->next_call_index);
1609 if (hfp_connection->send_status_of_current_calls){
1610 hfp_connection->ok_pending = 0;
1611 if (hfp_connection->next_call_index < hfp_gsm_get_number_of_calls()){
1612 hfp_connection->next_call_index++;
1613 hfp_ag_send_call_status(hfp_connection, hfp_connection->next_call_index);
1616 } else {
1614 } else {
1617 context->next_call_index = 0;
1618 context->ok_pending = 1;
1619 context->send_status_of_current_calls = 0;
1615 hfp_connection->next_call_index = 0;
1616 hfp_connection->ok_pending = 1;
1617 hfp_connection->send_status_of_current_calls = 0;
1620 }
1621 return;
1622 }
1623
1618 }
1619 return;
1620 }
1621
1624 if (context->command == HFP_CMD_UNKNOWN){
1625 context->ok_pending = 0;
1626 context->send_error = 0;
1627 context->command = HFP_CMD_NONE;
1628 hfp_ag_error(context->rfcomm_cid);
1622 if (hfp_connection->ag_notify_incoming_call_waiting){
1623 hfp_connection->ag_notify_incoming_call_waiting = 0;
1624 hfp_ag_send_call_waiting_notification(hfp_connection->rfcomm_cid);
1629 return;
1630 }
1631
1625 return;
1626 }
1627
1632 if (context->send_error){
1633 context->send_error = 0;
1634 context->command = HFP_CMD_NONE;
1635 hfp_ag_error(context->rfcomm_cid);
1628 if (hfp_connection->command == HFP_CMD_UNKNOWN){
1629 hfp_connection->ok_pending = 0;
1630 hfp_connection->send_error = 0;
1631 hfp_connection->command = HFP_CMD_NONE;
1632 hfp_ag_error(hfp_connection->rfcomm_cid);
1636 return;
1637 }
1638
1633 return;
1634 }
1635
1636 if (hfp_connection->send_error){
1637 hfp_connection->send_error = 0;
1638 hfp_connection->command = HFP_CMD_NONE;
1639 hfp_ag_error(hfp_connection->rfcomm_cid);
1640 return;
1641 }
1642
1639 // note: before update AG indicators and ok_pending
1643 // note: before update AG indicators and ok_pending
1640 if (context->send_response_and_hold_status){
1641 int status = context->send_response_and_hold_status - 1;
1642 context->send_response_and_hold_status = 0;
1643 hfp_ag_set_response_and_hold(context->rfcomm_cid, status);
1644 if (hfp_connection->send_response_and_hold_status){
1645 int status = hfp_connection->send_response_and_hold_status - 1;
1646 hfp_connection->send_response_and_hold_status = 0;
1647 hfp_ag_set_response_and_hold(hfp_connection->rfcomm_cid, status);
1644 return;
1645 }
1646
1648 return;
1649 }
1650
1647 if (context->ok_pending){
1648 context->ok_pending = 0;
1649 context->command = HFP_CMD_NONE;
1650 hfp_ag_ok(context->rfcomm_cid);
1651 if (hfp_connection->ok_pending){
1652 hfp_connection->ok_pending = 0;
1653 hfp_connection->command = HFP_CMD_NONE;
1654 hfp_ag_ok(hfp_connection->rfcomm_cid);
1651 return;
1652 }
1653
1654 // update AG indicators
1655 return;
1656 }
1657
1658 // update AG indicators
1655 if (context->ag_indicators_status_update_bitmap){
1659 if (hfp_connection->ag_indicators_status_update_bitmap){
1656 int i;
1660 int i;
1657 for (i=0;i<context->ag_indicators_nr;i++){
1658 if (get_bit(context->ag_indicators_status_update_bitmap, i)){
1659 context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, i, 0);
1660 if (!context->enable_status_update_for_ag_indicators) {
1661 for (i=0;i<hfp_connection->ag_indicators_nr;i++){
1662 if (get_bit(hfp_connection->ag_indicators_status_update_bitmap, i)){
1663 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, i, 0);
1664 if (!hfp_connection->enable_status_update_for_ag_indicators) {
1661 log_info("+CMER:3,0,0,0 - not sending update for '%s'", hfp_ag_indicators[i].name);
1662 break;
1663 }
1665 log_info("+CMER:3,0,0,0 - not sending update for '%s'", hfp_ag_indicators[i].name);
1666 break;
1667 }
1664 hfp_ag_transfer_ag_indicators_status_cmd(context->rfcomm_cid, &hfp_ag_indicators[i]);
1668 hfp_ag_transfer_ag_indicators_status_cmd(hfp_connection->rfcomm_cid, &hfp_ag_indicators[i]);
1665 return;
1666 }
1667 }
1668 }
1669
1669 return;
1670 }
1671 }
1672 }
1673
1670 if (context->ag_ring){
1671 context->ag_ring = 0;
1672 context->command = HFP_CMD_NONE;
1673 hfp_ag_ring(context->rfcomm_cid);
1674 if (hfp_connection->ag_ring){
1675 hfp_connection->ag_ring = 0;
1676 hfp_connection->command = HFP_CMD_NONE;
1677 hfp_ag_ring(hfp_connection->rfcomm_cid);
1674 return;
1675 }
1676
1678 return;
1679 }
1680
1677 if (context->ag_send_clip){
1678 context->ag_send_clip = 0;
1679 context->command = HFP_CMD_NONE;
1680 hfp_ag_send_clip(context->rfcomm_cid);
1681 if (hfp_connection->ag_send_clip){
1682 hfp_connection->ag_send_clip = 0;
1683 hfp_connection->command = HFP_CMD_NONE;
1684 hfp_ag_send_clip(hfp_connection->rfcomm_cid);
1681 return;
1682 }
1683
1685 return;
1686 }
1687
1684 if (context->send_phone_number_for_voice_tag){
1685 context->send_phone_number_for_voice_tag = 0;
1686 context->command = HFP_CMD_NONE;
1687 context->ok_pending = 1;
1688 hfp_ag_send_phone_number_for_voice_tag_cmd(context->rfcomm_cid);
1688 if (hfp_connection->send_phone_number_for_voice_tag){
1689 hfp_connection->send_phone_number_for_voice_tag = 0;
1690 hfp_connection->command = HFP_CMD_NONE;
1691 hfp_connection->ok_pending = 1;
1692 hfp_ag_send_phone_number_for_voice_tag_cmd(hfp_connection->rfcomm_cid);
1689 return;
1690 }
1691
1693 return;
1694 }
1695
1692 if (context->send_subscriber_number){
1693 if (context->next_subscriber_number_to_send < subscriber_numbers_count){
1694 hfp_phone_number_t phone = subscriber_numbers[context->next_subscriber_number_to_send++];
1695 hfp_send_subscriber_number_cmd(context->rfcomm_cid, phone.type, phone.number);
1696 if (hfp_connection->send_subscriber_number){
1697 if (hfp_connection->next_subscriber_number_to_send < subscriber_numbers_count){
1698 hfp_phone_number_t phone = subscriber_numbers[hfp_connection->next_subscriber_number_to_send++];
1699 hfp_send_subscriber_number_cmd(hfp_connection->rfcomm_cid, phone.type, phone.number);
1696 } else {
1700 } else {
1697 context->send_subscriber_number = 0;
1698 context->next_subscriber_number_to_send = 0;
1699 hfp_ag_ok(context->rfcomm_cid);
1701 hfp_connection->send_subscriber_number = 0;
1702 hfp_connection->next_subscriber_number_to_send = 0;
1703 hfp_ag_ok(hfp_connection->rfcomm_cid);
1700 }
1704 }
1701 context->command = HFP_CMD_NONE;
1705 hfp_connection->command = HFP_CMD_NONE;
1702 }
1703
1706 }
1707
1704 if (context->send_microphone_gain){
1705 context->send_microphone_gain = 0;
1706 context->command = HFP_CMD_NONE;
1707 hfp_ag_set_microphone_gain_cmd(context->rfcomm_cid, context->microphone_gain);
1708 if (hfp_connection->send_microphone_gain){
1709 hfp_connection->send_microphone_gain = 0;
1710 hfp_connection->command = HFP_CMD_NONE;
1711 hfp_ag_set_microphone_gain_cmd(hfp_connection->rfcomm_cid, hfp_connection->microphone_gain);
1708 return;
1709 }
1710
1712 return;
1713 }
1714
1711 if (context->send_speaker_gain){
1712 context->send_speaker_gain = 0;
1713 context->command = HFP_CMD_NONE;
1714 hfp_ag_set_speaker_gain_cmd(context->rfcomm_cid, context->speaker_gain);
1715 if (hfp_connection->send_speaker_gain){
1716 hfp_connection->send_speaker_gain = 0;
1717 hfp_connection->command = HFP_CMD_NONE;
1718 hfp_ag_set_speaker_gain_cmd(hfp_connection->rfcomm_cid, hfp_connection->speaker_gain);
1715 return;
1716 }
1717
1719 return;
1720 }
1721
1718 if (context->send_ag_status_indicators){
1719 context->send_ag_status_indicators = 0;
1720 hfp_ag_retrieve_indicators_status_cmd(context->rfcomm_cid);
1722 if (hfp_connection->send_ag_status_indicators){
1723 hfp_connection->send_ag_status_indicators = 0;
1724 hfp_ag_retrieve_indicators_status_cmd(hfp_connection->rfcomm_cid);
1721 return;
1722 }
1723
1725 return;
1726 }
1727
1724 int done = hfp_ag_run_for_context_service_level_connection(context);
1728 int done = hfp_ag_run_for_context_service_level_connection(hfp_connection);
1725 if (!done){
1729 if (!done){
1726 done = hfp_ag_run_for_context_service_level_connection_queries(context);
1730 done = hfp_ag_run_for_context_service_level_connection_queries(hfp_connection);
1727 }
1728
1729 if (!done){
1731 }
1732
1733 if (!done){
1730 done = call_setup_state_machine(context);
1734 done = call_setup_state_machine(hfp_connection);
1731 }
1732
1733 if (!done){
1735 }
1736
1737 if (!done){
1734 done = hfp_ag_run_for_audio_connection(context);
1738 done = hfp_ag_run_for_audio_connection(hfp_connection);
1735 }
1736
1739 }
1740
1737 if (context->command == HFP_CMD_NONE && !done){
1738 // log_info("context->command == HFP_CMD_NONE");
1739 switch(context->state){
1741 if (hfp_connection->command == HFP_CMD_NONE && !done){
1742 // log_info("hfp_connection->command == HFP_CMD_NONE");
1743 switch(hfp_connection->state){
1740 case HFP_W2_DISCONNECT_RFCOMM:
1744 case HFP_W2_DISCONNECT_RFCOMM:
1741 context->state = HFP_W4_RFCOMM_DISCONNECTED;
1742 rfcomm_disconnect(context->rfcomm_cid);
1745 hfp_connection->state = HFP_W4_RFCOMM_DISCONNECTED;
1746 rfcomm_disconnect(hfp_connection->rfcomm_cid);
1743 break;
1744 default:
1745 break;
1746 }
1747 }
1748 if (done){
1747 break;
1748 default:
1749 break;
1750 }
1751 }
1752 if (done){
1749 context->command = HFP_CMD_NONE;
1753 hfp_connection->command = HFP_CMD_NONE;
1750 }
1751}
1752static hfp_generic_status_indicator_t *get_hf_indicator_by_number(int number){
1753 int i;
1754 }
1755}
1756static hfp_generic_status_indicator_t *get_hf_indicator_by_number(int number){
1757 int i;
1754 for (i=0;i< get_hfp_generic_status_indicators_nr();i++){
1755 hfp_generic_status_indicator_t * indicator = &get_hfp_generic_status_indicators()[i];
1758 for (i=0;i< hfp_generic_status_indicators_nr;i++){
1759 hfp_generic_status_indicator_t * indicator = &hfp_generic_status_indicators[i];
1756 if (indicator->uuid == number){
1757 return indicator;
1758 }
1759 }
1760 return NULL;
1761}
1762
1763static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1760 if (indicator->uuid == number){
1761 return indicator;
1762 }
1763 }
1764 return NULL;
1765}
1766
1767static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1764 hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel);
1765 if (!context) return;
1768 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_rfcomm_cid(channel);
1769 if (!hfp_connection) return;
1766
1767 char last_char = packet[size-1];
1768 packet[size-1] = 0;
1769 log_info("HFP_RX %s", packet);
1770 packet[size-1] = last_char;
1771
1772 int pos;
1773 for (pos = 0; pos < size ; pos++){
1770
1771 char last_char = packet[size-1];
1772 packet[size-1] = 0;
1773 log_info("HFP_RX %s", packet);
1774 packet[size-1] = last_char;
1775
1776 int pos;
1777 for (pos = 0; pos < size ; pos++){
1774 hfp_parse(context, packet[pos], 0);
1778 hfp_parse(hfp_connection, packet[pos], 0);
1775 }
1776 hfp_generic_status_indicator_t * indicator;
1777 int value;
1779 }
1780 hfp_generic_status_indicator_t * indicator;
1781 int value;
1778 switch(context->command){
1782 switch(hfp_connection->command){
1779 case HFP_CMD_RESPONSE_AND_HOLD_QUERY:
1780 if (hfp_ag_response_and_hold_active){
1783 case HFP_CMD_RESPONSE_AND_HOLD_QUERY:
1784 if (hfp_ag_response_and_hold_active){
1781 context->send_response_and_hold_status = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD + 1;
1785 hfp_connection->send_response_and_hold_status = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD + 1;
1782 }
1786 }
1783 context->ok_pending = 1;
1787 hfp_connection->ok_pending = 1;
1784 break;
1785 case HFP_CMD_RESPONSE_AND_HOLD_COMMAND:
1788 break;
1789 case HFP_CMD_RESPONSE_AND_HOLD_COMMAND:
1786 value = atoi((char *)&context->line_buffer[0]);
1790 value = atoi((char *)&hfp_connection->line_buffer[0]);
1787 printf("HF Response and Hold: %u\n", value);
1788 switch(value){
1789 case HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD:
1791 printf("HF Response and Hold: %u\n", value);
1792 switch(value){
1793 case HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD:
1790 hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF, context);
1794 hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF, hfp_connection);
1791 break;
1792 case HFP_RESPONSE_AND_HOLD_HELD_INCOMING_ACCEPTED:
1795 break;
1796 case HFP_RESPONSE_AND_HOLD_HELD_INCOMING_ACCEPTED:
1793 hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF, context);
1797 hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF, hfp_connection);
1794 break;
1795 case HFP_RESPONSE_AND_HOLD_HELD_INCOMING_REJECTED:
1798 break;
1799 case HFP_RESPONSE_AND_HOLD_HELD_INCOMING_REJECTED:
1796 hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF, context);
1800 hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF, hfp_connection);
1797 break;
1798 default:
1799 break;
1800 }
1801 break;
1802 default:
1803 break;
1804 }
1801 context->ok_pending = 1;
1805 hfp_connection->ok_pending = 1;
1802 break;
1803 case HFP_CMD_HF_INDICATOR_STATUS:
1806 break;
1807 case HFP_CMD_HF_INDICATOR_STATUS:
1804 context->command = HFP_CMD_NONE;
1808 hfp_connection->command = HFP_CMD_NONE;
1805 // find indicator by assigned number
1809 // find indicator by assigned number
1806 indicator = get_hf_indicator_by_number(context->parser_indicator_index);
1810 indicator = get_hf_indicator_by_number(hfp_connection->parser_indicator_index);
1807 if (!indicator){
1811 if (!indicator){
1808 context->send_error = 1;
1812 hfp_connection->send_error = 1;
1809 break;
1810 }
1813 break;
1814 }
1811 value = atoi((char *)&context->line_buffer[0]);
1815 value = atoi((char *)&hfp_connection->line_buffer[0]);
1812 switch (indicator->uuid){
1813 case 1: // enhanced security
1814 if (value > 1) {
1816 switch (indicator->uuid){
1817 case 1: // enhanced security
1818 if (value > 1) {
1815 context->send_error = 1;
1819 hfp_connection->send_error = 1;
1816 return;
1817 }
1818 printf("HF Indicator 'enhanced security' set to %u\n", value);
1819 break;
1820 case 2: // battery level
1821 if (value > 100){
1820 return;
1821 }
1822 printf("HF Indicator 'enhanced security' set to %u\n", value);
1823 break;
1824 case 2: // battery level
1825 if (value > 100){
1822 context->send_error = 1;
1826 hfp_connection->send_error = 1;
1823 return;
1824 }
1825 printf("HF Indicator 'battery' set to %u\n", value);
1826 break;
1827 default:
1828 printf("HF Indicator unknown set to %u\n", value);
1829 break;
1830 }
1827 return;
1828 }
1829 printf("HF Indicator 'battery' set to %u\n", value);
1830 break;
1831 default:
1832 printf("HF Indicator unknown set to %u\n", value);
1833 break;
1834 }
1831 context->ok_pending = 1;
1835 hfp_connection->ok_pending = 1;
1832 break;
1833 case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
1834 // expected by SLC state machine
1836 break;
1837 case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
1838 // expected by SLC state machine
1835 if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) break;
1836 context->send_ag_indicators_segment = 0;
1837 context->send_ag_status_indicators = 1;
1839 if (hfp_connection->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) break;
1840 hfp_connection->send_ag_indicators_segment = 0;
1841 hfp_connection->send_ag_status_indicators = 1;
1838 break;
1839 case HFP_CMD_LIST_CURRENT_CALLS:
1842 break;
1843 case HFP_CMD_LIST_CURRENT_CALLS:
1840 context->command = HFP_CMD_NONE;
1841 context->next_call_index = 0;
1842 context->send_status_of_current_calls = 1;
1844 hfp_connection->command = HFP_CMD_NONE;
1845 hfp_connection->next_call_index = 0;
1846 hfp_connection->send_status_of_current_calls = 1;
1843 break;
1844 case HFP_CMD_GET_SUBSCRIBER_NUMBER_INFORMATION:
1845 if (subscriber_numbers_count == 0){
1847 break;
1848 case HFP_CMD_GET_SUBSCRIBER_NUMBER_INFORMATION:
1849 if (subscriber_numbers_count == 0){
1846 hfp_ag_ok(context->rfcomm_cid);
1850 hfp_ag_ok(hfp_connection->rfcomm_cid);
1847 break;
1848 }
1851 break;
1852 }
1849 context->next_subscriber_number_to_send = 0;
1850 context->send_subscriber_number = 1;
1853 hfp_connection->next_subscriber_number_to_send = 0;
1854 hfp_connection->send_subscriber_number = 1;
1851 break;
1852 case HFP_CMD_TRANSMIT_DTMF_CODES:
1855 break;
1856 case HFP_CMD_TRANSMIT_DTMF_CODES:
1853 context->command = HFP_CMD_NONE;
1854 hfp_emit_string_event(hfp_callback, HFP_SUBEVENT_TRANSMIT_DTMF_CODES, (const char *) &context->line_buffer[0]);
1857 hfp_connection->command = HFP_CMD_NONE;
1858 hfp_emit_string_event(hfp_callback, HFP_SUBEVENT_TRANSMIT_DTMF_CODES, (const char *) &hfp_connection->line_buffer[0]);
1855 break;
1856 case HFP_CMD_HF_REQUEST_PHONE_NUMBER:
1859 break;
1860 case HFP_CMD_HF_REQUEST_PHONE_NUMBER:
1857 context->command = HFP_CMD_NONE;
1858 hfp_emit_event(hfp_callback, HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG, 0);
1861 hfp_connection->command = HFP_CMD_NONE;
1862 hfp_emit_simple_event(hfp_callback, HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG);
1859 break;
1860 case HFP_CMD_TURN_OFF_EC_AND_NR:
1863 break;
1864 case HFP_CMD_TURN_OFF_EC_AND_NR:
1861 context->command = HFP_CMD_NONE;
1865 hfp_connection->command = HFP_CMD_NONE;
1862 if (get_bit(hfp_supported_features, HFP_AGSF_EC_NR_FUNCTION)){
1866 if (get_bit(hfp_supported_features, HFP_AGSF_EC_NR_FUNCTION)){
1863 context->ok_pending = 1;
1864 hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_EC_NR_FUNCTION, context->ag_echo_and_noise_reduction);
1865 printf("AG: EC/NR = %u\n", context->ag_echo_and_noise_reduction);
1867 hfp_connection->ok_pending = 1;
1868 hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_EC_NR_FUNCTION, hfp_connection->ag_echo_and_noise_reduction);
1869 printf("AG: EC/NR = %u\n", hfp_connection->ag_echo_and_noise_reduction);
1866 } else {
1870 } else {
1867 context->send_error = 1;
1871 hfp_connection->send_error = 1;
1868 }
1869 break;
1870 case HFP_CMD_CALL_ANSWERED:
1872 }
1873 break;
1874 case HFP_CMD_CALL_ANSWERED:
1871 context->command = HFP_CMD_NONE;
1875 hfp_connection->command = HFP_CMD_NONE;
1872 printf("HFP: ATA\n");
1876 printf("HFP: ATA\n");
1873 hfp_ag_call_sm(HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF, context);
1877 hfp_ag_call_sm(HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF, hfp_connection);
1874 break;
1875 case HFP_CMD_HANG_UP_CALL:
1878 break;
1879 case HFP_CMD_HANG_UP_CALL:
1876 context->command = HFP_CMD_NONE;
1877 context->ok_pending = 1;
1878 hfp_ag_call_sm(HFP_AG_TERMINATE_CALL_BY_HF, context);
1880 hfp_connection->command = HFP_CMD_NONE;
1881 hfp_connection->ok_pending = 1;
1882 hfp_ag_call_sm(HFP_AG_TERMINATE_CALL_BY_HF, hfp_connection);
1879 break;
1880 case HFP_CMD_CALL_HOLD: {
1881 // TODO: fully implement this
1883 break;
1884 case HFP_CMD_CALL_HOLD: {
1885 // TODO: fully implement this
1882 log_error("HFP: unhandled call hold type %c", context->line_buffer[0]);
1883 context->command = HFP_CMD_NONE;
1884 context->ok_pending = 1;
1885 context->call_index = 0;
1886 log_error("HFP: unhandled call hold type %c", hfp_connection->line_buffer[0]);
1887 hfp_connection->command = HFP_CMD_NONE;
1888 hfp_connection->ok_pending = 1;
1889 hfp_connection->call_index = 0;
1886
1890
1887 if (context->line_buffer[1] != '\0'){
1888 context->call_index = atoi((char *)&context->line_buffer[1]);
1891 if (hfp_connection->line_buffer[1] != '\0'){
1892 hfp_connection->call_index = atoi((char *)&hfp_connection->line_buffer[1]);
1889 }
1890
1893 }
1894
1891 switch (context->line_buffer[0]){
1895 switch (hfp_connection->line_buffer[0]){
1892 case '0':
1893 // Releases all held calls or sets User Determined User Busy (UDUB) for a waiting call.
1896 case '0':
1897 // Releases all held calls or sets User Determined User Busy (UDUB) for a waiting call.
1894 hfp_ag_call_sm(HFP_AG_CALL_HOLD_USER_BUSY, context);
1898 hfp_ag_call_sm(HFP_AG_CALL_HOLD_USER_BUSY, hfp_connection);
1895 break;
1896 case '1':
1897 // Releases all active calls (if any exist) and accepts the other (held or waiting) call.
1898 // Where both a held and a waiting call exist, the above procedures shall apply to the
1899 // waiting call (i.e., not to the held call) in conflicting situation.
1899 break;
1900 case '1':
1901 // Releases all active calls (if any exist) and accepts the other (held or waiting) call.
1902 // Where both a held and a waiting call exist, the above procedures shall apply to the
1903 // waiting call (i.e., not to the held call) in conflicting situation.
1900 hfp_ag_call_sm(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, context);
1904 hfp_ag_call_sm(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, hfp_connection);
1901 break;
1902 case '2':
1903 // Places all active calls (if any exist) on hold and accepts the other (held or waiting) call.
1904 // Where both a held and a waiting call exist, the above procedures shall apply to the
1905 // waiting call (i.e., not to the held call) in conflicting situation.
1905 break;
1906 case '2':
1907 // Places all active calls (if any exist) on hold and accepts the other (held or waiting) call.
1908 // Where both a held and a waiting call exist, the above procedures shall apply to the
1909 // waiting call (i.e., not to the held call) in conflicting situation.
1906 hfp_ag_call_sm(HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, context);
1910 hfp_ag_call_sm(HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, hfp_connection);
1907 break;
1908 case '3':
1909 // Adds a held call to the conversation.
1911 break;
1912 case '3':
1913 // Adds a held call to the conversation.
1910 hfp_ag_call_sm(HFP_AG_CALL_HOLD_ADD_HELD_CALL, context);
1914 hfp_ag_call_sm(HFP_AG_CALL_HOLD_ADD_HELD_CALL, hfp_connection);
1911 break;
1912 case '4':
1913 // Connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer).
1915 break;
1916 case '4':
1917 // Connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer).
1914 hfp_ag_call_sm(HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS, context);
1918 hfp_ag_call_sm(HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS, hfp_connection);
1915 break;
1916 default:
1917 break;
1918 }
1919 break;
1920 }
1921 case HFP_CMD_CALL_PHONE_NUMBER:
1919 break;
1920 default:
1921 break;
1922 }
1923 break;
1924 }
1925 case HFP_CMD_CALL_PHONE_NUMBER:
1922 context->command = HFP_CMD_NONE;
1923 hfp_ag_call_sm(HFP_AG_OUTGOING_CALL_INITIATED, context);
1926 hfp_connection->command = HFP_CMD_NONE;
1927 hfp_ag_call_sm(HFP_AG_OUTGOING_CALL_INITIATED, hfp_connection);
1924 break;
1925 case HFP_CMD_REDIAL_LAST_NUMBER:
1928 break;
1929 case HFP_CMD_REDIAL_LAST_NUMBER:
1926 context->command = HFP_CMD_NONE;
1927 hfp_ag_call_sm(HFP_AG_OUTGOING_REDIAL_INITIATED, context);
1930 hfp_connection->command = HFP_CMD_NONE;
1931 hfp_ag_call_sm(HFP_AG_OUTGOING_REDIAL_INITIATED, hfp_connection);
1928 break;
1929 case HFP_CMD_ENABLE_CLIP:
1932 break;
1933 case HFP_CMD_ENABLE_CLIP:
1930 context->command = HFP_CMD_NONE;
1931 context->clip_enabled = context->line_buffer[8] != '0';
1932 log_info("hfp: clip set, now: %u", context->clip_enabled);
1933 context->ok_pending = 1;
1934 hfp_connection->command = HFP_CMD_NONE;
1935 hfp_connection->clip_enabled = hfp_connection->line_buffer[8] != '0';
1936 log_info("hfp: clip set, now: %u", hfp_connection->clip_enabled);
1937 hfp_connection->ok_pending = 1;
1934 break;
1935 case HFP_CMD_ENABLE_CALL_WAITING_NOTIFICATION:
1938 break;
1939 case HFP_CMD_ENABLE_CALL_WAITING_NOTIFICATION:
1936 context->command = HFP_CMD_NONE;
1937 context->call_waiting_notification_enabled = context->line_buffer[8] != '0';
1938 log_info("hfp: call waiting notification set, now: %u", context->call_waiting_notification_enabled);
1939 context->ok_pending = 1;
1940 hfp_connection->command = HFP_CMD_NONE;
1941 hfp_connection->call_waiting_notification_enabled = hfp_connection->line_buffer[8] != '0';
1942 log_info("hfp: call waiting notification set, now: %u", hfp_connection->call_waiting_notification_enabled);
1943 hfp_connection->ok_pending = 1;
1940 break;
1941 case HFP_CMD_SET_SPEAKER_GAIN:
1944 break;
1945 case HFP_CMD_SET_SPEAKER_GAIN:
1942 context->command = HFP_CMD_NONE;
1943 context->ok_pending = 1;
1944 printf("HF speaker gain = %u\n", context->speaker_gain);
1946 hfp_connection->command = HFP_CMD_NONE;
1947 hfp_connection->ok_pending = 1;
1948 printf("HF speaker gain = %u\n", hfp_connection->speaker_gain);
1945 break;
1946 case HFP_CMD_SET_MICROPHONE_GAIN:
1949 break;
1950 case HFP_CMD_SET_MICROPHONE_GAIN:
1947 context->command = HFP_CMD_NONE;
1948 context->ok_pending = 1;
1949 printf("HF microphone gain = %u\n", context->microphone_gain);
1951 hfp_connection->command = HFP_CMD_NONE;
1952 hfp_connection->ok_pending = 1;
1953 printf("HF microphone gain = %u\n", hfp_connection->microphone_gain);
1950 break;
1951 default:
1952 break;
1953 }
1954}
1955
1956static void hfp_run(void){
1954 break;
1955 default:
1956 break;
1957 }
1958}
1959
1960static void hfp_run(void){
1957 btstack_linked_list_iterator_t it;
1958 btstack_linked_list_iterator_init(&it, hfp_get_connections());
1959 while (btstack_linked_list_iterator_has_next(&it)){
1960 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
1961 hfp_run_for_context(connection);
1961 linked_list_iterator_t it;
1962 linked_list_iterator_init(&it, hfp_get_connections());
1963 while (linked_list_iterator_has_next(&it)){
1964 hfp_connection_t * hfp_connection = (hfp_connection_t *)linked_list_iterator_next(&it);
1965 hfp_run_for_context(hfp_connection);
1962 }
1963}
1964
1965static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1966 switch (packet_type){
1967 case RFCOMM_DATA_PACKET:
1968 hfp_handle_rfcomm_data(packet_type, channel, packet, size);
1969 break;
1970 case HCI_EVENT_PACKET:
1971 hfp_handle_hci_event(packet_type, packet, size);
1972 break;
1973 default:
1974 break;
1975 }
1976
1977 hfp_run();
1978}
1979
1966 }
1967}
1968
1969static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1970 switch (packet_type){
1971 case RFCOMM_DATA_PACKET:
1972 hfp_handle_rfcomm_data(packet_type, channel, packet, size);
1973 break;
1974 case HCI_EVENT_PACKET:
1975 hfp_handle_hci_event(packet_type, packet, size);
1976 break;
1977 default:
1978 break;
1979 }
1980
1981 hfp_run();
1982}
1983
1980static void hfp_ag_set_ag_indicators(hfp_ag_indicator_t * ag_indicators, int ag_indicators_nr){
1981 hfp_ag_indicators_nr = ag_indicators_nr;
1982 memcpy(hfp_ag_indicators, ag_indicators, ag_indicators_nr * sizeof(hfp_ag_indicator_t));
1983}
1984
1984
1985void hfp_ag_init(uint16_t rfcomm_channel_nr, uint32_t supported_features,
1986 uint8_t * codecs, int codecs_nr,
1987 hfp_ag_indicator_t * ag_indicators, int ag_indicators_nr,
1988 hfp_generic_status_indicator_t * hf_indicators, int hf_indicators_nr,
1989 const char *call_hold_services[], int call_hold_services_nr){
1985void hfp_ag_init_codecs(int codecs_nr, uint8_t * codecs){
1990 if (codecs_nr > HFP_MAX_NUM_CODECS){
1991 log_error("hfp_init: codecs_nr (%d) > HFP_MAX_NUM_CODECS (%d)", codecs_nr, HFP_MAX_NUM_CODECS);
1992 return;
1993 }
1986 if (codecs_nr > HFP_MAX_NUM_CODECS){
1987 log_error("hfp_init: codecs_nr (%d) > HFP_MAX_NUM_CODECS (%d)", codecs_nr, HFP_MAX_NUM_CODECS);
1988 return;
1989 }
1994
1995 // register for HCI events
1996 hci_event_callback_registration.callback = &packet_handler;
1997 hci_add_event_handler(&hci_event_callback_registration);
1998
1999 l2cap_init();
2000
2001 rfcomm_register_service(packet_handler, rfcomm_channel_nr, 0xffff);
2002
2003 hfp_supported_features = supported_features;
2004 hfp_codecs_nr = codecs_nr;
2005
2006 int i;
1990 int i;
2007 for (i=0; i<codecs_nr; i++){
1991 hfp_codecs_nr = codecs_nr;
1992 for (i=0; i < codecs_nr; i++){
2008 hfp_codecs[i] = codecs[i];
2009 }
1993 hfp_codecs[i] = codecs[i];
1994 }
1995}
2010
1996
2011 hfp_ag_set_ag_indicators(ag_indicators, ag_indicators_nr);
1997void hfp_ag_init_supported_features(uint32_t supported_features){
1998 hfp_supported_features = supported_features;
1999}
2012
2000
2013 set_hfp_generic_status_indicators(hf_indicators, hf_indicators_nr);
2001void hfp_ag_init_ag_indicators(int ag_indicators_nr, hfp_ag_indicator_t * ag_indicators){
2002 hfp_ag_indicators_nr = ag_indicators_nr;
2003 memcpy(hfp_ag_indicators, ag_indicators, ag_indicators_nr * sizeof(hfp_ag_indicator_t));
2004}
2014
2005
2006void hfp_ag_init_hf_indicators(int hf_indicators_nr, hfp_generic_status_indicator_t * hf_indicators){
2007 if (hf_indicators_nr > HFP_MAX_NUM_HF_INDICATORS) return;
2008 hfp_generic_status_indicators_nr = hf_indicators_nr;
2009 memcpy(hfp_generic_status_indicators, hf_indicators, hf_indicators_nr * sizeof(hfp_generic_status_indicator_t));
2010}
2011
2012void hfp_ag_init_call_hold_services(int call_hold_services_nr, const char * call_hold_services[]){
2015 hfp_ag_call_hold_services_nr = call_hold_services_nr;
2016 memcpy(hfp_ag_call_hold_services, call_hold_services, call_hold_services_nr * sizeof(char *));
2013 hfp_ag_call_hold_services_nr = call_hold_services_nr;
2014 memcpy(hfp_ag_call_hold_services, call_hold_services, call_hold_services_nr * sizeof(char *));
2015}
2017
2016
2017
2018void hfp_ag_init(uint16_t rfcomm_channel_nr){
2019 l2cap_init();
2020 l2cap_register_packet_handler(packet_handler);
2021 rfcomm_register_packet_handler(packet_handler);
2022 hfp_init(rfcomm_channel_nr);
2023
2018 hfp_ag_response_and_hold_active = 0;
2019 subscriber_numbers = NULL;
2020 subscriber_numbers_count = 0;
2021
2022 hfp_gsm_init();
2023}
2024
2025void hfp_ag_establish_service_level_connection(bd_addr_t bd_addr){
2026 hfp_establish_service_level_connection(bd_addr, SDP_Handsfree);
2027}
2028
2029void hfp_ag_release_service_level_connection(bd_addr_t bd_addr){
2024 hfp_ag_response_and_hold_active = 0;
2025 subscriber_numbers = NULL;
2026 subscriber_numbers_count = 0;
2027
2028 hfp_gsm_init();
2029}
2030
2031void hfp_ag_establish_service_level_connection(bd_addr_t bd_addr){
2032 hfp_establish_service_level_connection(bd_addr, SDP_Handsfree);
2033}
2034
2035void hfp_ag_release_service_level_connection(bd_addr_t bd_addr){
2030 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2031 hfp_release_service_level_connection(connection);
2032 hfp_run_for_context(connection);
2036 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2037 hfp_release_service_level_connection(hfp_connection);
2038 hfp_run_for_context(hfp_connection);
2033}
2034
2035void hfp_ag_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, hfp_cme_error_t error){
2039}
2040
2041void hfp_ag_report_extended_audio_gateway_error_result_code(bd_addr_t bd_addr, hfp_cme_error_t error){
2036 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2037 if (!connection){
2038 log_error("HFP HF: connection doesn't exist.");
2042 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2043 if (!hfp_connection){
2044 log_error("HFP HF: hfp_connection doesn't exist.");
2039 return;
2040 }
2045 return;
2046 }
2041 connection->extended_audio_gateway_error = 0;
2042 if (!connection->enable_extended_audio_gateway_error_report){
2047 hfp_connection->extended_audio_gateway_error = 0;
2048 if (!hfp_connection->enable_extended_audio_gateway_error_report){
2043 return;
2044 }
2049 return;
2050 }
2045 connection->extended_audio_gateway_error = error;
2046 hfp_run_for_context(connection);
2051 hfp_connection->extended_audio_gateway_error = error;
2052 hfp_run_for_context(hfp_connection);
2047}
2048
2053}
2054
2049static void hfp_ag_setup_audio_connection(hfp_connection_t * connection){
2050 if (connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return;
2051 if (connection->state >= HFP_W2_DISCONNECT_SCO) return;
2055static void hfp_ag_setup_audio_connection(hfp_connection_t * hfp_connection){
2056 if (hfp_connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return;
2057 if (hfp_connection->state >= HFP_W2_DISCONNECT_SCO) return;
2052
2058
2053 connection->establish_audio_connection = 1;
2059 hfp_connection->establish_audio_connection = 1;
2054
2060
2055 if (!has_codec_negotiation_feature(connection)){
2061 if (!has_codec_negotiation_feature(hfp_connection)){
2056 log_info("hfp_ag_establish_audio_connection - no codec negotiation feature, using defaults");
2062 log_info("hfp_ag_establish_audio_connection - no codec negotiation feature, using defaults");
2057 connection->codecs_state = HFP_CODECS_EXCHANGED;
2063 hfp_connection->codecs_state = HFP_CODECS_EXCHANGED;
2058 }
2059
2064 }
2065
2060 switch (connection->codecs_state){
2066 switch (hfp_connection->codecs_state){
2061 case HFP_CODECS_IDLE:
2062 case HFP_CODECS_RECEIVED_LIST:
2063 case HFP_CODECS_AG_RESEND_COMMON_CODEC:
2064 case HFP_CODECS_ERROR:
2067 case HFP_CODECS_IDLE:
2068 case HFP_CODECS_RECEIVED_LIST:
2069 case HFP_CODECS_AG_RESEND_COMMON_CODEC:
2070 case HFP_CODECS_ERROR:
2065 connection->command = HFP_CMD_AG_SEND_COMMON_CODEC;
2071 hfp_connection->command = HFP_CMD_AG_SEND_COMMON_CODEC;
2066 break;
2067 default:
2068 break;
2069 }
2070}
2071
2072void hfp_ag_establish_audio_connection(bd_addr_t bd_addr){
2073 hfp_ag_establish_service_level_connection(bd_addr);
2072 break;
2073 default:
2074 break;
2075 }
2076}
2077
2078void hfp_ag_establish_audio_connection(bd_addr_t bd_addr){
2079 hfp_ag_establish_service_level_connection(bd_addr);
2074 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2080 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2075
2081
2076 connection->establish_audio_connection = 0;
2077 hfp_ag_setup_audio_connection(connection);
2078 hfp_run_for_context(connection);
2082 hfp_connection->establish_audio_connection = 0;
2083 hfp_ag_setup_audio_connection(hfp_connection);
2084 hfp_run_for_context(hfp_connection);
2079}
2080
2081void hfp_ag_release_audio_connection(bd_addr_t bd_addr){
2085}
2086
2087void hfp_ag_release_audio_connection(bd_addr_t bd_addr){
2082 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2083 hfp_release_audio_connection(connection);
2084 hfp_run_for_context(connection);
2088 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2089 hfp_release_audio_connection(hfp_connection);
2090 hfp_run_for_context(hfp_connection);
2085}
2086
2087/**
2088 * @brief Enable in-band ring tone
2089 */
2090void hfp_ag_set_use_in_band_ring_tone(int use_in_band_ring_tone){
2091 if (get_bit(hfp_supported_features, HFP_AGSF_IN_BAND_RING_TONE) == use_in_band_ring_tone){
2092 return;
2093 }
2094 hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_IN_BAND_RING_TONE, use_in_band_ring_tone);
2095
2096 btstack_linked_list_iterator_t it;
2097 btstack_linked_list_iterator_init(&it, hfp_get_connections());
2098 while (btstack_linked_list_iterator_has_next(&it)){
2091}
2092
2093/**
2094 * @brief Enable in-band ring tone
2095 */
2096void hfp_ag_set_use_in_band_ring_tone(int use_in_band_ring_tone){
2097 if (get_bit(hfp_supported_features, HFP_AGSF_IN_BAND_RING_TONE) == use_in_band_ring_tone){
2098 return;
2099 }
2100 hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_IN_BAND_RING_TONE, use_in_band_ring_tone);
2101
2102 btstack_linked_list_iterator_t it;
2103 btstack_linked_list_iterator_init(&it, hfp_get_connections());
2104 while (btstack_linked_list_iterator_has_next(&it)){
2099 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
2100 connection->command = HFP_CMD_CHANGE_IN_BAND_RING_TONE_SETTING;
2101 hfp_run_for_context(connection);
2105 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
2106 hfp_connection->command = HFP_CMD_CHANGE_IN_BAND_RING_TONE_SETTING;
2107 hfp_run_for_context(hfp_connection);
2102 }
2103}
2104
2105/**
2106 * @brief Called from GSM
2107 */
2108void hfp_ag_incoming_call(void){
2109 hfp_ag_call_sm(HFP_AG_INCOMING_CALL, NULL);

--- 55 unchanged lines hidden (view full) ---

2165 int indicator_index = get_ag_indicator_index_for_name(name);
2166 if (indicator_index < 0) return;
2167 hfp_ag_indicators[indicator_index].status = value;
2168
2169
2170 btstack_linked_list_iterator_t it;
2171 btstack_linked_list_iterator_init(&it, hfp_get_connections());
2172 while (btstack_linked_list_iterator_has_next(&it)){
2108 }
2109}
2110
2111/**
2112 * @brief Called from GSM
2113 */
2114void hfp_ag_incoming_call(void){
2115 hfp_ag_call_sm(HFP_AG_INCOMING_CALL, NULL);

--- 55 unchanged lines hidden (view full) ---

2171 int indicator_index = get_ag_indicator_index_for_name(name);
2172 if (indicator_index < 0) return;
2173 hfp_ag_indicators[indicator_index].status = value;
2174
2175
2176 btstack_linked_list_iterator_t it;
2177 btstack_linked_list_iterator_init(&it, hfp_get_connections());
2178 while (btstack_linked_list_iterator_has_next(&it)){
2173 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
2174 if (!connection->ag_indicators[indicator_index].enabled) {
2179 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it);
2180 if (! hfp_connection->ag_indicators[indicator_index].enabled) {
2175 log_info("AG indicator '%s' changed to %u but not enabled", hfp_ag_indicators[indicator_index].name, value);
2176 continue;
2177 }
2178 log_info("AG indicator '%s' changed to %u, request transfer statur", hfp_ag_indicators[indicator_index].name, value);
2181 log_info("AG indicator '%s' changed to %u but not enabled", hfp_ag_indicators[indicator_index].name, value);
2182 continue;
2183 }
2184 log_info("AG indicator '%s' changed to %u, request transfer statur", hfp_ag_indicators[indicator_index].name, value);
2179 connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1);
2180 hfp_run_for_context(connection);
2185 hfp_connection->ag_indicators_status_update_bitmap = store_bit(hfp_connection->ag_indicators_status_update_bitmap, indicator_index, 1);
2186 hfp_run_for_context(hfp_connection);
2181 }
2182}
2183
2187 }
2188}
2189
2184/*
2185 * @brief
2186 */
2187void hfp_ag_set_registration_status(int status){
2188 hfp_ag_set_ag_indicator("service", status);
2189}
2190
2190void hfp_ag_set_registration_status(int status){
2191 hfp_ag_set_ag_indicator("service", status);
2192}
2193
2191/*
2192 * @brief
2193 */
2194void hfp_ag_set_signal_strength(int strength){
2195 hfp_ag_set_ag_indicator("signal", strength);
2196}
2197
2194void hfp_ag_set_signal_strength(int strength){
2195 hfp_ag_set_ag_indicator("signal", strength);
2196}
2197
2198/*
2199 * @brief
2200 */
2201void hfp_ag_set_roaming_status(int status){
2202 hfp_ag_set_ag_indicator("roam", status);
2203}
2204
2198void hfp_ag_set_roaming_status(int status){
2199 hfp_ag_set_ag_indicator("roam", status);
2200}
2201
2205/*
2206 * @brief
2207 */
2208void hfp_ag_set_battery_level(int level){
2209 hfp_ag_set_ag_indicator("battchg", level);
2210}
2211
2202void hfp_ag_set_battery_level(int level){
2203 hfp_ag_set_ag_indicator("battchg", level);
2204}
2205
2212/*
2213 * @brief
2214 */
2215void hfp_ag_activate_voice_recognition(bd_addr_t bd_addr, int activate){
2216 if (!get_bit(hfp_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION)) return;
2206void hfp_ag_activate_voice_recognition(bd_addr_t bd_addr, int activate){
2207 if (!get_bit(hfp_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION)) return;
2217 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2208 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2218
2209
2219 if (!get_bit(connection->remote_supported_features, HFP_HFSF_VOICE_RECOGNITION_FUNCTION)) {
2210 if (!get_bit(hfp_connection->remote_supported_features, HFP_HFSF_VOICE_RECOGNITION_FUNCTION)) {
2220 printf("AG cannot acivate voice recognition - not supported by HF\n");
2221 return;
2222 }
2223
2224 if (activate){
2225 hfp_ag_establish_audio_connection(bd_addr);
2226 }
2227
2211 printf("AG cannot acivate voice recognition - not supported by HF\n");
2212 return;
2213 }
2214
2215 if (activate){
2216 hfp_ag_establish_audio_connection(bd_addr);
2217 }
2218
2228 connection->ag_activate_voice_recognition = activate;
2229 connection->command = HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION;
2230 hfp_run_for_context(connection);
2219 hfp_connection->ag_activate_voice_recognition = activate;
2220 hfp_connection->command = HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION;
2221 hfp_run_for_context(hfp_connection);
2231}
2232
2222}
2223
2233/*
2234 * @brief
2235 */
2236void hfp_ag_set_microphone_gain(bd_addr_t bd_addr, int gain){
2224void hfp_ag_set_microphone_gain(bd_addr_t bd_addr, int gain){
2237 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2238 if (connection->microphone_gain != gain){
2239 connection->command = HFP_CMD_SET_MICROPHONE_GAIN;
2240 connection->microphone_gain = gain;
2241 connection->send_microphone_gain = 1;
2225 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2226 if (hfp_connection->microphone_gain != gain){
2227 hfp_connection->command = HFP_CMD_SET_MICROPHONE_GAIN;
2228 hfp_connection->microphone_gain = gain;
2229 hfp_connection->send_microphone_gain = 1;
2242 }
2230 }
2243 hfp_run_for_context(connection);
2231 hfp_run_for_context(hfp_connection);
2244}
2245
2232}
2233
2246/*
2247 * @brief
2248 */
2249void hfp_ag_set_speaker_gain(bd_addr_t bd_addr, int gain){
2234void hfp_ag_set_speaker_gain(bd_addr_t bd_addr, int gain){
2250 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2251 if (connection->speaker_gain != gain){
2252 connection->speaker_gain = gain;
2253 connection->send_speaker_gain = 1;
2235 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2236 if (hfp_connection->speaker_gain != gain){
2237 hfp_connection->speaker_gain = gain;
2238 hfp_connection->send_speaker_gain = 1;
2254 }
2239 }
2255 hfp_run_for_context(connection);
2240 hfp_run_for_context(hfp_connection);
2256}
2257
2241}
2242
2258/*
2259 * @brief
2260 */
2261void hfp_ag_send_phone_number_for_voice_tag(bd_addr_t bd_addr, const char * number){
2243void hfp_ag_send_phone_number_for_voice_tag(bd_addr_t bd_addr, const char * number){
2262 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2244 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2263 hfp_ag_set_clip(0, number);
2245 hfp_ag_set_clip(0, number);
2264 connection->send_phone_number_for_voice_tag = 1;
2246 hfp_connection->send_phone_number_for_voice_tag = 1;
2265}
2266
2267void hfp_ag_reject_phone_number_for_voice_tag(bd_addr_t bd_addr){
2247}
2248
2249void hfp_ag_reject_phone_number_for_voice_tag(bd_addr_t bd_addr){
2268 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2269 connection->send_error = 1;
2250 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2251 hfp_connection->send_error = 1;
2270}
2271
2272void hfp_ag_send_dtmf_code_done(bd_addr_t bd_addr){
2252}
2253
2254void hfp_ag_send_dtmf_code_done(bd_addr_t bd_addr){
2273 hfp_connection_t * connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2274 connection->ok_pending = 1;
2255 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2256 hfp_connection->ok_pending = 1;
2275}
2276
2277void hfp_ag_set_subcriber_number_information(hfp_phone_number_t * numbers, int numbers_count){
2278 subscriber_numbers = numbers;
2279 subscriber_numbers_count = numbers_count;
2280}
2281
2282void hfp_ag_clear_last_dialed_number(void){
2283 hfp_gsm_clear_last_dialed_number();
2284}
2285
2257}
2258
2259void hfp_ag_set_subcriber_number_information(hfp_phone_number_t * numbers, int numbers_count){
2260 subscriber_numbers = numbers;
2261 subscriber_numbers_count = numbers_count;
2262}
2263
2264void hfp_ag_clear_last_dialed_number(void){
2265 hfp_gsm_clear_last_dialed_number();
2266}
2267
2268void hfp_ag_notify_incoming_call_waiting(bd_addr_t bd_addr){
2269 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr);
2270 if (!hfp_connection->call_waiting_notification_enabled) return;
2271
2272 hfp_connection->ag_notify_incoming_call_waiting = 1;
2273 hfp_run_for_context(hfp_connection);
2274}
2286
2275