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 |