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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define BTSTACK_FILE__ "hfp.c" 39 40 41 #include "btstack_config.h" 42 43 #include <stdint.h> 44 #include <string.h> 45 #include <inttypes.h> 46 47 #include "bluetooth_sdp.h" 48 #include "btstack_debug.h" 49 #include "btstack_event.h" 50 #include "btstack_memory.h" 51 #include "btstack_run_loop.h" 52 #include "classic/sdp_client_rfcomm.h" 53 #include "classic/sdp_server.h" 54 #include "classic/sdp_util.h" 55 #include "classic/sdp_client.h" 56 #include "hci.h" 57 #include "hci_cmd.h" 58 #include "hci_dump.h" 59 60 #if defined(ENABLE_CC256X_ASSISTED_HFP) && !defined(ENABLE_SCO_OVER_PCM) 61 #error "Assisted HFP is only possible over PCM/I2S. Please add define: ENABLE_SCO_OVER_PCM" 62 #endif 63 64 #if defined(ENABLE_BCM_PCM_WBS) && !defined(ENABLE_SCO_OVER_PCM) 65 #error "WBS for PCM is only possible over PCM/I2S. Please add define: ENABLE_SCO_OVER_PCM" 66 #endif 67 68 #define HFP_HF_FEATURES_SIZE 10 69 #define HFP_AG_FEATURES_SIZE 12 70 71 typedef struct { 72 hfp_role_t local_role; 73 bd_addr_t remote_address; 74 } hfp_sdp_query_context_t; 75 76 // globals 77 78 static hfp_sdp_query_context_t sdp_query_context; 79 static btstack_context_callback_registration_t hfp_handle_sdp_client_query_request; 80 81 static btstack_linked_list_t hfp_connections ; 82 83 static btstack_packet_handler_t hfp_hf_callback; 84 static btstack_packet_handler_t hfp_ag_callback; 85 86 static btstack_packet_handler_t hfp_hf_rfcomm_packet_handler; 87 static btstack_packet_handler_t hfp_ag_rfcomm_packet_handler; 88 89 static hfp_connection_t * sco_establishment_active; 90 91 static uint16_t hfp_allowed_sco_packet_types; 92 93 // prototypes 94 static hfp_link_settings_t hfp_next_link_setting_for_connection(hfp_link_settings_t current_setting, hfp_connection_t * hfp_connection, uint8_t eSCO_S4_supported); 95 static void parse_sequence(hfp_connection_t * context); 96 97 98 static const char * hfp_hf_features[] = { 99 "EC and/or NR function", 100 "Three-way calling", 101 "CLI presentation capability", 102 "Voice recognition activation", 103 "Remote volume control", 104 105 "Enhanced call status", 106 "Enhanced call control", 107 108 "Codec negotiation", 109 110 "HF Indicators", 111 "eSCO S4 (and T2) Settings Supported", 112 "Reserved for future definition" 113 }; 114 115 static const char * hfp_ag_features[] = { 116 "Three-way calling", 117 "EC and/or NR function", 118 "Voice recognition function", 119 "In-band ring tone capability", 120 "Attach a number to a voice tag", 121 "Ability to reject a call", 122 "Enhanced call status", 123 "Enhanced call control", 124 "Extended Error Result Codes", 125 "Codec negotiation", 126 "HF Indicators", 127 "eSCO S4 (and T2) Settings Supported", 128 "Reserved for future definition" 129 }; 130 131 static const char * hfp_enhanced_call_dir[] = { 132 "outgoing", 133 "incoming" 134 }; 135 136 static const char * hfp_enhanced_call_status[] = { 137 "active", 138 "held", 139 "outgoing dialing", 140 "outgoing alerting", 141 "incoming", 142 "incoming waiting", 143 "call held by response and hold" 144 }; 145 146 static const char * hfp_enhanced_call_mode[] = { 147 "voice", 148 "data", 149 "fax" 150 }; 151 152 static const char * hfp_enhanced_call_mpty[] = { 153 "not a conference call", 154 "conference call" 155 }; 156 157 const char * hfp_enhanced_call_dir2str(uint16_t index){ 158 if (index <= HFP_ENHANCED_CALL_DIR_INCOMING) return hfp_enhanced_call_dir[index]; 159 return "not defined"; 160 } 161 162 const char * hfp_enhanced_call_status2str(uint16_t index){ 163 if (index <= HFP_ENHANCED_CALL_STATUS_CALL_HELD_BY_RESPONSE_AND_HOLD) return hfp_enhanced_call_status[index]; 164 return "not defined"; 165 } 166 167 const char * hfp_enhanced_call_mode2str(uint16_t index){ 168 if (index <= HFP_ENHANCED_CALL_MODE_FAX) return hfp_enhanced_call_mode[index]; 169 return "not defined"; 170 } 171 172 const char * hfp_enhanced_call_mpty2str(uint16_t index){ 173 if (index <= HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL) return hfp_enhanced_call_mpty[index]; 174 return "not defined"; 175 } 176 177 static uint16_t hfp_parse_indicator_index(hfp_connection_t * hfp_connection){ 178 uint16_t index = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 179 180 if (index > HFP_MAX_NUM_INDICATORS){ 181 log_info("ignoring invalid indicator index bigger then HFP_MAX_NUM_INDICATORS"); 182 return HFP_MAX_NUM_INDICATORS - 1; 183 } 184 185 // indicator index enumeration starts with 1, we substract 1 to store in array with starting index 0 186 if (index > 0){ 187 index -= 1; 188 } else { 189 log_info("ignoring invalid indicator index 0"); 190 return 0; 191 } 192 return index; 193 } 194 195 static void hfp_next_indicators_index(hfp_connection_t * hfp_connection){ 196 if (hfp_connection->parser_item_index < HFP_MAX_NUM_INDICATORS - 1){ 197 hfp_connection->parser_item_index++; 198 } else { 199 log_info("Ignoring additional indicator"); 200 } 201 } 202 203 static void hfp_next_codec_index(hfp_connection_t * hfp_connection){ 204 if (hfp_connection->parser_item_index < HFP_MAX_NUM_CODECS - 1){ 205 hfp_connection->parser_item_index++; 206 } else { 207 log_info("Ignoring additional codec index"); 208 } 209 } 210 211 static void hfp_next_remote_call_services_index(hfp_connection_t * hfp_connection){ 212 if (hfp_connection->remote_call_services_index < HFP_MAX_NUM_CALL_SERVICES - 1){ 213 hfp_connection->remote_call_services_index++; 214 } else { 215 log_info("Ignoring additional remote_call_services"); 216 } 217 } 218 219 const char * hfp_hf_feature(int index){ 220 if (index > HFP_HF_FEATURES_SIZE){ 221 return hfp_hf_features[HFP_HF_FEATURES_SIZE]; 222 } 223 return hfp_hf_features[index]; 224 } 225 226 const char * hfp_ag_feature(int index){ 227 if (index > HFP_AG_FEATURES_SIZE){ 228 return hfp_ag_features[HFP_AG_FEATURES_SIZE]; 229 } 230 return hfp_ag_features[index]; 231 } 232 233 int send_str_over_rfcomm(uint16_t cid, char * command){ 234 if (!rfcomm_can_send_packet_now(cid)) return 1; 235 log_info("HFP_TX %s", command); 236 int err = rfcomm_send(cid, (uint8_t*) command, strlen(command)); 237 if (err){ 238 log_error("rfcomm_send -> error 0x%02x \n", err); 239 } 240 #ifdef ENABLE_HFP_AT_MESSAGES 241 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_rfcomm_cid(cid); 242 hfp_emit_string_event(hfp_connection, HFP_SUBEVENT_AT_MESSAGE_SENT, command); 243 #endif 244 return 1; 245 } 246 247 int hfp_supports_codec(uint8_t codec, int codecs_nr, uint8_t * codecs){ 248 249 // mSBC requires support for eSCO connections 250 if ((codec == HFP_CODEC_MSBC) && !hci_extended_sco_link_supported()) return 0; 251 252 int i; 253 for (i = 0; i < codecs_nr; i++){ 254 if (codecs[i] != codec) continue; 255 return 1; 256 } 257 return 0; 258 } 259 260 void hfp_hf_drop_mSBC_if_eSCO_not_supported(uint8_t * codecs, uint8_t * codecs_nr){ 261 if (hci_extended_sco_link_supported()) return; 262 uint8_t tmp_codecs[HFP_MAX_NUM_CODECS]; 263 int i; 264 int tmp_codec_nr = 0; 265 for (i=0; i < *codecs_nr; i++){ 266 if (codecs[i] == HFP_CODEC_MSBC) continue; 267 tmp_codecs[tmp_codec_nr++] = codecs[i]; 268 } 269 *codecs_nr = tmp_codec_nr; 270 (void)memcpy(codecs, tmp_codecs, tmp_codec_nr); 271 } 272 273 // UTILS 274 int get_bit(uint16_t bitmap, int position){ 275 return (bitmap >> position) & 1; 276 } 277 278 int store_bit(uint32_t bitmap, int position, uint8_t value){ 279 if (value){ 280 bitmap |= 1 << position; 281 } else { 282 bitmap &= ~ (1 << position); 283 } 284 return bitmap; 285 } 286 287 int join(char * buffer, int buffer_size, uint8_t * values, int values_nr){ 288 if (buffer_size < (values_nr * 3)) return 0; 289 int i; 290 int offset = 0; 291 for (i = 0; i < (values_nr-1); i++) { 292 offset += snprintf(buffer+offset, buffer_size-offset, "%d,", values[i]); // puts string into buffer 293 } 294 if (i<values_nr){ 295 offset += snprintf(buffer+offset, buffer_size-offset, "%d", values[i]); 296 } 297 return offset; 298 } 299 300 int join_bitmap(char * buffer, int buffer_size, uint32_t values, int values_nr){ 301 if (buffer_size < (values_nr * 3)) return 0; 302 303 int i; 304 int offset = 0; 305 for (i = 0; i < (values_nr-1); i++) { 306 offset += snprintf(buffer+offset, buffer_size-offset, "%d,", get_bit(values,i)); // puts string into buffer 307 } 308 309 if (i<values_nr){ 310 offset += snprintf(buffer+offset, buffer_size-offset, "%d", get_bit(values,i)); 311 } 312 return offset; 313 } 314 315 static void hfp_emit_event_for_context(hfp_connection_t * hfp_connection, uint8_t * packet, uint16_t size){ 316 if (!hfp_connection) return; 317 btstack_packet_handler_t callback = NULL; 318 switch (hfp_connection->local_role){ 319 case HFP_ROLE_HF: 320 callback = hfp_hf_callback; 321 break; 322 case HFP_ROLE_AG: 323 callback = hfp_ag_callback; 324 break; 325 default: 326 return; 327 } 328 (*callback)(HCI_EVENT_PACKET, 0, packet, size); 329 } 330 331 void hfp_emit_simple_event(hfp_connection_t * hfp_connection, uint8_t event_subtype){ 332 hci_con_handle_t acl_handle = (hfp_connection != NULL) ? hfp_connection->acl_handle : HCI_CON_HANDLE_INVALID; 333 uint8_t event[5]; 334 event[0] = HCI_EVENT_HFP_META; 335 event[1] = sizeof(event) - 2; 336 event[2] = event_subtype; 337 little_endian_store_16(event, 3, acl_handle); 338 hfp_emit_event_for_context(hfp_connection, event, sizeof(event)); 339 } 340 341 void hfp_emit_event(hfp_connection_t * hfp_connection, uint8_t event_subtype, uint8_t value){ 342 hci_con_handle_t acl_handle = (hfp_connection != NULL) ? hfp_connection->acl_handle : HCI_CON_HANDLE_INVALID; 343 uint8_t event[6]; 344 event[0] = HCI_EVENT_HFP_META; 345 event[1] = sizeof(event) - 2; 346 event[2] = event_subtype; 347 little_endian_store_16(event, 3, acl_handle); 348 event[5] = value; // status 0 == OK 349 hfp_emit_event_for_context(hfp_connection, event, sizeof(event)); 350 } 351 352 void hfp_emit_slc_connection_event(hfp_connection_t * hfp_connection, uint8_t status, hci_con_handle_t con_handle, bd_addr_t addr){ 353 btstack_assert(hfp_connection != NULL); 354 uint8_t event[12]; 355 int pos = 0; 356 event[pos++] = HCI_EVENT_HFP_META; 357 event[pos++] = sizeof(event) - 2; 358 event[pos++] = HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED; 359 event[pos++] = status; // status 0 == OK 360 little_endian_store_16(event, pos, con_handle); 361 pos += 2; 362 reverse_bd_addr(addr,&event[pos]); 363 pos += 6; 364 hfp_emit_event_for_context(hfp_connection, event, sizeof(event)); 365 } 366 367 static void hfp_emit_audio_connection_released(hfp_connection_t * hfp_connection, hci_con_handle_t sco_handle){ 368 btstack_assert(hfp_connection != NULL); 369 uint8_t event[7]; 370 int pos = 0; 371 event[pos++] = HCI_EVENT_HFP_META; 372 event[pos++] = sizeof(event) - 2; 373 event[pos++] = HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED; 374 little_endian_store_16(event, pos, hfp_connection->acl_handle); 375 pos += 2; 376 little_endian_store_16(event, pos, sco_handle); 377 pos += 2; 378 hfp_emit_event_for_context(hfp_connection, event, sizeof(event)); 379 } 380 381 void hfp_emit_sco_event(hfp_connection_t * hfp_connection, uint8_t status, hci_con_handle_t sco_handle, bd_addr_t addr, uint8_t negotiated_codec){ 382 btstack_assert(hfp_connection != NULL); 383 uint8_t event[15]; 384 int pos = 0; 385 event[pos++] = HCI_EVENT_HFP_META; 386 event[pos++] = sizeof(event) - 2; 387 event[pos++] = HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED; 388 little_endian_store_16(event, pos, hfp_connection->acl_handle); 389 pos += 2; 390 event[pos++] = status; // status 0 == OK 391 little_endian_store_16(event, pos, sco_handle); 392 pos += 2; 393 reverse_bd_addr(addr,&event[pos]); 394 pos += 6; 395 event[pos++] = negotiated_codec; 396 hfp_emit_event_for_context(hfp_connection, event, sizeof(event)); 397 } 398 399 void hfp_emit_string_event(hfp_connection_t * hfp_connection, uint8_t event_subtype, const char * value){ 400 btstack_assert(hfp_connection != NULL); 401 #ifdef ENABLE_HFP_AT_MESSAGES 402 uint8_t event[256]; 403 #else 404 uint8_t event[40]; 405 #endif 406 event[0] = HCI_EVENT_HFP_META; 407 event[1] = sizeof(event) - 2; 408 event[2] = event_subtype; 409 little_endian_store_16(event, 3, hfp_connection->acl_handle); 410 uint16_t size = btstack_min(strlen(value), sizeof(event) - 6); 411 strncpy((char*)&event[5], value, size); 412 event[5 + size] = 0; 413 hfp_emit_event_for_context(hfp_connection, event, sizeof(event)); 414 } 415 416 static void hfp_emit_enhanced_voice_recognition_state(hfp_connection_t * hfp_connection){ 417 btstack_assert(hfp_connection != NULL); 418 uint8_t event[7]; 419 int pos = 0; 420 event[pos++] = HCI_EVENT_HFP_META; 421 event[pos++] = sizeof(event) - 2; 422 event[pos++] = HFP_SUBEVENT_ENHANCED_VOICE_RECOGNITION_STATUS; 423 little_endian_store_16(event, pos, hfp_connection->acl_handle); 424 pos += 2; 425 event[pos++] = hfp_connection->ag_vra_status; 426 event[pos++] = hfp_connection->ag_vra_state; 427 hfp_emit_event_for_context(hfp_connection, event, sizeof(event)); 428 } 429 430 static void hfp_emit_enhanced_voice_recognition_text(hfp_connection_t * hfp_connection, uint16_t value_length, uint8_t * value){ 431 btstack_assert(hfp_connection != NULL); 432 uint8_t event[HFP_MAX_VR_TEXT_SIZE]; 433 int pos = 0; 434 event[pos++] = HCI_EVENT_HFP_META; 435 event[pos++] = sizeof(event) - 2; 436 event[pos++] = HFP_SUBEVENT_ENHANCED_VOICE_RECOGNITION_TEXT; 437 little_endian_store_16(event, pos, hfp_connection->acl_handle); 438 pos += 2; 439 little_endian_store_16(event, pos, hfp_connection->ag_msg.text_id); 440 pos += 2; 441 event[pos++] = hfp_connection->ag_msg.text_operation; 442 event[pos++] = hfp_connection->ag_msg.text_type; 443 444 // length, zero ending 445 uint16_t size = btstack_min(value_length, sizeof(event) - pos - 2 - 1); 446 little_endian_store_16(event, pos, size+1); 447 pos += 2; 448 memcpy(&event[pos], value, size); 449 event[pos + size] = 0; 450 pos += size + 1; 451 hfp_emit_event_for_context(hfp_connection, event, pos); 452 } 453 454 btstack_linked_list_t * hfp_get_connections(void){ 455 return (btstack_linked_list_t *) &hfp_connections; 456 } 457 458 hfp_connection_t * get_hfp_connection_context_for_rfcomm_cid(uint16_t cid){ 459 btstack_linked_list_iterator_t it; 460 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 461 while (btstack_linked_list_iterator_has_next(&it)){ 462 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 463 if (hfp_connection->rfcomm_cid == cid){ 464 return hfp_connection; 465 } 466 } 467 return NULL; 468 } 469 470 hfp_connection_t * get_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr, hfp_role_t hfp_role){ 471 btstack_linked_list_iterator_t it; 472 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 473 while (btstack_linked_list_iterator_has_next(&it)){ 474 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 475 if ((memcmp(hfp_connection->remote_addr, bd_addr, 6) == 0) && (hfp_connection->local_role == hfp_role)) { 476 return hfp_connection; 477 } 478 } 479 return NULL; 480 } 481 482 hfp_connection_t * get_hfp_connection_context_for_sco_handle(uint16_t handle, hfp_role_t hfp_role){ 483 btstack_linked_list_iterator_t it; 484 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 485 while (btstack_linked_list_iterator_has_next(&it)){ 486 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 487 if ((hfp_connection->sco_handle == handle) && (hfp_connection->local_role == hfp_role)){ 488 return hfp_connection; 489 } 490 } 491 return NULL; 492 } 493 494 hfp_connection_t * get_hfp_connection_context_for_acl_handle(uint16_t handle, hfp_role_t hfp_role){ 495 btstack_linked_list_iterator_t it; 496 btstack_linked_list_iterator_init(&it, hfp_get_connections()); 497 while (btstack_linked_list_iterator_has_next(&it)){ 498 hfp_connection_t * hfp_connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 499 if ((hfp_connection->acl_handle == handle) && (hfp_connection->local_role == hfp_role)){ 500 return hfp_connection; 501 } 502 } 503 return NULL; 504 } 505 506 void hfp_reset_context_flags(hfp_connection_t * hfp_connection){ 507 if (!hfp_connection) return; 508 hfp_connection->ok_pending = 0; 509 hfp_connection->send_error = 0; 510 511 hfp_connection->found_equal_sign = false; 512 513 hfp_connection->change_status_update_for_individual_ag_indicators = 0; 514 hfp_connection->operator_name_changed = 0; 515 516 hfp_connection->enable_extended_audio_gateway_error_report = 0; 517 hfp_connection->extended_audio_gateway_error = 0; 518 519 // establish codecs hfp_connection 520 hfp_connection->suggested_codec = 0; 521 hfp_connection->negotiated_codec = 0; 522 hfp_connection->codec_confirmed = 0; 523 524 hfp_connection->establish_audio_connection = 0; 525 hfp_connection->call_waiting_notification_enabled = 0; 526 hfp_connection->command = HFP_CMD_NONE; 527 hfp_connection->enable_status_update_for_ag_indicators = 0xFF; 528 } 529 530 static hfp_connection_t * create_hfp_connection_context(void){ 531 hfp_connection_t * hfp_connection = btstack_memory_hfp_connection_get(); 532 if (!hfp_connection) return NULL; 533 534 hfp_connection->state = HFP_IDLE; 535 hfp_connection->call_state = HFP_CALL_IDLE; 536 hfp_connection->codecs_state = HFP_CODECS_IDLE; 537 538 hfp_connection->parser_state = HFP_PARSER_CMD_HEADER; 539 hfp_connection->command = HFP_CMD_NONE; 540 541 hfp_connection->acl_handle = HCI_CON_HANDLE_INVALID; 542 hfp_connection->sco_handle = HCI_CON_HANDLE_INVALID; 543 544 hfp_reset_context_flags(hfp_connection); 545 546 btstack_linked_list_add(&hfp_connections, (btstack_linked_item_t*)hfp_connection); 547 return hfp_connection; 548 } 549 550 void hfp_finalize_connection_context(hfp_connection_t * hfp_connection){ 551 btstack_run_loop_remove_timer(&hfp_connection->hfp_timeout); 552 btstack_linked_list_remove(&hfp_connections, (btstack_linked_item_t*) hfp_connection); 553 btstack_memory_hfp_connection_free(hfp_connection); 554 } 555 556 static hfp_connection_t * provide_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr, hfp_role_t local_role){ 557 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(bd_addr, local_role); 558 if (hfp_connection) return hfp_connection; 559 hfp_connection = create_hfp_connection_context(); 560 (void)memcpy(hfp_connection->remote_addr, bd_addr, 6); 561 hfp_connection->local_role = local_role; 562 log_info("Create HFP context %p: role %u, addr %s", hfp_connection, local_role, bd_addr_to_str(bd_addr)); 563 564 return hfp_connection; 565 } 566 567 /* @param network. 568 * 0 == no ability to reject a call. 569 * 1 == ability to reject a call. 570 */ 571 572 /* @param suported_features 573 * HF bit 0: EC and/or NR function (yes/no, 1 = yes, 0 = no) 574 * HF bit 1: Call waiting or three-way calling(yes/no, 1 = yes, 0 = no) 575 * HF bit 2: CLI presentation capability (yes/no, 1 = yes, 0 = no) 576 * HF bit 3: Voice recognition activation (yes/no, 1= yes, 0 = no) 577 * HF bit 4: Remote volume control (yes/no, 1 = yes, 0 = no) 578 * HF bit 5: Wide band speech (yes/no, 1 = yes, 0 = no) 579 */ 580 /* Bit position: 581 * AG bit 0: Three-way calling (yes/no, 1 = yes, 0 = no) 582 * AG bit 1: EC and/or NR function (yes/no, 1 = yes, 0 = no) 583 * AG bit 2: Voice recognition function (yes/no, 1 = yes, 0 = no) 584 * AG bit 3: In-band ring tone capability (yes/no, 1 = yes, 0 = no) 585 * AG bit 4: Attach a phone number to a voice tag (yes/no, 1 = yes, 0 = no) 586 * AG bit 5: Wide band speech (yes/no, 1 = yes, 0 = no) 587 */ 588 589 void hfp_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t service_uuid, int rfcomm_channel_nr, const char * name){ 590 uint8_t* attribute; 591 de_create_sequence(service); 592 593 // 0x0000 "Service Record Handle" 594 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE); 595 de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle); 596 597 // 0x0001 "Service Class ID List" 598 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST); 599 attribute = de_push_sequence(service); 600 { 601 // "UUID for Service" 602 de_add_number(attribute, DE_UUID, DE_SIZE_16, service_uuid); 603 de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_GENERIC_AUDIO); 604 } 605 de_pop_sequence(service, attribute); 606 607 // 0x0004 "Protocol Descriptor List" 608 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST); 609 attribute = de_push_sequence(service); 610 { 611 uint8_t* l2cpProtocol = de_push_sequence(attribute); 612 { 613 de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP); 614 } 615 de_pop_sequence(attribute, l2cpProtocol); 616 617 uint8_t* rfcomm = de_push_sequence(attribute); 618 { 619 de_add_number(rfcomm, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_RFCOMM); // rfcomm_service 620 de_add_number(rfcomm, DE_UINT, DE_SIZE_8, rfcomm_channel_nr); // rfcomm channel 621 } 622 de_pop_sequence(attribute, rfcomm); 623 } 624 de_pop_sequence(service, attribute); 625 626 627 // 0x0005 "Public Browse Group" 628 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group 629 attribute = de_push_sequence(service); 630 { 631 de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT); 632 } 633 de_pop_sequence(service, attribute); 634 635 // 0x0009 "Bluetooth Profile Descriptor List" 636 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST); 637 attribute = de_push_sequence(service); 638 { 639 uint8_t *sppProfile = de_push_sequence(attribute); 640 { 641 de_add_number(sppProfile, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HANDSFREE); 642 de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0108); // Verision 1.8 643 } 644 de_pop_sequence(attribute, sppProfile); 645 } 646 de_pop_sequence(service, attribute); 647 648 // 0x0100 "Service Name" 649 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); 650 de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name); 651 } 652 653 static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 654 UNUSED(packet_type); // ok: handling own sdp events 655 UNUSED(channel); // ok: no channel 656 UNUSED(size); // ok: handling own sdp events 657 658 hfp_connection_t * hfp_connection = get_hfp_connection_context_for_bd_addr(sdp_query_context.remote_address, sdp_query_context.local_role); 659 if (hfp_connection == NULL) { 660 log_info("connection with %s and local role %d not found", sdp_query_context.remote_address, sdp_query_context.local_role); 661 return; 662 } 663 664 switch (hci_event_packet_get_type(packet)){ 665 case SDP_EVENT_QUERY_RFCOMM_SERVICE: 666 hfp_connection->rfcomm_channel_nr = sdp_event_query_rfcomm_service_get_rfcomm_channel(packet); 667 break; 668 case SDP_EVENT_QUERY_COMPLETE: 669 if (hfp_connection->rfcomm_channel_nr > 0){ 670 hfp_connection->state = HFP_W4_RFCOMM_CONNECTED; 671 btstack_packet_handler_t packet_handler; 672 switch (hfp_connection->local_role){ 673 case HFP_ROLE_AG: 674 packet_handler = hfp_ag_rfcomm_packet_handler; 675 break; 676 case HFP_ROLE_HF: 677 packet_handler = hfp_hf_rfcomm_packet_handler; 678 break; 679 default: 680 btstack_assert(false); 681 return; 682 } 683 684 rfcomm_create_channel(packet_handler, hfp_connection->remote_addr, hfp_connection->rfcomm_channel_nr, NULL); 685 686 } else { 687 hfp_connection->state = HFP_IDLE; 688 uint8_t status = sdp_event_query_complete_get_status(packet); 689 if (status == ERROR_CODE_SUCCESS){ 690 // report service not found 691 status = SDP_SERVICE_NOT_FOUND; 692 } 693 hfp_emit_slc_connection_event(hfp_connection, status, HCI_CON_HANDLE_INVALID, hfp_connection->remote_addr); 694 log_info("rfcomm service not found, status 0x%02x", status); 695 } 696 697 // register the SDP Query request to check if there is another connection waiting for the query 698 // ignore ERROR_CODE_COMMAND_DISALLOWED because in that case, we already have requested an SDP callback 699 (void) sdp_client_register_query_callback(&hfp_handle_sdp_client_query_request); 700 break; 701 default: 702 break; 703 } 704 } 705 706 // returns 0 if unexpected error or no other link options remained, otherwise 1 707 static int hfp_handle_failed_sco_connection(uint8_t status){ 708 709 if (!sco_establishment_active){ 710 log_info("(e)SCO Connection failed but not started by us"); 711 return 0; 712 } 713 714 log_info("(e)SCO Connection failed 0x%02x", status); 715 switch (status){ 716 case ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE: 717 case ERROR_CODE_UNSPECIFIED_ERROR: 718 case ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES: 719 break; 720 default: 721 return 0; 722 } 723 724 // note: eSCO_S4 supported flag not available, but it's only relevant for highest CVSD link setting (and the current failed) 725 hfp_link_settings_t next_setting = hfp_next_link_setting_for_connection(sco_establishment_active->link_setting, sco_establishment_active, false); 726 727 // handle no valid setting found 728 if (next_setting == HFP_LINK_SETTINGS_NONE) { 729 if (sco_establishment_active->negotiated_codec == HFP_CODEC_MSBC){ 730 log_info("T2/T1 failed, fallback to CVSD - D1"); 731 sco_establishment_active->negotiated_codec = HFP_CODEC_CVSD; 732 sco_establishment_active->sco_for_msbc_failed = 1; 733 sco_establishment_active->command = HFP_CMD_AG_SEND_COMMON_CODEC; 734 sco_establishment_active->link_setting = HFP_LINK_SETTINGS_D1; 735 } else { 736 // no other options 737 return 0; 738 } 739 } 740 741 log_info("e)SCO Connection: try new link_setting %d", next_setting); 742 sco_establishment_active->establish_audio_connection = 1; 743 sco_establishment_active->link_setting = next_setting; 744 sco_establishment_active = NULL; 745 return 1; 746 } 747 748 749 void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role){ 750 UNUSED(packet_type); 751 UNUSED(channel); // ok: no channel 752 UNUSED(size); 753 754 bd_addr_t event_addr; 755 hci_con_handle_t handle; 756 hfp_connection_t * hfp_connection = NULL; 757 uint8_t status; 758 759 log_debug("HFP HCI event handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size); 760 761 switch (hci_event_packet_get_type(packet)) { 762 763 case HCI_EVENT_CONNECTION_REQUEST: 764 switch(hci_event_connection_request_get_link_type(packet)){ 765 case 0: // SCO 766 case 2: // eSCO 767 hci_event_connection_request_get_bd_addr(packet, event_addr); 768 hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr, local_role); 769 if (!hfp_connection) break; 770 if (hci_event_connection_request_get_link_type(packet) == 2){ 771 hfp_connection->accept_sco = 2; 772 } else { 773 hfp_connection->accept_sco = 1; 774 } 775 #ifdef ENABLE_CC256X_ASSISTED_HFP 776 hfp_cc256x_prepare_for_sco(hfp_connection); 777 #endif 778 #ifdef ENABLE_BCM_PCM_WBS 779 hfp_bcm_prepare_for_sco(hfp_connection); 780 #endif 781 log_info("accept sco %u\n", hfp_connection->accept_sco); 782 sco_establishment_active = hfp_connection; 783 break; 784 default: 785 break; 786 } 787 break; 788 789 case HCI_EVENT_COMMAND_STATUS: 790 if (hci_event_command_status_get_command_opcode(packet) == hci_setup_synchronous_connection.opcode) { 791 if (sco_establishment_active == NULL) break; 792 status = hci_event_command_status_get_status(packet); 793 if (status == ERROR_CODE_SUCCESS) break; 794 795 hfp_connection = sco_establishment_active; 796 if (hfp_handle_failed_sco_connection(status)) break; 797 hfp_connection->establish_audio_connection = 0; 798 hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; 799 hfp_emit_sco_event(hfp_connection, status, 0, hfp_connection->remote_addr, hfp_connection->negotiated_codec); 800 } 801 break; 802 803 case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{ 804 if (sco_establishment_active == NULL) break; 805 hci_event_synchronous_connection_complete_get_bd_addr(packet, event_addr); 806 hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr, local_role); 807 if (!hfp_connection) { 808 log_error("HFP: connection does not exist for remote with addr %s.", bd_addr_to_str(event_addr)); 809 return; 810 } 811 812 status = hci_event_synchronous_connection_complete_get_status(packet); 813 if (status != ERROR_CODE_SUCCESS){ 814 hfp_connection->accept_sco = 0; 815 if (hfp_handle_failed_sco_connection(status)) break; 816 817 hfp_connection->establish_audio_connection = 0; 818 hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; 819 hfp_emit_sco_event(hfp_connection, status, 0, event_addr, hfp_connection->negotiated_codec); 820 break; 821 } 822 823 uint16_t sco_handle = hci_event_synchronous_connection_complete_get_handle(packet); 824 uint8_t link_type = hci_event_synchronous_connection_complete_get_link_type(packet); 825 uint8_t transmission_interval = hci_event_synchronous_connection_complete_get_transmission_interval(packet); // measured in slots 826 uint8_t retransmission_interval = hci_event_synchronous_connection_complete_get_retransmission_interval(packet);// measured in slots 827 uint16_t rx_packet_length = hci_event_synchronous_connection_complete_get_rx_packet_length(packet); // measured in bytes 828 uint16_t tx_packet_length = hci_event_synchronous_connection_complete_get_tx_packet_length(packet); // measured in bytes 829 830 switch (link_type){ 831 case 0x00: 832 log_info("SCO Connection established."); 833 if (transmission_interval != 0) log_error("SCO Connection: transmission_interval not zero: %d.", transmission_interval); 834 if (retransmission_interval != 0) log_error("SCO Connection: retransmission_interval not zero: %d.", retransmission_interval); 835 if (rx_packet_length != 0) log_error("SCO Connection: rx_packet_length not zero: %d.", rx_packet_length); 836 if (tx_packet_length != 0) log_error("SCO Connection: tx_packet_length not zero: %d.", tx_packet_length); 837 break; 838 case 0x02: 839 log_info("eSCO Connection established. \n"); 840 break; 841 default: 842 log_error("(e)SCO reserved link_type 0x%2x", link_type); 843 break; 844 } 845 846 log_info("sco_handle 0x%2x, address %s, transmission_interval %u slots, retransmission_interval %u slots, " 847 " rx_packet_length %u bytes, tx_packet_length %u bytes, air_mode 0x%2x (0x02 == CVSD)\n", sco_handle, 848 bd_addr_to_str(event_addr), transmission_interval, retransmission_interval, rx_packet_length, tx_packet_length, 849 hci_event_synchronous_connection_complete_get_air_mode(packet)); 850 851 if (hfp_connection->state == HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN){ 852 log_info("SCO about to disconnect: HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN"); 853 hfp_connection->state = HFP_W2_DISCONNECT_SCO; 854 break; 855 } 856 hfp_connection->sco_handle = sco_handle; 857 hfp_connection->establish_audio_connection = 0; 858 hfp_connection->state = HFP_AUDIO_CONNECTION_ESTABLISHED; 859 hfp_emit_sco_event(hfp_connection, status, sco_handle, event_addr, hfp_connection->negotiated_codec); 860 break; 861 } 862 863 case HCI_EVENT_DISCONNECTION_COMPLETE: 864 handle = little_endian_read_16(packet,3); 865 hfp_connection = get_hfp_connection_context_for_sco_handle(handle, local_role); 866 867 if (!hfp_connection) break; 868 869 #ifdef ENABLE_CC256X_ASSISTED_HFP 870 hfp_connection->cc256x_send_wbs_disassociate = true; 871 #endif 872 #ifdef ENABLE_BCM_PCM_WBS 873 hfp_connection->bcm_send_disable_wbs = true; 874 #endif 875 hfp_connection->sco_handle = HCI_CON_HANDLE_INVALID; 876 hfp_connection->release_audio_connection = 0; 877 878 if (hfp_connection->state == HFP_W4_SCO_DISCONNECTED_TO_SHUTDOWN){ 879 // RFCOMM already closed -> remote power off 880 #if defined(ENABLE_CC256X_ASSISTED_HFP) || defined (ENABLE_BCM_PCM_WBS) 881 hfp_connection->state = HFP_W4_WBS_SHUTDOWN; 882 #else 883 hfp_finalize_connection_context(hfp_connection); 884 #endif 885 break; 886 } 887 888 hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; 889 hfp_emit_audio_connection_released(hfp_connection, handle); 890 891 if (hfp_connection->release_slc_connection){ 892 hfp_connection->release_slc_connection = 0; 893 log_info("SCO disconnected, w2 disconnect RFCOMM\n"); 894 hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM; 895 } 896 break; 897 898 default: 899 break; 900 } 901 } 902 903 904 void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, hfp_role_t local_role){ 905 UNUSED(packet_type); 906 UNUSED(channel); // ok: no channel 907 UNUSED(size); 908 909 bd_addr_t event_addr; 910 uint16_t rfcomm_cid; 911 hfp_connection_t * hfp_connection = NULL; 912 uint8_t status; 913 914 log_debug("HFP packet_handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size); 915 916 switch (hci_event_packet_get_type(packet)) { 917 918 case RFCOMM_EVENT_INCOMING_CONNECTION: 919 // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) 920 rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr); 921 hfp_connection = provide_hfp_connection_context_for_bd_addr(event_addr, local_role); 922 if (!hfp_connection){ 923 log_info("hfp: no memory to accept incoming connection - decline"); 924 rfcomm_decline_connection(rfcomm_event_incoming_connection_get_rfcomm_cid(packet)); 925 return; 926 } 927 if (hfp_connection->state != HFP_IDLE) { 928 log_error("hfp: incoming connection but not idle, reject"); 929 rfcomm_decline_connection(rfcomm_event_incoming_connection_get_rfcomm_cid(packet)); 930 return; 931 } 932 933 hfp_connection->rfcomm_cid = rfcomm_event_incoming_connection_get_rfcomm_cid(packet); 934 hfp_connection->state = HFP_W4_RFCOMM_CONNECTED; 935 rfcomm_accept_connection(hfp_connection->rfcomm_cid); 936 break; 937 938 case RFCOMM_EVENT_CHANNEL_OPENED: 939 // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) 940 941 rfcomm_event_channel_opened_get_bd_addr(packet, event_addr); 942 status = rfcomm_event_channel_opened_get_status(packet); 943 944 hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr, local_role); 945 if (!hfp_connection || (hfp_connection->state != HFP_W4_RFCOMM_CONNECTED)) return; 946 947 if (status) { 948 hfp_emit_slc_connection_event(hfp_connection, status, rfcomm_event_channel_opened_get_con_handle(packet), event_addr); 949 hfp_finalize_connection_context(hfp_connection); 950 } else { 951 hfp_connection->acl_handle = rfcomm_event_channel_opened_get_con_handle(packet); 952 hfp_connection->rfcomm_cid = rfcomm_event_channel_opened_get_rfcomm_cid(packet); 953 bd_addr_copy(hfp_connection->remote_addr, event_addr); 954 955 switch (hfp_connection->state){ 956 case HFP_W4_RFCOMM_CONNECTED: 957 hfp_connection->state = HFP_EXCHANGE_SUPPORTED_FEATURES; 958 break; 959 case HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN: 960 hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM; 961 break; 962 default: 963 break; 964 } 965 rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid); 966 } 967 break; 968 969 case RFCOMM_EVENT_CHANNEL_CLOSED: 970 rfcomm_cid = little_endian_read_16(packet,2); 971 hfp_connection = get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid); 972 if (!hfp_connection) break; 973 if (hfp_connection->state == HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART){ 974 hfp_connection->state = HFP_IDLE; 975 hfp_establish_service_level_connection(hfp_connection->remote_addr, hfp_connection->service_uuid, local_role); 976 break; 977 } 978 if ( hfp_connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED){ 979 // service connection was released, this implicitly releases audio connection as well 980 hfp_connection->release_audio_connection = 0; 981 hci_con_handle_t sco_handle = hfp_connection->sco_handle; 982 gap_disconnect(hfp_connection->sco_handle); 983 hfp_connection->state = HFP_W4_SCO_DISCONNECTED_TO_SHUTDOWN; 984 hfp_emit_audio_connection_released(hfp_connection, sco_handle); 985 hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0); 986 } else { 987 // regular case 988 hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0); 989 hfp_finalize_connection_context(hfp_connection); 990 } 991 break; 992 993 default: 994 break; 995 } 996 } 997 // translates command string into hfp_command_t CMD 998 999 typedef struct { 1000 const char * command; 1001 hfp_command_t command_id; 1002 } hfp_command_entry_t; 1003 1004 static hfp_command_entry_t hfp_ag_commmand_table[] = { 1005 { "AT+BAC=", HFP_CMD_AVAILABLE_CODECS }, 1006 { "AT+BCC", HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP }, 1007 { "AT+BCS=", HFP_CMD_HF_CONFIRMED_CODEC }, 1008 { "AT+BIA=", HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, }, // +BIA:<enabled>,,<enabled>,,,<enabled> 1009 { "AT+BIEV=", HFP_CMD_HF_INDICATOR_STATUS }, 1010 { "AT+BIND=", HFP_CMD_LIST_GENERIC_STATUS_INDICATORS }, 1011 { "AT+BIND=?", HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS }, 1012 { "AT+BIND?", HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE }, 1013 { "AT+BINP=", HFP_CMD_HF_REQUEST_PHONE_NUMBER }, 1014 { "AT+BLDN", HFP_CMD_REDIAL_LAST_NUMBER }, 1015 { "AT+BRSF=", HFP_CMD_SUPPORTED_FEATURES }, 1016 { "AT+BTRH=", HFP_CMD_RESPONSE_AND_HOLD_COMMAND }, 1017 { "AT+BTRH?", HFP_CMD_RESPONSE_AND_HOLD_QUERY }, 1018 { "AT+BVRA=", HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION }, 1019 { "AT+CCWA=", HFP_CMD_ENABLE_CALL_WAITING_NOTIFICATION}, 1020 { "AT+CHLD=", HFP_CMD_CALL_HOLD }, 1021 { "AT+CHLD=?", HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES }, 1022 { "AT+CHUP", HFP_CMD_HANG_UP_CALL }, 1023 { "AT+CIND=?", HFP_CMD_RETRIEVE_AG_INDICATORS }, 1024 { "AT+CIND?", HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS }, 1025 { "AT+CLCC", HFP_CMD_LIST_CURRENT_CALLS }, 1026 { "AT+CLIP=", HFP_CMD_ENABLE_CLIP}, 1027 { "AT+CMEE=", HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR}, 1028 { "AT+CMER=", HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE }, 1029 { "AT+CNUM", HFP_CMD_GET_SUBSCRIBER_NUMBER_INFORMATION }, 1030 { "AT+COPS=", HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT }, 1031 { "AT+COPS?", HFP_CMD_QUERY_OPERATOR_SELECTION_NAME }, 1032 { "AT+NREC=", HFP_CMD_TURN_OFF_EC_AND_NR, }, 1033 { "AT+VGM=", HFP_CMD_SET_MICROPHONE_GAIN }, 1034 { "AT+VGS=", HFP_CMD_SET_SPEAKER_GAIN }, 1035 { "AT+VTS=", HFP_CMD_TRANSMIT_DTMF_CODES }, 1036 { "ATA", HFP_CMD_CALL_ANSWERED }, 1037 }; 1038 1039 static hfp_command_entry_t hfp_hf_commmand_table[] = { 1040 { "+BCS:", HFP_CMD_AG_SUGGESTED_CODEC }, 1041 { "+BIND:", HFP_CMD_SET_GENERIC_STATUS_INDICATOR_STATUS }, 1042 { "+BINP", HFP_CMD_AG_SENT_PHONE_NUMBER }, 1043 { "+BRSF:", HFP_CMD_SUPPORTED_FEATURES }, 1044 { "+BSIR:", HFP_CMD_CHANGE_IN_BAND_RING_TONE_SETTING }, 1045 { "+BTRH:", HFP_CMD_RESPONSE_AND_HOLD_STATUS }, 1046 { "+BVRA:", HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION }, 1047 { "+CCWA:", HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE, }, 1048 { "+CHLD:", HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES }, 1049 { "+CIEV:", HFP_CMD_TRANSFER_AG_INDICATOR_STATUS}, 1050 { "+CIND:", HFP_CMD_RETRIEVE_AG_INDICATORS_GENERIC }, 1051 { "+CLCC:", HFP_CMD_LIST_CURRENT_CALLS }, 1052 { "+CLIP:", HFP_CMD_AG_SENT_CLIP_INFORMATION }, 1053 { "+CME ERROR:", HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR }, 1054 { "+CNUM:", HFP_CMD_GET_SUBSCRIBER_NUMBER_INFORMATION}, 1055 { "+COPS:", HFP_CMD_QUERY_OPERATOR_SELECTION_NAME }, 1056 { "+VGM:", HFP_CMD_SET_MICROPHONE_GAIN }, 1057 { "+VGS:", HFP_CMD_SET_SPEAKER_GAIN}, 1058 { "ERROR", HFP_CMD_ERROR}, 1059 { "NOP", HFP_CMD_NONE}, // dummy command used by unit tests 1060 { "OK", HFP_CMD_OK }, 1061 { "RING", HFP_CMD_RING }, 1062 }; 1063 1064 static hfp_command_t parse_command(const char * line_buffer, int isHandsFree){ 1065 1066 // table lookup based on role 1067 uint16_t num_entries; 1068 hfp_command_entry_t * table; 1069 if (isHandsFree == 0){ 1070 table = hfp_ag_commmand_table; 1071 num_entries = sizeof(hfp_ag_commmand_table) / sizeof(hfp_command_entry_t); 1072 } else { 1073 table = hfp_hf_commmand_table; 1074 num_entries = sizeof(hfp_hf_commmand_table) / sizeof(hfp_command_entry_t); 1075 } 1076 // binary search 1077 uint16_t left = 0; 1078 uint16_t right = num_entries - 1; 1079 while (left <= right){ 1080 uint16_t middle = left + (right - left) / 2; 1081 hfp_command_entry_t *entry = &table[middle]; 1082 int match = strcmp(line_buffer, entry->command); 1083 if (match < 0){ 1084 // search term is lower than middle element 1085 if (right == 0) break; 1086 right = middle - 1; 1087 } else if (match == 0){ 1088 return entry->command_id; 1089 } else { 1090 // search term is higher than middle element 1091 left = middle + 1; 1092 } 1093 } 1094 1095 // note: if parser in CMD_HEADER state would treats digits and maybe '+' as separator, match on "ATD" would work. 1096 // note: phone number is currently expected in line_buffer[3..] 1097 // prefix match on 'ATD', AG only 1098 if ((isHandsFree == 0) && (strncmp(line_buffer, HFP_CALL_PHONE_NUMBER, strlen(HFP_CALL_PHONE_NUMBER)) == 0)){ 1099 return HFP_CMD_CALL_PHONE_NUMBER; 1100 } 1101 1102 // Valid looking, but unknown commands/responses 1103 if ((isHandsFree == 0) && (strncmp(line_buffer, "AT+", 3) == 0)){ 1104 return HFP_CMD_UNKNOWN; 1105 } 1106 1107 if ((isHandsFree != 0) && (strncmp(line_buffer, "+", 1) == 0)){ 1108 return HFP_CMD_UNKNOWN; 1109 } 1110 1111 return HFP_CMD_NONE; 1112 } 1113 1114 static void hfp_parser_store_byte(hfp_connection_t * hfp_connection, uint8_t byte){ 1115 if ((hfp_connection->line_size + 1 ) >= HFP_MAX_INDICATOR_DESC_SIZE) return; 1116 hfp_connection->line_buffer[hfp_connection->line_size++] = byte; 1117 hfp_connection->line_buffer[hfp_connection->line_size] = 0; 1118 } 1119 static int hfp_parser_is_buffer_empty(hfp_connection_t * hfp_connection){ 1120 return hfp_connection->line_size == 0; 1121 } 1122 1123 static int hfp_parser_is_end_of_line(uint8_t byte){ 1124 return (byte == '\n') || (byte == '\r'); 1125 } 1126 1127 static void hfp_parser_reset_line_buffer(hfp_connection_t *hfp_connection) { 1128 hfp_connection->line_size = 0; 1129 } 1130 1131 static void hfp_parser_store_if_token(hfp_connection_t * hfp_connection, uint8_t byte){ 1132 switch (byte){ 1133 case ',': 1134 case '-': 1135 case ';': 1136 case '(': 1137 case ')': 1138 case '\n': 1139 case '\r': 1140 break; 1141 default: 1142 hfp_parser_store_byte(hfp_connection, byte); 1143 break; 1144 } 1145 } 1146 1147 static bool hfp_parser_is_separator( uint8_t byte){ 1148 switch (byte){ 1149 case ',': 1150 case '-': 1151 case ';': 1152 case '\n': 1153 case '\r': 1154 return true; 1155 default: 1156 return false; 1157 } 1158 } 1159 1160 static bool hfp_parse_byte(hfp_connection_t * hfp_connection, uint8_t byte, int isHandsFree){ 1161 1162 // handle doubles quotes 1163 if (byte == '"'){ 1164 hfp_connection->parser_quoted = !hfp_connection->parser_quoted; 1165 return true; 1166 } 1167 if (hfp_connection->parser_quoted) { 1168 hfp_parser_store_byte(hfp_connection, byte); 1169 return true; 1170 } 1171 1172 // ignore spaces outside command or double quotes (required e.g. for '+CME ERROR:..") command 1173 if ((byte == ' ') && (hfp_connection->parser_state != HFP_PARSER_CMD_HEADER)) return true; 1174 1175 bool processed = true; 1176 1177 switch (hfp_connection->parser_state) { 1178 case HFP_PARSER_CMD_HEADER: 1179 switch (byte) { 1180 case '\n': 1181 case '\r': 1182 case ';': 1183 // ignore separator 1184 break; 1185 case ':': 1186 case '?': 1187 // store separator 1188 hfp_parser_store_byte(hfp_connection, byte); 1189 break; 1190 case '=': 1191 // equal sign: remember and wait for next char to decided between '=?' and '=\?' 1192 hfp_connection->found_equal_sign = true; 1193 hfp_parser_store_byte(hfp_connection, byte); 1194 return true; 1195 default: 1196 // store if not lookahead 1197 if (!hfp_connection->found_equal_sign) { 1198 hfp_parser_store_byte(hfp_connection, byte); 1199 return true; 1200 } 1201 // mark as lookahead 1202 processed = false; 1203 break; 1204 } 1205 1206 // ignore empty tokens 1207 if (hfp_parser_is_buffer_empty(hfp_connection)) return true; 1208 1209 // parse 1210 hfp_connection->command = parse_command((char *)hfp_connection->line_buffer, isHandsFree); 1211 1212 // pick +CIND version based on connection state: descriptions during SLC vs. states later 1213 if (hfp_connection->command == HFP_CMD_RETRIEVE_AG_INDICATORS_GENERIC){ 1214 switch(hfp_connection->state){ 1215 case HFP_W4_RETRIEVE_INDICATORS_STATUS: 1216 hfp_connection->command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS; 1217 break; 1218 case HFP_W4_RETRIEVE_INDICATORS: 1219 hfp_connection->command = HFP_CMD_RETRIEVE_AG_INDICATORS; 1220 break; 1221 default: 1222 hfp_connection->command = HFP_CMD_UNKNOWN; 1223 break; 1224 } 1225 } 1226 1227 log_info("command string '%s', handsfree %u -> cmd id %u", (char *)hfp_connection->line_buffer, isHandsFree, hfp_connection->command); 1228 1229 // next state 1230 hfp_connection->found_equal_sign = false; 1231 hfp_parser_reset_line_buffer(hfp_connection); 1232 hfp_connection->parser_state = HFP_PARSER_CMD_SEQUENCE; 1233 1234 return processed; 1235 1236 case HFP_PARSER_CMD_SEQUENCE: 1237 // handle empty fields 1238 if ((byte == ',' ) && (hfp_connection->line_size == 0)){ 1239 hfp_connection->line_buffer[0] = 0; 1240 hfp_connection->ignore_value = 1; 1241 parse_sequence(hfp_connection); 1242 return true; 1243 } 1244 1245 hfp_parser_store_if_token(hfp_connection, byte); 1246 if (!hfp_parser_is_separator(byte)) return true; 1247 1248 // ignore empty tokens 1249 if (hfp_parser_is_buffer_empty(hfp_connection) && (hfp_connection->ignore_value == 0)) return true; 1250 1251 parse_sequence(hfp_connection); 1252 1253 hfp_parser_reset_line_buffer(hfp_connection); 1254 1255 switch (hfp_connection->command){ 1256 case HFP_CMD_AG_SENT_PHONE_NUMBER: 1257 case HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE: 1258 case HFP_CMD_AG_SENT_CLIP_INFORMATION: 1259 case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: 1260 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: 1261 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: 1262 case HFP_CMD_RETRIEVE_AG_INDICATORS: 1263 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: 1264 case HFP_CMD_HF_INDICATOR_STATUS: 1265 hfp_connection->parser_state = HFP_PARSER_SECOND_ITEM; 1266 break; 1267 default: 1268 break; 1269 } 1270 return true; 1271 1272 case HFP_PARSER_SECOND_ITEM: 1273 1274 hfp_parser_store_if_token(hfp_connection, byte); 1275 if (!hfp_parser_is_separator(byte)) return true; 1276 1277 switch (hfp_connection->command){ 1278 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: 1279 log_info("format %s, ", hfp_connection->line_buffer); 1280 hfp_connection->network_operator.format = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1281 break; 1282 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: 1283 log_info("format %s \n", hfp_connection->line_buffer); 1284 hfp_connection->network_operator.format = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1285 break; 1286 case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS: 1287 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS: 1288 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: 1289 hfp_connection->generic_status_indicators[hfp_connection->parser_item_index].state = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer); 1290 break; 1291 case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: 1292 hfp_connection->ag_indicators[hfp_connection->parser_item_index].status = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer); 1293 log_info("%d \n", hfp_connection->ag_indicators[hfp_connection->parser_item_index].status); 1294 hfp_connection->ag_indicators[hfp_connection->parser_item_index].status_changed = 1; 1295 break; 1296 case HFP_CMD_RETRIEVE_AG_INDICATORS: 1297 hfp_connection->ag_indicators[hfp_connection->parser_item_index].min_range = btstack_atoi((char *)hfp_connection->line_buffer); 1298 log_info("%s, ", hfp_connection->line_buffer); 1299 break; 1300 case HFP_CMD_AG_SENT_PHONE_NUMBER: 1301 case HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE: 1302 case HFP_CMD_AG_SENT_CLIP_INFORMATION: 1303 hfp_connection->bnip_type = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer); 1304 break; 1305 case HFP_CMD_HF_INDICATOR_STATUS: 1306 hfp_connection->parser_indicator_value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1307 break; 1308 default: 1309 break; 1310 } 1311 1312 hfp_parser_reset_line_buffer(hfp_connection); 1313 1314 hfp_connection->parser_state = HFP_PARSER_THIRD_ITEM; 1315 1316 return true; 1317 1318 case HFP_PARSER_THIRD_ITEM: 1319 1320 hfp_parser_store_if_token(hfp_connection, byte); 1321 if (!hfp_parser_is_separator(byte)) return true; 1322 1323 switch (hfp_connection->command){ 1324 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: 1325 strncpy(hfp_connection->network_operator.name, (char *)hfp_connection->line_buffer, HFP_MAX_NETWORK_OPERATOR_NAME_SIZE); 1326 hfp_connection->network_operator.name[HFP_MAX_NETWORK_OPERATOR_NAME_SIZE - 1] = 0; 1327 log_info("name %s\n", hfp_connection->line_buffer); 1328 break; 1329 case HFP_CMD_RETRIEVE_AG_INDICATORS: 1330 hfp_connection->ag_indicators[hfp_connection->parser_item_index].max_range = btstack_atoi((char *)hfp_connection->line_buffer); 1331 hfp_next_indicators_index(hfp_connection); 1332 hfp_connection->ag_indicators_nr = hfp_connection->parser_item_index; 1333 log_info("%s)\n", hfp_connection->line_buffer); 1334 break; 1335 default: 1336 break; 1337 } 1338 1339 hfp_parser_reset_line_buffer(hfp_connection); 1340 1341 if (hfp_connection->command == HFP_CMD_RETRIEVE_AG_INDICATORS){ 1342 hfp_connection->parser_state = HFP_PARSER_CMD_SEQUENCE; 1343 } else { 1344 hfp_connection->parser_state = HFP_PARSER_CMD_HEADER; 1345 } 1346 return true; 1347 1348 default: 1349 btstack_assert(false); 1350 return true; 1351 } 1352 } 1353 1354 void hfp_parse(hfp_connection_t * hfp_connection, uint8_t byte, int isHandsFree){ 1355 bool processed = false; 1356 while (!processed){ 1357 processed = hfp_parse_byte(hfp_connection, byte, isHandsFree); 1358 } 1359 // reset parser state on end-of-line 1360 if (hfp_parser_is_end_of_line(byte)){ 1361 hfp_connection->parser_item_index = 0; 1362 hfp_connection->parser_state = HFP_PARSER_CMD_HEADER; 1363 } 1364 } 1365 1366 static void parse_sequence(hfp_connection_t * hfp_connection){ 1367 int value; 1368 switch (hfp_connection->command){ 1369 case HFP_CMD_SET_GENERIC_STATUS_INDICATOR_STATUS: 1370 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1371 int i; 1372 switch (hfp_connection->parser_item_index){ 1373 case 0: 1374 for (i=0;i<hfp_connection->generic_status_indicators_nr;i++){ 1375 if (hfp_connection->generic_status_indicators[i].uuid == value){ 1376 hfp_connection->parser_indicator_index = i; 1377 break; 1378 } 1379 } 1380 break; 1381 case 1: 1382 if (hfp_connection->parser_indicator_index <0) break; 1383 hfp_connection->generic_status_indicators[hfp_connection->parser_indicator_index].state = value; 1384 log_info("HFP_CMD_SET_GENERIC_STATUS_INDICATOR_STATUS set indicator at index %u, to %u\n", 1385 hfp_connection->parser_item_index, value); 1386 break; 1387 default: 1388 break; 1389 } 1390 hfp_next_indicators_index(hfp_connection); 1391 break; 1392 1393 case HFP_CMD_GET_SUBSCRIBER_NUMBER_INFORMATION: 1394 switch(hfp_connection->parser_item_index){ 1395 case 0: 1396 // <alpha>: This optional field is not supported, and shall be left blank. 1397 break; 1398 case 1: 1399 // <number>: Quoted string containing the phone number in the format specified by <type>. 1400 strncpy(hfp_connection->bnip_number, (char *)hfp_connection->line_buffer, sizeof(hfp_connection->bnip_number)); 1401 hfp_connection->bnip_number[sizeof(hfp_connection->bnip_number)-1] = 0; 1402 break; 1403 case 2: 1404 /* 1405 <type> field specifies the format of the phone number provided, and can be one of the following values: 1406 - values 128-143: The phone number format may be a national or international format, and may contain prefix and/or escape digits. No changes on the number presentation are required. 1407 - values 144-159: The phone number format is an international number, including the country code prefix. If the plus sign ("+") is not included as part of the number and shall be added by the AG as needed. 1408 - values 160-175: National number. No prefix nor escape digits included. 1409 */ 1410 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1411 hfp_connection->bnip_type = value; 1412 break; 1413 case 3: 1414 // <speed>: This optional field is not supported, and shall be left blank. 1415 break; 1416 case 4: 1417 // <service>: Indicates which service this phone number relates to. Shall be either 4 (voice) or 5 (fax). 1418 default: 1419 break; 1420 } 1421 // index > 2 are ignored in switch above 1422 hfp_connection->parser_item_index++; 1423 break; 1424 case HFP_CMD_LIST_CURRENT_CALLS: 1425 switch(hfp_connection->parser_item_index){ 1426 case 0: 1427 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1428 hfp_connection->clcc_idx = value; 1429 break; 1430 case 1: 1431 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1432 hfp_connection->clcc_dir = value; 1433 break; 1434 case 2: 1435 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1436 hfp_connection->clcc_status = value; 1437 break; 1438 case 3: 1439 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1440 hfp_connection->clcc_mode = value; 1441 break; 1442 case 4: 1443 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1444 hfp_connection->clcc_mpty = value; 1445 break; 1446 case 5: 1447 strncpy(hfp_connection->bnip_number, (char *)hfp_connection->line_buffer, sizeof(hfp_connection->bnip_number)); 1448 hfp_connection->bnip_number[sizeof(hfp_connection->bnip_number)-1] = 0; 1449 break; 1450 case 6: 1451 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1452 hfp_connection->bnip_type = value; 1453 break; 1454 default: 1455 break; 1456 } 1457 // index > 6 are ignored in switch above 1458 hfp_connection->parser_item_index++; 1459 break; 1460 case HFP_CMD_SET_MICROPHONE_GAIN: 1461 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1462 hfp_connection->microphone_gain = value; 1463 log_info("hfp parse HFP_CMD_SET_MICROPHONE_GAIN %d\n", value); 1464 break; 1465 case HFP_CMD_SET_SPEAKER_GAIN: 1466 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1467 hfp_connection->speaker_gain = value; 1468 log_info("hfp parse HFP_CMD_SET_SPEAKER_GAIN %d\n", value); 1469 break; 1470 case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION: 1471 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1472 hfp_connection->ag_activate_voice_recognition = value; 1473 log_info("hfp parse HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION %d\n", value); 1474 break; 1475 case HFP_CMD_TURN_OFF_EC_AND_NR: 1476 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1477 hfp_connection->ag_echo_and_noise_reduction = value; 1478 log_info("hfp parse HFP_CMD_TURN_OFF_EC_AND_NR %d\n", value); 1479 break; 1480 case HFP_CMD_CHANGE_IN_BAND_RING_TONE_SETTING: 1481 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1482 hfp_connection->remote_supported_features = store_bit(hfp_connection->remote_supported_features, HFP_AGSF_IN_BAND_RING_TONE, value); 1483 log_info("hfp parse HFP_CHANGE_IN_BAND_RING_TONE_SETTING %d\n", value); 1484 break; 1485 case HFP_CMD_HF_CONFIRMED_CODEC: 1486 hfp_connection->codec_confirmed = btstack_atoi((char*)hfp_connection->line_buffer); 1487 log_info("hfp parse HFP_CMD_HF_CONFIRMED_CODEC %d\n", hfp_connection->codec_confirmed); 1488 break; 1489 case HFP_CMD_AG_SUGGESTED_CODEC: 1490 hfp_connection->suggested_codec = btstack_atoi((char*)hfp_connection->line_buffer); 1491 log_info("hfp parse HFP_CMD_AG_SUGGESTED_CODEC %d\n", hfp_connection->suggested_codec); 1492 break; 1493 case HFP_CMD_SUPPORTED_FEATURES: 1494 hfp_connection->remote_supported_features = btstack_atoi((char*)hfp_connection->line_buffer); 1495 log_info("Parsed supported feature %d\n", (int) hfp_connection->remote_supported_features); 1496 break; 1497 case HFP_CMD_AVAILABLE_CODECS: 1498 log_info("Parsed codec %s\n", hfp_connection->line_buffer); 1499 hfp_connection->remote_codecs[hfp_connection->parser_item_index] = (uint16_t)btstack_atoi((char*)hfp_connection->line_buffer); 1500 hfp_next_codec_index(hfp_connection); 1501 hfp_connection->remote_codecs_nr = hfp_connection->parser_item_index; 1502 break; 1503 case HFP_CMD_RETRIEVE_AG_INDICATORS: 1504 strncpy((char *)hfp_connection->ag_indicators[hfp_connection->parser_item_index].name, (char *)hfp_connection->line_buffer, HFP_MAX_INDICATOR_DESC_SIZE); 1505 hfp_connection->ag_indicators[hfp_connection->parser_item_index].name[HFP_MAX_INDICATOR_DESC_SIZE-1] = 0; 1506 hfp_connection->ag_indicators[hfp_connection->parser_item_index].index = hfp_connection->parser_item_index+1; 1507 log_info("Indicator %d: %s (", hfp_connection->ag_indicators_nr+1, hfp_connection->line_buffer); 1508 break; 1509 case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS: 1510 log_info("Parsed Indicator %d with status: %s\n", hfp_connection->parser_item_index+1, hfp_connection->line_buffer); 1511 hfp_connection->ag_indicators[hfp_connection->parser_item_index].status = btstack_atoi((char *) hfp_connection->line_buffer); 1512 hfp_next_indicators_index(hfp_connection); 1513 break; 1514 case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE: 1515 hfp_next_indicators_index(hfp_connection); 1516 if (hfp_connection->parser_item_index != 4) break; 1517 log_info("Parsed Enable indicators: %s\n", hfp_connection->line_buffer); 1518 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1519 hfp_connection->enable_status_update_for_ag_indicators = (uint8_t) value; 1520 break; 1521 case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES: 1522 log_info("Parsed Support call hold: %s\n", hfp_connection->line_buffer); 1523 if (hfp_connection->line_size > 2 ) break; 1524 memcpy((char *)hfp_connection->remote_call_services[hfp_connection->remote_call_services_index].name, (char *)hfp_connection->line_buffer, HFP_CALL_SERVICE_SIZE-1); 1525 hfp_connection->remote_call_services[hfp_connection->remote_call_services_index].name[HFP_CALL_SERVICE_SIZE - 1] = 0; 1526 hfp_next_remote_call_services_index(hfp_connection); 1527 break; 1528 case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS: 1529 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS: 1530 log_info("Parsed Generic status indicator: %s\n", hfp_connection->line_buffer); 1531 hfp_connection->generic_status_indicators[hfp_connection->parser_item_index].uuid = (uint16_t)btstack_atoi((char*)hfp_connection->line_buffer); 1532 hfp_next_indicators_index(hfp_connection); 1533 hfp_connection->generic_status_indicators_nr = hfp_connection->parser_item_index; 1534 break; 1535 case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE: 1536 // HF parses inital AG gen. ind. state 1537 log_info("Parsed List generic status indicator %s state: ", hfp_connection->line_buffer); 1538 hfp_connection->parser_item_index = hfp_parse_indicator_index(hfp_connection); 1539 break; 1540 case HFP_CMD_HF_INDICATOR_STATUS: 1541 hfp_connection->parser_indicator_index = hfp_parse_indicator_index(hfp_connection); 1542 log_info("Parsed HF indicator index %u", hfp_connection->parser_indicator_index); 1543 break; 1544 case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE: 1545 // AG parses new gen. ind. state 1546 if (hfp_connection->ignore_value){ 1547 hfp_connection->ignore_value = 0; 1548 log_info("Parsed Enable AG indicator pos %u('%s') - unchanged (stays %u)\n", hfp_connection->parser_item_index, 1549 hfp_connection->ag_indicators[hfp_connection->parser_item_index].name, hfp_connection->ag_indicators[hfp_connection->parser_item_index].enabled); 1550 } 1551 else if (hfp_connection->ag_indicators[hfp_connection->parser_item_index].mandatory){ 1552 log_info("Parsed Enable AG indicator pos %u('%s') - ignore (mandatory)\n", 1553 hfp_connection->parser_item_index, hfp_connection->ag_indicators[hfp_connection->parser_item_index].name); 1554 } else { 1555 value = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1556 hfp_connection->ag_indicators[hfp_connection->parser_item_index].enabled = value; 1557 log_info("Parsed Enable AG indicator pos %u('%s'): %u\n", hfp_connection->parser_item_index, 1558 hfp_connection->ag_indicators[hfp_connection->parser_item_index].name, value); 1559 } 1560 hfp_next_indicators_index(hfp_connection); 1561 break; 1562 case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS: 1563 // indicators are indexed starting with 1 1564 hfp_connection->parser_item_index = hfp_parse_indicator_index(hfp_connection); 1565 log_info("Parsed status of the AG indicator %d, status ", hfp_connection->parser_item_index); 1566 break; 1567 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME: 1568 hfp_connection->network_operator.mode = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1569 log_info("Parsed network operator mode: %d, ", hfp_connection->network_operator.mode); 1570 break; 1571 case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT: 1572 if (hfp_connection->line_buffer[0] == '3'){ 1573 log_info("Parsed Set network operator format : %s, ", hfp_connection->line_buffer); 1574 break; 1575 } 1576 // TODO emit ERROR, wrong format 1577 log_info("ERROR Set network operator format: index %s not supported\n", hfp_connection->line_buffer); 1578 break; 1579 case HFP_CMD_ERROR: 1580 break; 1581 case HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR: 1582 hfp_connection->extended_audio_gateway_error = 1; 1583 hfp_connection->extended_audio_gateway_error_value = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer); 1584 break; 1585 case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR: 1586 hfp_connection->enable_extended_audio_gateway_error_report = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer); 1587 hfp_connection->ok_pending = 1; 1588 hfp_connection->extended_audio_gateway_error = 0; 1589 break; 1590 case HFP_CMD_AG_SENT_PHONE_NUMBER: 1591 case HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE: 1592 case HFP_CMD_AG_SENT_CLIP_INFORMATION: 1593 strncpy(hfp_connection->bnip_number, (char *)hfp_connection->line_buffer, sizeof(hfp_connection->bnip_number)); 1594 hfp_connection->bnip_number[sizeof(hfp_connection->bnip_number)-1] = 0; 1595 break; 1596 case HFP_CMD_CALL_HOLD: 1597 hfp_connection->ag_call_hold_action = hfp_connection->line_buffer[0] - '0'; 1598 if (hfp_connection->line_buffer[1] != '\0'){ 1599 hfp_connection->call_index = btstack_atoi((char *)&hfp_connection->line_buffer[1]); 1600 } 1601 break; 1602 case HFP_CMD_RESPONSE_AND_HOLD_COMMAND: 1603 hfp_connection->ag_response_and_hold_action = btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1604 break; 1605 case HFP_CMD_TRANSMIT_DTMF_CODES: 1606 hfp_connection->ag_dtmf_code = hfp_connection->line_buffer[0]; 1607 break; 1608 case HFP_CMD_ENABLE_CLIP: 1609 hfp_connection->clip_enabled = hfp_connection->line_buffer[0] != '0'; 1610 break; 1611 case HFP_CMD_ENABLE_CALL_WAITING_NOTIFICATION: 1612 hfp_connection->call_waiting_notification_enabled = hfp_connection->line_buffer[0] != '0'; 1613 break; 1614 case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION: 1615 switch(hfp_connection->parser_item_index){ 1616 case 0: 1617 hfp_connection->ag_vra_status = (hfp_voice_recognition_activation_status_t) btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1618 break; 1619 case 1: 1620 hfp_connection->ag_vra_state = (hfp_voice_recognition_state_t) btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1621 hfp_emit_enhanced_voice_recognition_state(hfp_connection); 1622 break; 1623 case 2: 1624 hfp_connection->ag_msg.text_id = 0; 1625 for (i = 0 ; i < 4; i++){ 1626 hfp_connection->ag_msg.text_id = (hfp_connection->ag_msg.text_id << 4) | nibble_for_char(hfp_connection->line_buffer[i]); 1627 } 1628 break; 1629 case 3: 1630 hfp_connection->ag_msg.text_operation = (hfp_text_operation_t) btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1631 break; 1632 case 4: 1633 hfp_connection->ag_msg.text_type = (hfp_text_type_t) btstack_atoi((char *)&hfp_connection->line_buffer[0]); 1634 break; 1635 case 5: 1636 printf("text%s\n", hfp_connection->line_buffer); 1637 hfp_emit_enhanced_voice_recognition_text(hfp_connection, hfp_connection->line_size, &hfp_connection->line_buffer[0]); 1638 break; 1639 default: 1640 break; 1641 } 1642 break; 1643 default: 1644 break; 1645 } 1646 } 1647 1648 static void hfp_handle_start_sdp_client_query(void * context){ 1649 UNUSED(context); 1650 1651 btstack_linked_list_iterator_t it; 1652 btstack_linked_list_iterator_init(&it, &hfp_connections); 1653 while (btstack_linked_list_iterator_has_next(&it)){ 1654 hfp_connection_t * connection = (hfp_connection_t *)btstack_linked_list_iterator_next(&it); 1655 1656 if (connection->state != HFP_W2_SEND_SDP_QUERY) continue; 1657 1658 connection->state = HFP_W4_SDP_QUERY_COMPLETE; 1659 sdp_query_context.local_role = connection->local_role; 1660 (void)memcpy(sdp_query_context.remote_address, connection->remote_addr, 6); 1661 sdp_client_query_rfcomm_channel_and_name_for_service_class_uuid(&handle_query_rfcomm_event, connection->remote_addr, connection->service_uuid); 1662 return; 1663 } 1664 } 1665 1666 void hfp_establish_service_level_connection(bd_addr_t bd_addr, uint16_t service_uuid, hfp_role_t local_role){ 1667 hfp_connection_t * hfp_connection = provide_hfp_connection_context_for_bd_addr(bd_addr, local_role); 1668 log_info("hfp_connect %s, hfp_connection %p", bd_addr_to_str(bd_addr), hfp_connection); 1669 1670 if (!hfp_connection) { 1671 log_error("hfp_establish_service_level_connection for addr %s failed", bd_addr_to_str(bd_addr)); 1672 return; 1673 } 1674 switch (hfp_connection->state){ 1675 case HFP_W2_DISCONNECT_RFCOMM: 1676 hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; 1677 return; 1678 case HFP_W4_RFCOMM_DISCONNECTED: 1679 hfp_connection->state = HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART; 1680 return; 1681 case HFP_IDLE: 1682 (void)memcpy(hfp_connection->remote_addr, bd_addr, 6); 1683 hfp_connection->state = HFP_W2_SEND_SDP_QUERY; 1684 hfp_connection->service_uuid = service_uuid; 1685 1686 hfp_handle_sdp_client_query_request.callback = &hfp_handle_start_sdp_client_query; 1687 // ignore ERROR_CODE_COMMAND_DISALLOWED because in that case, we already have requested an SDP callback 1688 (void) sdp_client_register_query_callback(&hfp_handle_sdp_client_query_request); 1689 break; 1690 default: 1691 break; 1692 } 1693 } 1694 1695 void hfp_release_service_level_connection(hfp_connection_t * hfp_connection){ 1696 if (!hfp_connection) return; 1697 hfp_release_audio_connection(hfp_connection); 1698 1699 if (hfp_connection->state < HFP_W4_RFCOMM_CONNECTED){ 1700 hfp_connection->state = HFP_IDLE; 1701 return; 1702 } 1703 1704 if (hfp_connection->state == HFP_W4_RFCOMM_CONNECTED){ 1705 hfp_connection->state = HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN; 1706 return; 1707 } 1708 1709 if (hfp_connection->state < HFP_W4_SCO_CONNECTED){ 1710 hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM; 1711 return; 1712 } 1713 1714 if (hfp_connection->state < HFP_W4_SCO_DISCONNECTED){ 1715 hfp_connection->state = HFP_W2_DISCONNECT_SCO; 1716 return; 1717 } 1718 1719 // HFP_W4_SCO_DISCONNECTED or later 1720 hfp_connection->release_slc_connection = 1; 1721 } 1722 1723 void hfp_release_audio_connection(hfp_connection_t * hfp_connection){ 1724 if (!hfp_connection) return; 1725 if (hfp_connection->state >= HFP_W2_DISCONNECT_SCO) return; 1726 hfp_connection->release_audio_connection = 1; 1727 } 1728 1729 static const struct link_settings { 1730 const uint16_t max_latency; 1731 const uint8_t retransmission_effort; 1732 const uint16_t packet_types; 1733 const bool eSCO; 1734 const uint8_t codec; 1735 } hfp_link_settings [] = { 1736 { 0xffff, 0xff, SCO_PACKET_TYPES_HV1, false, HFP_CODEC_CVSD }, // HFP_LINK_SETTINGS_D0 1737 { 0xffff, 0xff, SCO_PACKET_TYPES_HV3, false, HFP_CODEC_CVSD }, // HFP_LINK_SETTINGS_D1 1738 { 0x0007, 0x01, SCO_PACKET_TYPES_EV3, true, HFP_CODEC_CVSD }, // HFP_LINK_SETTINGS_S1 1739 { 0x0007, 0x01, SCO_PACKET_TYPES_2EV3, true, HFP_CODEC_CVSD }, // HFP_LINK_SETTINGS_S2 1740 { 0x000a, 0x01, SCO_PACKET_TYPES_2EV3, true, HFP_CODEC_CVSD }, // HFP_LINK_SETTINGS_S3 1741 { 0x000c, 0x02, SCO_PACKET_TYPES_2EV3, true, HFP_CODEC_CVSD }, // HFP_LINK_SETTINGS_S4 1742 { 0x0008, 0x02, SCO_PACKET_TYPES_EV3, true, HFP_CODEC_MSBC }, // HFP_LINK_SETTINGS_T1 1743 { 0x000d, 0x02, SCO_PACKET_TYPES_2EV3, true, HFP_CODEC_MSBC } // HFP_LINK_SETTINGS_T2 1744 }; 1745 1746 void hfp_setup_synchronous_connection(hfp_connection_t * hfp_connection){ 1747 // all packet types, fixed bandwidth 1748 int setting = hfp_connection->link_setting; 1749 log_info("hfp_setup_synchronous_connection using setting nr %u", setting); 1750 sco_establishment_active = hfp_connection; 1751 uint16_t sco_voice_setting = hci_get_sco_voice_setting(); 1752 if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){ 1753 #ifdef ENABLE_BCM_PCM_WBS 1754 sco_voice_setting = 0x0063; // Transparent data, 16-bit for BCM controllers 1755 #else 1756 sco_voice_setting = 0x0043; // Transparent data, 8-bit otherwise 1757 #endif 1758 } 1759 // get packet types - bits 6-9 are 'don't allow' 1760 uint16_t packet_types = hfp_link_settings[setting].packet_types ^ 0x03c0; 1761 hci_send_cmd(&hci_setup_synchronous_connection, hfp_connection->acl_handle, 8000, 8000, hfp_link_settings[setting].max_latency, 1762 sco_voice_setting, hfp_link_settings[setting].retransmission_effort, packet_types); 1763 } 1764 1765 void hfp_accept_synchronous_connection(hfp_connection_t * hfp_connection, bool incoming_eSCO){ 1766 1767 // remote supported feature eSCO is set if link type is eSCO 1768 // eSCO: S4 - max latency == transmission interval = 0x000c == 12 ms, 1769 uint16_t max_latency; 1770 uint8_t retransmission_effort; 1771 uint16_t packet_types; 1772 1773 if (incoming_eSCO && hci_extended_sco_link_supported() && hci_remote_esco_supported(hfp_connection->acl_handle)){ 1774 max_latency = 0x000c; 1775 retransmission_effort = 0x02; 1776 // eSCO: EV3 and 2-EV3 1777 packet_types = 0x0048; 1778 } else { 1779 max_latency = 0xffff; 1780 retransmission_effort = 0xff; 1781 // sco: HV1 and HV3 1782 packet_types = 0x005; 1783 } 1784 1785 // mSBC only allows for transparent data 1786 uint16_t sco_voice_setting = hci_get_sco_voice_setting(); 1787 if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){ 1788 #ifdef ENABLE_BCM_PCM_WBS 1789 sco_voice_setting = 0x0063; // Transparent data, 16-bit for BCM controllers 1790 #else 1791 sco_voice_setting = 0x0043; // Transparent data, 8-bit otherwise 1792 #endif 1793 } 1794 1795 // filter packet types 1796 packet_types &= hfp_get_sco_packet_types(); 1797 1798 // bits 6-9 are 'don't allow' 1799 packet_types ^= 0x3c0; 1800 1801 log_info("HFP: sending hci_accept_connection_request, packet types 0x%04x, sco_voice_setting 0x%02x", packet_types, sco_voice_setting); 1802 hci_send_cmd(&hci_accept_synchronous_connection, hfp_connection->remote_addr, 8000, 8000, max_latency, 1803 sco_voice_setting, retransmission_effort, packet_types); 1804 } 1805 1806 #ifdef ENABLE_CC256X_ASSISTED_HFP 1807 void hfp_cc256x_prepare_for_sco(hfp_connection_t * hfp_connection){ 1808 hfp_connection->cc256x_send_write_codec_config = true; 1809 if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){ 1810 hfp_connection->cc256x_send_wbs_associate = true; 1811 } 1812 } 1813 1814 void hfp_cc256x_write_codec_config(hfp_connection_t * hfp_connection){ 1815 uint32_t sample_rate_hz; 1816 uint16_t clock_rate_khz; 1817 if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){ 1818 clock_rate_khz = 512; 1819 sample_rate_hz = 16000; 1820 } else { 1821 clock_rate_khz = 256; 1822 sample_rate_hz = 8000; 1823 } 1824 uint8_t clock_direction = 0; // master 1825 uint16_t frame_sync_duty_cycle = 0; // i2s with 50% 1826 uint8_t frame_sync_edge = 1; // rising edge 1827 uint8_t frame_sync_polarity = 0; // active high 1828 uint8_t reserved = 0; 1829 uint16_t size = 16; 1830 uint16_t chan_1_offset = 1; 1831 uint16_t chan_2_offset = chan_1_offset + size; 1832 uint8_t out_edge = 1; // rising 1833 uint8_t in_edge = 0; // falling 1834 hci_send_cmd(&hci_ti_write_codec_config, clock_rate_khz, clock_direction, sample_rate_hz, frame_sync_duty_cycle, 1835 frame_sync_edge, frame_sync_polarity, reserved, 1836 size, chan_1_offset, out_edge, size, chan_1_offset, in_edge, reserved, 1837 size, chan_2_offset, out_edge, size, chan_2_offset, in_edge, reserved); 1838 } 1839 #endif 1840 1841 #ifdef ENABLE_BCM_PCM_WBS 1842 void hfp_bcm_prepare_for_sco(hfp_connection_t * hfp_connection){ 1843 hfp_connection->bcm_send_write_i2spcm_interface_param = true; 1844 if (hfp_connection->negotiated_codec == HFP_CODEC_MSBC){ 1845 hfp_connection->bcm_send_enable_wbs = true; 1846 } 1847 } 1848 void hfp_bcm_write_i2spcm_interface_param(hfp_connection_t * hfp_connection){ 1849 uint8_t sample_rate = (hfp_connection->negotiated_codec == HFP_CODEC_MSBC) ? 1 : 0; 1850 // i2s enable, master, 8/16 kHz, 512 kHz 1851 hci_send_cmd(&hci_bcm_write_i2spcm_interface_paramhci_bcm_write_i2spcm_interface_param, 1, 1, sample_rate, 2); 1852 } 1853 #endif 1854 1855 void hfp_set_hf_callback(btstack_packet_handler_t callback){ 1856 hfp_hf_callback = callback; 1857 } 1858 1859 void hfp_set_ag_callback(btstack_packet_handler_t callback){ 1860 hfp_ag_callback = callback; 1861 } 1862 1863 void hfp_set_ag_rfcomm_packet_handler(btstack_packet_handler_t handler){ 1864 hfp_ag_rfcomm_packet_handler = handler; 1865 } 1866 1867 void hfp_set_hf_rfcomm_packet_handler(btstack_packet_handler_t handler){ 1868 hfp_hf_rfcomm_packet_handler = handler; 1869 } 1870 1871 void hfp_init(void){ 1872 hfp_allowed_sco_packet_types = SCO_PACKET_TYPES_ALL; 1873 } 1874 1875 void hfp_deinit(void){ 1876 hfp_connections = NULL; 1877 hfp_hf_callback = NULL; 1878 hfp_ag_callback = NULL; 1879 hfp_hf_rfcomm_packet_handler = NULL; 1880 hfp_ag_rfcomm_packet_handler = NULL; 1881 sco_establishment_active = NULL; 1882 (void) memset(&sdp_query_context, 0, sizeof(hfp_sdp_query_context_t)); 1883 (void) memset(&hfp_handle_sdp_client_query_request, 0, sizeof(btstack_context_callback_registration_t)); 1884 } 1885 1886 void hfp_set_sco_packet_types(uint16_t packet_types){ 1887 hfp_allowed_sco_packet_types = packet_types; 1888 } 1889 1890 uint16_t hfp_get_sco_packet_types(void){ 1891 return hfp_allowed_sco_packet_types; 1892 } 1893 1894 hfp_link_settings_t hfp_next_link_setting(hfp_link_settings_t current_setting, bool local_eSCO_supported, bool remote_eSCO_supported, bool eSCO_S4_supported, uint8_t negotiated_codec){ 1895 int8_t setting = (int8_t) current_setting; 1896 bool can_use_eSCO = local_eSCO_supported && remote_eSCO_supported; 1897 while (setting > 0){ 1898 setting--; 1899 // skip if eSCO required but not available 1900 if (hfp_link_settings[setting].eSCO && !can_use_eSCO) continue; 1901 // skip if S4 but not supported 1902 if ((setting == (int8_t) HFP_LINK_SETTINGS_S4) && !eSCO_S4_supported) continue; 1903 // skip wrong codec 1904 if ( hfp_link_settings[setting].codec != negotiated_codec) continue; 1905 // skip disabled packet types 1906 uint16_t required_packet_types = hfp_link_settings[setting].packet_types; 1907 uint16_t allowed_packet_types = hfp_allowed_sco_packet_types; 1908 if ((required_packet_types & allowed_packet_types) == 0) continue; 1909 1910 // found matching setting 1911 return (hfp_link_settings_t) setting; 1912 } 1913 return HFP_LINK_SETTINGS_NONE; 1914 } 1915 1916 static hfp_link_settings_t hfp_next_link_setting_for_connection(hfp_link_settings_t current_setting, hfp_connection_t * hfp_connection, uint8_t eSCO_S4_supported){ 1917 bool local_eSCO_supported = hci_extended_sco_link_supported(); 1918 bool remote_eSCO_supported = hci_remote_esco_supported(hfp_connection->acl_handle); 1919 uint8_t negotiated_codec = hfp_connection->negotiated_codec; 1920 return hfp_next_link_setting(current_setting, local_eSCO_supported, remote_eSCO_supported, eSCO_S4_supported, negotiated_codec); 1921 } 1922 1923 void hfp_init_link_settings(hfp_connection_t * hfp_connection, uint8_t eSCO_S4_supported){ 1924 // get highest possible link setting 1925 hfp_connection->link_setting = hfp_next_link_setting_for_connection(HFP_LINK_SETTINGS_NONE, hfp_connection, eSCO_S4_supported); 1926 log_info("hfp_init_link_settings: %u", hfp_connection->link_setting); 1927 } 1928 1929 #define HFP_HF_RX_DEBUG_PRINT_LINE 80 1930 1931 void hfp_log_rfcomm_message(const char * tag, uint8_t * packet, uint16_t size){ 1932 #ifdef ENABLE_LOG_INFO 1933 // encode \n\r 1934 char printable[HFP_HF_RX_DEBUG_PRINT_LINE+2]; 1935 int i = 0; 1936 int pos; 1937 for (pos=0 ; (pos < size) && (i < (HFP_HF_RX_DEBUG_PRINT_LINE - 3)) ; pos++){ 1938 switch (packet[pos]){ 1939 case '\n': 1940 printable[i++] = '\\'; 1941 printable[i++] = 'n'; 1942 break; 1943 case '\r': 1944 printable[i++] = '\\'; 1945 printable[i++] = 'r'; 1946 break; 1947 default: 1948 printable[i++] = packet[pos]; 1949 break; 1950 } 1951 } 1952 printable[i] = 0; 1953 log_info("%s: '%s'", tag, printable); 1954 #endif 1955 } 1956