1/****************************************************************************** 2 * 3 * Copyright (C) 2000-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19/****************************************************************************** 20 * 21 * This file contains functions that handle SCO connections. This includes 22 * operations such as connect, disconnect, change supported packet types. 23 * 24 ******************************************************************************/ 25 26#include <string.h> 27#include "bt_common.h" 28#include "bt_target.h" 29#include "bt_types.h" 30#include "bt_utils.h" 31#include "btm_api.h" 32#include "btm_int.h" 33#include "btu.h" 34#include "device/include/controller.h" 35#include "device/include/esco_parameters.h" 36#include "hcidefs.h" 37#include "hcimsgs.h" 38#include "osi/include/osi.h" 39 40#if (BTM_SCO_INCLUDED == TRUE) 41 42/******************************************************************************/ 43/* L O C A L D A T A D E F I N I T I O N S */ 44/******************************************************************************/ 45 46#define SCO_ST_UNUSED 0 47#define SCO_ST_LISTENING 1 48#define SCO_ST_W4_CONN_RSP 2 49#define SCO_ST_CONNECTING 3 50#define SCO_ST_CONNECTED 4 51#define SCO_ST_DISCONNECTING 5 52#define SCO_ST_PEND_UNPARK 6 53#define SCO_ST_PEND_ROLECHANGE 7 54#define SCO_ST_PEND_MODECHANGE 8 55 56/******************************************************************************/ 57/* L O C A L F U N C T I O N P R O T O T Y P E S */ 58/******************************************************************************/ 59 60static uint16_t btm_sco_voice_settings_to_legacy(enh_esco_params_t* p_parms); 61 62/******************************************************************************* 63 * 64 * Function btm_sco_flush_sco_data 65 * 66 * Description This function is called to flush the SCO data for this 67 * channel. 68 * 69 * Returns void 70 * 71 ******************************************************************************/ 72#if (BTM_SCO_HCI_INCLUDED == TRUE && BTM_MAX_SCO_LINKS > 0) 73void btm_sco_flush_sco_data(uint16_t sco_inx) { 74 tSCO_CONN* p; 75 BT_HDR* p_buf; 76 77 if (sco_inx < BTM_MAX_SCO_LINKS) { 78 p = &btm_cb.sco_cb.sco_db[sco_inx]; 79 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p->xmit_data_q)) != NULL) 80 osi_free(p_buf); 81 } 82} 83} 84#else 85void btm_sco_flush_sco_data(UNUSED_ATTR uint16_t sco_inx) {} 86#endif 87/******************************************************************************* 88 * 89 * Function btm_sco_init 90 * 91 * Description This function is called at BTM startup to initialize 92 * 93 * Returns void 94 * 95 ******************************************************************************/ 96void btm_sco_init(void) { 97#if (BTM_SCO_HCI_INCLUDED == TRUE) 98 for (int i = 0; i < BTM_MAX_SCO_LINKS; i++) 99 btm_cb.sco_cb.sco_db[i].xmit_data_q = fixed_queue_new(SIZE_MAX); 100#endif 101 /* Initialize nonzero defaults */ 102 btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON; 103 btm_cb.sco_cb.def_esco_parms = esco_parameters_for_codec(ESCO_CODEC_CVSD); 104 btm_cb.sco_cb.def_esco_parms.max_latency_ms = 12; 105 btm_cb.sco_cb.sco_route = ESCO_DATA_PATH_PCM; 106} 107 108/******************************************************************************* 109 * 110 * Function btm_esco_conn_rsp 111 * 112 * Description This function is called upon receipt of an (e)SCO connection 113 * request event (BTM_ESCO_CONN_REQ_EVT) to accept or reject 114 * the request. Parameters used to negotiate eSCO links. 115 * If p_parms is NULL, then default values are used. 116 * If the link type of the incoming request is SCO, then only 117 * the tx_bw, max_latency, content format, and packet_types are 118 * valid. The hci_status parameter should be 119 * ([0x0] to accept, [0x0d..0x0f] to reject) 120 * 121 * Returns void 122 * 123 ******************************************************************************/ 124static void btm_esco_conn_rsp(uint16_t sco_inx, uint8_t hci_status, 125 const RawAddress& bda, 126 enh_esco_params_t* p_parms) { 127#if (BTM_MAX_SCO_LINKS > 0) 128 tSCO_CONN* p_sco = NULL; 129 130 if (sco_inx < BTM_MAX_SCO_LINKS) p_sco = &btm_cb.sco_cb.sco_db[sco_inx]; 131 132 /* Reject the connect request if refused by caller or wrong state */ 133 if (hci_status != HCI_SUCCESS || p_sco == NULL) { 134 if (p_sco) { 135 p_sco->state = (p_sco->state == SCO_ST_W4_CONN_RSP) ? SCO_ST_LISTENING 136 : SCO_ST_UNUSED; 137 } 138 if (!btm_cb.sco_cb.esco_supported) { 139 btsnd_hcic_reject_conn(bda, hci_status); 140 } else { 141 btsnd_hcic_reject_esco_conn(bda, hci_status); 142 } 143 } else { 144 /* Connection is being accepted */ 145 p_sco->state = SCO_ST_CONNECTING; 146 enh_esco_params_t* p_setup = &p_sco->esco.setup; 147 /* If parameters not specified use the default */ 148 if (p_parms) { 149 *p_setup = *p_parms; 150 } else { 151 /* Use the last setup passed thru BTM_SetEscoMode (or defaults) */ 152 *p_setup = btm_cb.sco_cb.def_esco_parms; 153 } 154 155 uint16_t temp_packet_types = 156 (p_setup->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK & 157 btm_cb.btm_sco_pkt_types_supported); 158 159 /* Make sure at least one eSCO packet type is sent, else might confuse peer 160 */ 161 /* Taking this out to confirm with BQB tests 162 ** Real application would like to include this though, as many devices 163 ** do not retry with SCO only if an eSCO connection fails. 164 if (!(temp_packet_types & BTM_ESCO_LINK_ONLY_MASK)) 165 { 166 temp_packet_types |= BTM_SCO_PKT_TYPES_MASK_EV3; 167 } 168 */ 169 /* If SCO request, remove eSCO packet types (conformance) */ 170 if (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO) { 171 temp_packet_types &= BTM_SCO_LINK_ONLY_MASK; 172 temp_packet_types |= BTM_SCO_EXCEPTION_PKTS_MASK; 173 } else { 174 /* OR in any exception packet types */ 175 temp_packet_types |= 176 ((p_setup->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) | 177 (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK)); 178 } 179 180 /* Use Enhanced Synchronous commands if supported */ 181 if (controller_get_interface() 182 ->supports_enhanced_setup_synchronous_connection()) { 183 /* Use the saved SCO routing */ 184 p_setup->input_data_path = p_setup->output_data_path = 185 btm_cb.sco_cb.sco_route; 186 187 BTM_TRACE_DEBUG( 188 "%s: txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, " 189 "pkt 0x%04x, path %u", 190 __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth, 191 p_setup->max_latency_ms, p_setup->retransmission_effort, 192 p_setup->packet_types, p_setup->input_data_path); 193 194 btsnd_hcic_enhanced_accept_synchronous_connection(bda, p_setup); 195 196 } else { 197 /* Use legacy command if enhanced SCO setup is not supported */ 198 uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup); 199 btsnd_hcic_accept_esco_conn( 200 bda, p_setup->transmit_bandwidth, p_setup->receive_bandwidth, 201 p_setup->max_latency_ms, voice_content_format, 202 p_setup->retransmission_effort, p_setup->packet_types); 203 } 204 } 205#endif 206} 207 208#if (BTM_SCO_HCI_INCLUDED == TRUE) 209/******************************************************************************* 210 * 211 * Function btm_sco_check_send_pkts 212 * 213 * Description This function is called to check if it can send packets 214 * to the Host Controller. 215 * 216 * Returns void 217 * 218 ******************************************************************************/ 219void btm_sco_check_send_pkts(uint16_t sco_inx) { 220 tSCO_CB* p_cb = &btm_cb.sco_cb; 221 tSCO_CONN* p_ccb = &p_cb->sco_db[sco_inx]; 222 223 /* If there is data to send, send it now */ 224 BT_HDR* p_buf; 225 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_data_q)) != 226 NULL) { 227#if (BTM_SCO_HCI_DEBUG == TRUE) 228 BTM_TRACE_DEBUG("btm: [%d] buf in xmit_data_q", 229 fixed_queue_length(p_ccb->xmit_data_q) + 1); 230#endif 231 232 HCI_SCO_DATA_TO_LOWER(p_buf); 233 } 234} 235#endif /* BTM_SCO_HCI_INCLUDED == TRUE */ 236 237/******************************************************************************* 238 * 239 * Function btm_route_sco_data 240 * 241 * Description Route received SCO data. 242 * 243 * Returns void 244 * 245 ******************************************************************************/ 246void btm_route_sco_data(BT_HDR* p_msg) { 247#if (BTM_SCO_HCI_INCLUDED == TRUE) 248 uint16_t sco_inx, handle; 249 uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset; 250 uint8_t pkt_size = 0; 251 uint8_t pkt_status = 0; 252 253 /* Extract Packet_Status_Flag and handle */ 254 STREAM_TO_UINT16(handle, p); 255 pkt_status = HCID_GET_EVENT(handle); 256 handle = HCID_GET_HANDLE(handle); 257 258 STREAM_TO_UINT8(pkt_size, p); 259 260 sco_inx = btm_find_scb_by_handle(handle); 261 if (sco_inx != BTM_MAX_SCO_LINKS) { 262 /* send data callback */ 263 if (!btm_cb.sco_cb.p_data_cb) 264 /* if no data callback registered, just free the buffer */ 265 osi_free(p_msg); 266 else { 267 (*btm_cb.sco_cb.p_data_cb)(sco_inx, p_msg, 268 (tBTM_SCO_DATA_FLAG)pkt_status); 269 } 270 } else /* no mapping handle SCO connection is active, free the buffer */ 271 { 272 osi_free(p_msg); 273 } 274#else 275 osi_free(p_msg); 276#endif 277} 278 279/******************************************************************************* 280 * 281 * Function BTM_WriteScoData 282 * 283 * Description This function write SCO data to a specified instance. The 284 * data to be written p_buf needs to carry an offset of 285 * HCI_SCO_PREAMBLE_SIZE bytes, and the data length can not 286 * exceed BTM_SCO_DATA_SIZE_MAX bytes, whose default value is 287 * set to 60 and is configurable. Data longer than the maximum 288 * bytes will be truncated. 289 * 290 * Returns BTM_SUCCESS: data write is successful 291 * BTM_ILLEGAL_VALUE: SCO data contains illegal offset value. 292 * BTM_SCO_BAD_LENGTH: SCO data length exceeds the max SCO 293 * packet size. 294 * BTM_NO_RESOURCES: no resources. 295 * BTM_UNKNOWN_ADDR: unknown SCO connection handle, or SCO is 296 * not routed via HCI. 297 * 298 * 299 ******************************************************************************/ 300#if (BTM_SCO_HCI_INCLUDED == TRUE && BTM_MAX_SCO_LINKS > 0) 301tBTM_STATUS BTM_WriteScoData(uint16_t sco_inx, BT_HDR* p_buf) { 302 tSCO_CONN* p_ccb = &btm_cb.sco_cb.sco_db[sco_inx]; 303 uint8_t* p; 304 tBTM_STATUS status = BTM_SUCCESS; 305 306 if (sco_inx < BTM_MAX_SCO_LINKS && btm_cb.sco_cb.p_data_cb && 307 p_ccb->state == SCO_ST_CONNECTED) { 308 /* Ensure we have enough space in the buffer for the SCO and HCI headers */ 309 if (p_buf->offset < HCI_SCO_PREAMBLE_SIZE) { 310 BTM_TRACE_ERROR("BTM SCO - cannot send buffer, offset: %d", 311 p_buf->offset); 312 osi_free(p_buf); 313 status = BTM_ILLEGAL_VALUE; 314 } else /* write HCI header */ 315 { 316 /* Step back 3 bytes to add the headers */ 317 p_buf->offset -= HCI_SCO_PREAMBLE_SIZE; 318 /* Set the pointer to the beginning of the data */ 319 p = (uint8_t*)(p_buf + 1) + p_buf->offset; 320 /* add HCI handle */ 321 UINT16_TO_STREAM(p, p_ccb->hci_handle); 322 /* only sent the first BTM_SCO_DATA_SIZE_MAX bytes data if more than max, 323 and set warning status */ 324 if (p_buf->len > BTM_SCO_DATA_SIZE_MAX) { 325 p_buf->len = BTM_SCO_DATA_SIZE_MAX; 326 status = BTM_SCO_BAD_LENGTH; 327 } 328 329 UINT8_TO_STREAM(p, (uint8_t)p_buf->len); 330 p_buf->len += HCI_SCO_PREAMBLE_SIZE; 331 332 fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf); 333 334 btm_sco_check_send_pkts(sco_inx); 335 } 336 } else { 337 osi_free(p_buf); 338 339 BTM_TRACE_ERROR("%s:invalid sco index: %d at state [%d]", __func__, sco_inx, 340 btm_cb.sco_cb.sco_db[sco_inx].state); 341 status = BTM_UNKNOWN_ADDR; 342 } 343 344 return status; 345} 346#else 347tBTM_STATUS BTM_WriteScoData(UNUSED_ATTR uint16_t sco_inx, 348 UNUSED_ATTR BT_HDR* p_buf) { 349 return (BTM_NO_RESOURCES); 350} 351#endif 352 353#if (BTM_MAX_SCO_LINKS > 0) 354/******************************************************************************* 355 * 356 * Function btm_send_connect_request 357 * 358 * Description This function is called to respond to SCO connect 359 * indications 360 * 361 * Returns void 362 * 363 ******************************************************************************/ 364static tBTM_STATUS btm_send_connect_request(uint16_t acl_handle, 365 enh_esco_params_t* p_setup) { 366 tACL_CONN* p_acl; 367 368 /* Send connect request depending on version of spec */ 369 if (!btm_cb.sco_cb.esco_supported) { 370 btsnd_hcic_add_SCO_conn(acl_handle, BTM_ESCO_2_SCO(p_setup->packet_types)); 371 } else { 372 uint16_t temp_packet_types = 373 (p_setup->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK & 374 btm_cb.btm_sco_pkt_types_supported); 375 376 /* OR in any exception packet types */ 377 temp_packet_types |= 378 ((p_setup->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) | 379 (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK)); 380 381 /* Finally, remove EDR eSCO if the remote device doesn't support it */ 382 /* UPF25: Only SCO was brought up in this case */ 383 btm_handle_to_acl_index(acl_handle); 384 uint8_t acl_index = btm_handle_to_acl_index(acl_handle); 385 if (acl_index < MAX_L2CAP_LINKS) { 386 p_acl = &btm_cb.acl_db[acl_index]; 387 if (!HCI_EDR_ESCO_2MPS_SUPPORTED(p_acl->peer_lmp_feature_pages[0])) { 388 BTM_TRACE_WARNING("BTM Remote does not support 2-EDR eSCO"); 389 temp_packet_types |= 390 (ESCO_PKT_TYPES_MASK_NO_2_EV3 | ESCO_PKT_TYPES_MASK_NO_2_EV5); 391 } 392 if (!HCI_EDR_ESCO_3MPS_SUPPORTED(p_acl->peer_lmp_feature_pages[0])) { 393 BTM_TRACE_WARNING("BTM Remote does not support 3-EDR eSCO"); 394 temp_packet_types |= 395 (ESCO_PKT_TYPES_MASK_NO_3_EV3 | ESCO_PKT_TYPES_MASK_NO_3_EV5); 396 } 397 398 /* Check to see if BR/EDR Secure Connections is being used 399 ** If so, we cannot use SCO-only packet types (HFP 1.7) 400 */ 401 if (BTM_BothEndsSupportSecureConnections(p_acl->remote_addr)) { 402 temp_packet_types &= ~(BTM_SCO_PKT_TYPE_MASK); 403 BTM_TRACE_DEBUG("%s: SCO Conn: pkt_types after removing SCO (0x%04x)", 404 __func__, temp_packet_types); 405 406 /* Return error if no packet types left */ 407 if (temp_packet_types == 0) { 408 BTM_TRACE_ERROR("%s: SCO Conn (BR/EDR SC): No packet types available", 409 __func__); 410 return (BTM_WRONG_MODE); 411 } 412 } else { 413 BTM_TRACE_DEBUG( 414 "%s: SCO Conn(BR/EDR SC):local or peer does not support BR/EDR SC", 415 __func__); 416 } 417 } 418 419 /* Save the previous types in case command fails */ 420 uint16_t saved_packet_types = p_setup->packet_types; 421 p_setup->packet_types = temp_packet_types; 422 423 /* Use Enhanced Synchronous commands if supported */ 424 if (controller_get_interface() 425 ->supports_enhanced_setup_synchronous_connection()) { 426 /* Use the saved SCO routing */ 427 p_setup->input_data_path = p_setup->output_data_path = 428 btm_cb.sco_cb.sco_route; 429 430 BTM_TRACE_DEBUG( 431 "%s: txbw 0x%x, rxbw 0x%x, " 432 "lat 0x%x, retrans 0x%02x, pkt 0x%04x, path %u", 433 __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth, 434 p_setup->max_latency_ms, p_setup->retransmission_effort, 435 p_setup->packet_types, p_setup->input_data_path); 436 437 btsnd_hcic_enhanced_set_up_synchronous_connection(acl_handle, p_setup); 438 p_setup->packet_types = saved_packet_types; 439 } else { /* Use older command */ 440 uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup); 441 442 BTM_TRACE_API( 443 "%s: txbw 0x%x, rxbw 0x%x, " 444 "lat 0x%x, voice 0x%x, retrans 0x%02x, pkt 0x%04x", 445 __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth, 446 p_setup->max_latency_ms, voice_content_format, 447 p_setup->retransmission_effort, p_setup->packet_types); 448 449 btsnd_hcic_setup_esco_conn( 450 acl_handle, p_setup->transmit_bandwidth, p_setup->receive_bandwidth, 451 p_setup->max_latency_ms, voice_content_format, 452 p_setup->retransmission_effort, p_setup->packet_types); 453 } 454 } 455 456 return (BTM_CMD_STARTED); 457} 458#endif 459 460/******************************************************************************* 461 * 462 * Function btm_set_sco_ind_cback 463 * 464 * Description This function is called to register for TCS SCO connect 465 * indications. 466 * 467 * Returns void 468 * 469 ******************************************************************************/ 470void btm_set_sco_ind_cback(tBTM_SCO_IND_CBACK* sco_ind_cb) { 471 btm_cb.sco_cb.app_sco_ind_cb = sco_ind_cb; 472} 473 474/******************************************************************************* 475 * 476 * Function btm_accept_sco_link 477 * 478 * Description This function is called to respond to TCS SCO connect 479 * indications 480 * 481 * Returns void 482 * 483 ******************************************************************************/ 484void btm_accept_sco_link(uint16_t sco_inx, enh_esco_params_t* p_setup, 485 tBTM_SCO_CB* p_conn_cb, tBTM_SCO_CB* p_disc_cb) { 486#if (BTM_MAX_SCO_LINKS > 0) 487 tSCO_CONN* p_sco; 488 489 if (sco_inx >= BTM_MAX_SCO_LINKS) { 490 BTM_TRACE_ERROR("btm_accept_sco_link: Invalid sco_inx(%d)", sco_inx); 491 return; 492 } 493 494 /* Link role is ignored in for this message */ 495 p_sco = &btm_cb.sco_cb.sco_db[sco_inx]; 496 p_sco->p_conn_cb = p_conn_cb; 497 p_sco->p_disc_cb = p_disc_cb; 498 p_sco->esco.data.link_type = 499 BTM_LINK_TYPE_ESCO; /* Accept with all supported types */ 500 501 BTM_TRACE_DEBUG("TCS accept SCO: Packet Types 0x%04x", p_setup->packet_types); 502 503 btm_esco_conn_rsp(sco_inx, HCI_SUCCESS, p_sco->esco.data.bd_addr, p_setup); 504#else 505 btm_reject_sco_link(sco_inx); 506#endif 507} 508 509/******************************************************************************* 510 * 511 * Function btm_reject_sco_link 512 * 513 * Description This function is called to respond to SCO connect 514 * indications 515 * 516 * Returns void 517 * 518 ******************************************************************************/ 519void btm_reject_sco_link(uint16_t sco_inx) { 520 btm_esco_conn_rsp(sco_inx, HCI_ERR_HOST_REJECT_RESOURCES, 521 btm_cb.sco_cb.sco_db[sco_inx].esco.data.bd_addr, NULL); 522} 523 524/******************************************************************************* 525 * 526 * Function BTM_CreateSco 527 * 528 * Description This function is called to create an SCO connection. If the 529 * "is_orig" flag is true, the connection will be originated, 530 * otherwise BTM will wait for the other side to connect. 531 * 532 * NOTE: If BTM_IGNORE_SCO_PKT_TYPE is passed in the pkt_types 533 * parameter the default packet types is used. 534 * 535 * Returns BTM_UNKNOWN_ADDR if the ACL connection is not up 536 * BTM_BUSY if another SCO being set up to 537 * the same BD address 538 * BTM_NO_RESOURCES if the max SCO limit has been reached 539 * BTM_CMD_STARTED if the connection establishment is started. 540 * In this case, "*p_sco_inx" is filled in 541 * with the sco index used for the connection. 542 * 543 ******************************************************************************/ 544tBTM_STATUS BTM_CreateSco(const RawAddress* remote_bda, bool is_orig, 545 uint16_t pkt_types, uint16_t* p_sco_inx, 546 tBTM_SCO_CB* p_conn_cb, tBTM_SCO_CB* p_disc_cb) { 547#if (BTM_MAX_SCO_LINKS > 0) 548 enh_esco_params_t* p_setup; 549 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 550 uint16_t xx; 551 uint16_t acl_handle = 0; 552 tACL_CONN* p_acl; 553 554#if (BTM_SCO_WAKE_PARKED_LINK == TRUE) 555 tBTM_PM_PWR_MD pm; 556 tBTM_PM_STATE state; 557#else 558 uint8_t mode; 559#endif // BTM_SCO_WAKE_PARKED_LINK 560 561 *p_sco_inx = BTM_INVALID_SCO_INDEX; 562 563 /* If originating, ensure that there is an ACL connection to the BD Address */ 564 565 if (is_orig) { 566 if (!remote_bda) { 567 BTM_TRACE_ERROR("%s: remote_bda is null", __func__); 568 return BTM_ILLEGAL_VALUE; 569 } 570 acl_handle = BTM_GetHCIConnHandle(*remote_bda, BT_TRANSPORT_BR_EDR); 571 if (acl_handle == 0xFFFF) { 572 VLOG(2) << __func__ << ": cannot find ACL handle for remote device " 573 << remote_bda; 574 return BTM_UNKNOWN_ADDR; 575 } 576 } 577 578 if (remote_bda) { 579 /* If any SCO is being established to the remote BD address, refuse this */ 580 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 581 if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) || 582 (p->state == SCO_ST_PEND_UNPARK)) && 583 (p->esco.data.bd_addr == *remote_bda)) { 584 return BTM_BUSY; 585 } 586 } 587 } else { 588 /* Support only 1 wildcard BD address at a time */ 589 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 590 if ((p->state == SCO_ST_LISTENING) && (!p->rem_bd_known)) return BTM_BUSY; 591 } 592 } 593 594 /* Try to find an unused control block, and kick off the SCO establishment */ 595 for (xx = 0, p = &btm_cb.sco_cb.sco_db[0]; xx < BTM_MAX_SCO_LINKS; 596 xx++, p++) { 597 if (p->state == SCO_ST_UNUSED) { 598 if (remote_bda) { 599 if (is_orig) { 600/* can not create SCO link if in park mode */ 601#if (BTM_SCO_WAKE_PARKED_LINK == TRUE) 602 if ((btm_read_power_mode_state(p->esco.data.bd_addr, &state) == 603 BTM_SUCCESS)) { 604 if (state == BTM_PM_ST_SNIFF || state == BTM_PM_ST_PARK || 605 state == BTM_PM_ST_PENDING) { 606 BTM_TRACE_DEBUG("%s In sniff, park or pend mode: %d", __func__, 607 state); 608 memset((void*)&pm, 0, sizeof(pm)); 609 pm.mode = BTM_PM_MD_ACTIVE; 610 BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, *remote_bda, &pm); 611 p->state = SCO_ST_PEND_UNPARK; 612 } 613 } 614#else // BTM_SCO_WAKE_PARKED_LINK 615 if ((BTM_ReadPowerMode(*remote_bda, &mode) == BTM_SUCCESS) && 616 (mode == BTM_PM_MD_PARK)) 617 return (BTM_WRONG_MODE); 618#endif // BTM_SCO_WAKE_PARKED_LINK 619 } 620 p->esco.data.bd_addr = *remote_bda; 621 p->rem_bd_known = true; 622 } else 623 p->rem_bd_known = false; 624 625 p_setup = &p->esco.setup; 626 *p_setup = btm_cb.sco_cb.def_esco_parms; 627 628 /* Determine the packet types */ 629 p_setup->packet_types = pkt_types & BTM_SCO_SUPPORTED_PKTS_MASK & 630 btm_cb.btm_sco_pkt_types_supported; 631 /* OR in any exception packet types */ 632 if (controller_get_interface()->get_bt_version()->hci_version >= 633 HCI_PROTO_VERSION_2_0) { 634 p_setup->packet_types |= 635 (pkt_types & BTM_SCO_EXCEPTION_PKTS_MASK) | 636 (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK); 637 } 638 639 p->p_conn_cb = p_conn_cb; 640 p->p_disc_cb = p_disc_cb; 641 p->hci_handle = BTM_INVALID_HCI_HANDLE; 642 p->is_orig = is_orig; 643 644 if (p->state != SCO_ST_PEND_UNPARK) { 645 if (is_orig) { 646 /* If role change is in progress, do not proceed with SCO setup 647 * Wait till role change is complete */ 648 p_acl = btm_bda_to_acl(*remote_bda, BT_TRANSPORT_BR_EDR); 649 if (p_acl && p_acl->switch_role_state != BTM_ACL_SWKEY_STATE_IDLE) { 650 BTM_TRACE_API("Role Change is in progress for ACL handle 0x%04x", 651 acl_handle); 652 p->state = SCO_ST_PEND_ROLECHANGE; 653 } 654 } 655 } 656 657 if (p->state != SCO_ST_PEND_UNPARK && 658 p->state != SCO_ST_PEND_ROLECHANGE) { 659 if (is_orig) { 660 BTM_TRACE_API("%s:(e)SCO Link for ACL handle 0x%04x", __func__, 661 acl_handle); 662 663 if ((btm_send_connect_request(acl_handle, p_setup)) != 664 BTM_CMD_STARTED) 665 return (BTM_NO_RESOURCES); 666 667 p->state = SCO_ST_CONNECTING; 668 } else 669 p->state = SCO_ST_LISTENING; 670 } 671 672 *p_sco_inx = xx; 673 674 return BTM_CMD_STARTED; 675 } 676 } 677 678#endif 679 /* If here, all SCO blocks in use */ 680 return BTM_NO_RESOURCES; 681} 682 683#if (BTM_SCO_WAKE_PARKED_LINK == TRUE) 684/******************************************************************************* 685 * 686 * Function btm_sco_chk_pend_unpark 687 * 688 * Description This function is called by BTIF when there is a mode change 689 * event to see if there are SCO commands waiting for the 690 * unpark. 691 * 692 * Returns void 693 * 694 ******************************************************************************/ 695void btm_sco_chk_pend_unpark(uint8_t hci_status, uint16_t hci_handle) { 696#if (BTM_MAX_SCO_LINKS > 0) 697 uint16_t xx; 698 uint16_t acl_handle; 699 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 700 701 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 702 if ((p->state == SCO_ST_PEND_UNPARK) && 703 ((acl_handle = BTM_GetHCIConnHandle( 704 p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle)) 705 706 { 707 BTM_TRACE_API( 708 "%s:(e)SCO Link for ACL " 709 "handle 0x%04x, hci_status 0x%02x", 710 __func__, acl_handle, hci_status); 711 712 if ((btm_send_connect_request(acl_handle, &p->esco.setup)) == 713 BTM_CMD_STARTED) 714 p->state = SCO_ST_CONNECTING; 715 } 716 } 717#endif // BTM_MAX_SCO_LINKS 718} 719#endif // BTM_SCO_WAKE_PARKED_LINK 720 721/******************************************************************************* 722 * 723 * Function btm_sco_chk_pend_rolechange 724 * 725 * Description This function is called by BTIF when there is a role change 726 * event to see if there are SCO commands waiting for the role 727 * change. 728 * 729 * Returns void 730 * 731 ******************************************************************************/ 732void btm_sco_chk_pend_rolechange(uint16_t hci_handle) { 733#if (BTM_MAX_SCO_LINKS > 0) 734 uint16_t xx; 735 uint16_t acl_handle; 736 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 737 738 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 739 if ((p->state == SCO_ST_PEND_ROLECHANGE) && 740 ((acl_handle = BTM_GetHCIConnHandle( 741 p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle)) 742 743 { 744 BTM_TRACE_API( 745 "btm_sco_chk_pend_rolechange -> (e)SCO Link for ACL handle 0x%04x", 746 acl_handle); 747 748 if ((btm_send_connect_request(acl_handle, &p->esco.setup)) == 749 BTM_CMD_STARTED) 750 p->state = SCO_ST_CONNECTING; 751 } 752 } 753#endif 754} 755 756/******************************************************************************* 757 * 758 * Function btm_sco_disc_chk_pend_for_modechange 759 * 760 * Description This function is called by btm when there is a mode change 761 * event to see if there are SCO disconnect commands waiting 762 * for the mode change. 763 * 764 * Returns void 765 * 766 ******************************************************************************/ 767void btm_sco_disc_chk_pend_for_modechange(uint16_t hci_handle) { 768#if (BTM_MAX_SCO_LINKS > 0) 769 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 770 771 BTM_TRACE_DEBUG("%s: hci_handle 0x%04x, p->state 0x%02x", __func__, 772 hci_handle, p->state); 773 774 for (uint16_t xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 775 if ((p->state == SCO_ST_PEND_MODECHANGE) && 776 (BTM_GetHCIConnHandle(p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == 777 hci_handle) 778 779 { 780 BTM_TRACE_DEBUG("%s: SCO Link handle 0x%04x", __func__, p->hci_handle); 781 BTM_RemoveSco(xx); 782 } 783 } 784#endif 785} 786 787/******************************************************************************* 788 * 789 * Function btm_sco_conn_req 790 * 791 * Description This function is called by BTIF when an SCO connection 792 * request is received from a remote. 793 * 794 * Returns void 795 * 796 ******************************************************************************/ 797void btm_sco_conn_req(const RawAddress& bda, DEV_CLASS dev_class, 798 uint8_t link_type) { 799#if (BTM_MAX_SCO_LINKS > 0) 800 tSCO_CB* p_sco = &btm_cb.sco_cb; 801 tSCO_CONN* p = &p_sco->sco_db[0]; 802 uint16_t xx; 803 tBTM_ESCO_CONN_REQ_EVT_DATA evt_data; 804 805 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 806 /* 807 * If the sco state is in the SCO_ST_CONNECTING state, we still need 808 * to return accept sco to avoid race conditon for sco creation 809 */ 810 int rem_bd_matches = p->rem_bd_known && p->esco.data.bd_addr == bda; 811 if (((p->state == SCO_ST_CONNECTING) && rem_bd_matches) || 812 ((p->state == SCO_ST_LISTENING) && 813 (rem_bd_matches || !p->rem_bd_known))) { 814 /* If this guy was a wildcard, he is not one any more */ 815 p->rem_bd_known = true; 816 p->esco.data.link_type = link_type; 817 p->state = SCO_ST_W4_CONN_RSP; 818 p->esco.data.bd_addr = bda; 819 820 /* If no callback, auto-accept the connection if packet types match */ 821 if (!p->esco.p_esco_cback) { 822 /* If requesting eSCO reject if default parameters are SCO only */ 823 if ((link_type == BTM_LINK_TYPE_ESCO && 824 !(p_sco->def_esco_parms.packet_types & BTM_ESCO_LINK_ONLY_MASK) && 825 ((p_sco->def_esco_parms.packet_types & 826 BTM_SCO_EXCEPTION_PKTS_MASK) == BTM_SCO_EXCEPTION_PKTS_MASK)) 827 828 /* Reject request if SCO is desired but no SCO packets delected */ 829 || 830 (link_type == BTM_LINK_TYPE_SCO && 831 !(p_sco->def_esco_parms.packet_types & BTM_SCO_LINK_ONLY_MASK))) { 832 btm_esco_conn_rsp(xx, HCI_ERR_HOST_REJECT_RESOURCES, bda, NULL); 833 } else /* Accept the request */ 834 { 835 btm_esco_conn_rsp(xx, HCI_SUCCESS, bda, NULL); 836 } 837 } else /* Notify upper layer of connect indication */ 838 { 839 evt_data.bd_addr = bda; 840 memcpy(evt_data.dev_class, dev_class, DEV_CLASS_LEN); 841 evt_data.link_type = link_type; 842 evt_data.sco_inx = xx; 843 tBTM_ESCO_EVT_DATA btm_esco_evt_data; 844 btm_esco_evt_data.conn_evt = evt_data; 845 p->esco.p_esco_cback(BTM_ESCO_CONN_REQ_EVT, &btm_esco_evt_data); 846 } 847 848 return; 849 } 850 } 851 852 /* TCS usage */ 853 if (btm_cb.sco_cb.app_sco_ind_cb) { 854 /* Now, try to find an unused control block */ 855 for (xx = 0, p = &btm_cb.sco_cb.sco_db[0]; xx < BTM_MAX_SCO_LINKS; 856 xx++, p++) { 857 if (p->state == SCO_ST_UNUSED) { 858 p->is_orig = false; 859 p->state = SCO_ST_LISTENING; 860 861 p->esco.data.link_type = link_type; 862 p->esco.data.bd_addr = bda; 863 p->rem_bd_known = true; 864 break; 865 } 866 } 867 if (xx < BTM_MAX_SCO_LINKS) { 868 btm_cb.sco_cb.app_sco_ind_cb(xx); 869 return; 870 } 871 } 872 873#endif 874 /* If here, no one wants the SCO connection. Reject it */ 875 BTM_TRACE_WARNING( 876 "btm_sco_conn_req: No one wants this SCO connection; rejecting it"); 877 btm_esco_conn_rsp(BTM_MAX_SCO_LINKS, HCI_ERR_HOST_REJECT_RESOURCES, bda, 878 NULL); 879} 880 881/******************************************************************************* 882 * 883 * Function btm_sco_connected 884 * 885 * Description This function is called by BTIF when an (e)SCO connection 886 * is connected. 887 * 888 * Returns void 889 * 890 ******************************************************************************/ 891void btm_sco_connected(uint8_t hci_status, const RawAddress* bda, 892 uint16_t hci_handle, tBTM_ESCO_DATA* p_esco_data) { 893#if (BTM_MAX_SCO_LINKS > 0) 894 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 895 uint16_t xx; 896 bool spt = false; 897 tBTM_CHG_ESCO_PARAMS parms; 898#endif 899 900 btm_cb.sco_cb.sco_disc_reason = hci_status; 901 902#if (BTM_MAX_SCO_LINKS > 0) 903 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 904 if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) || 905 (p->state == SCO_ST_W4_CONN_RSP)) && 906 (p->rem_bd_known) && (!bda || p->esco.data.bd_addr == *bda)) { 907 if (hci_status != HCI_SUCCESS) { 908 /* Report the error if originator, otherwise remain in Listen mode */ 909 if (p->is_orig) { 910 /* If role switch is pending, we need try again after role switch is 911 * complete */ 912 if (hci_status == HCI_ERR_ROLE_SWITCH_PENDING) { 913 BTM_TRACE_API("Role Change pending for HCI handle 0x%04x", 914 hci_handle); 915 p->state = SCO_ST_PEND_ROLECHANGE; 916 } 917 /* avoid calling disconnect callback because of sco creation race */ 918 else if (hci_status != HCI_ERR_LMP_ERR_TRANS_COLLISION) { 919 p->state = SCO_ST_UNUSED; 920 (*p->p_disc_cb)(xx); 921 } 922 } else { 923 /* Notify the upper layer that incoming sco connection has failed. */ 924 if (p->state == SCO_ST_CONNECTING) { 925 p->state = SCO_ST_UNUSED; 926 (*p->p_disc_cb)(xx); 927 } else 928 p->state = SCO_ST_LISTENING; 929 } 930 931 return; 932 } 933 934 if (p->state == SCO_ST_LISTENING) spt = true; 935 936 p->state = SCO_ST_CONNECTED; 937 p->hci_handle = hci_handle; 938 939 if (!btm_cb.sco_cb.esco_supported) { 940 p->esco.data.link_type = BTM_LINK_TYPE_SCO; 941 if (spt) { 942 parms.packet_types = p->esco.setup.packet_types; 943 /* Keep the other parameters the same for SCO */ 944 parms.max_latency_ms = p->esco.setup.max_latency_ms; 945 parms.retransmission_effort = p->esco.setup.retransmission_effort; 946 947 BTM_ChangeEScoLinkParms(xx, &parms); 948 } 949 } else { 950 if (p_esco_data) p->esco.data = *p_esco_data; 951 } 952 953 (*p->p_conn_cb)(xx); 954 955 return; 956 } 957 } 958#endif 959} 960 961/******************************************************************************* 962 * 963 * Function btm_find_scb_by_handle 964 * 965 * Description Look through all active SCO connection for a match based on 966 * the HCI handle. 967 * 968 * Returns index to matched SCO connection CB, or BTM_MAX_SCO_LINKS if 969 * no match. 970 * 971 ******************************************************************************/ 972uint16_t btm_find_scb_by_handle(uint16_t handle) { 973 int xx; 974 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 975 976 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 977 if ((p->state == SCO_ST_CONNECTED) && (p->hci_handle == handle)) { 978 return (xx); 979 } 980 } 981 982 /* If here, no match found */ 983 return (xx); 984} 985 986/******************************************************************************* 987 * 988 * Function BTM_RemoveSco 989 * 990 * Description This function is called to remove a specific SCO connection. 991 * 992 * Returns status of the operation 993 * 994 ******************************************************************************/ 995tBTM_STATUS BTM_RemoveSco(uint16_t sco_inx) { 996#if (BTM_MAX_SCO_LINKS > 0) 997 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx]; 998 uint16_t tempstate; 999 tBTM_PM_STATE state = BTM_PM_ST_INVALID; 1000 1001 BTM_TRACE_DEBUG("%s", __func__); 1002 1003 /* Validity check */ 1004 if ((sco_inx >= BTM_MAX_SCO_LINKS) || (p->state == SCO_ST_UNUSED)) 1005 return (BTM_UNKNOWN_ADDR); 1006 1007 /* If no HCI handle, simply drop the connection and return */ 1008 if (p->hci_handle == BTM_INVALID_HCI_HANDLE || 1009 p->state == SCO_ST_PEND_UNPARK) { 1010 p->hci_handle = BTM_INVALID_HCI_HANDLE; 1011 p->state = SCO_ST_UNUSED; 1012 p->esco.p_esco_cback = NULL; /* Deregister the eSCO event callback */ 1013 return (BTM_SUCCESS); 1014 } 1015 1016 if ((btm_read_power_mode_state(p->esco.data.bd_addr, &state) == 1017 BTM_SUCCESS) && 1018 state == BTM_PM_ST_PENDING) { 1019 BTM_TRACE_DEBUG("%s: BTM_PM_ST_PENDING for ACL mapped with SCO Link 0x%04x", 1020 __func__, p->hci_handle); 1021 p->state = SCO_ST_PEND_MODECHANGE; 1022 return (BTM_CMD_STARTED); 1023 } 1024 1025 tempstate = p->state; 1026 p->state = SCO_ST_DISCONNECTING; 1027 1028 btsnd_hcic_disconnect(p->hci_handle, HCI_ERR_PEER_USER); 1029 1030 return (BTM_CMD_STARTED); 1031#else 1032 return (BTM_NO_RESOURCES); 1033#endif 1034} 1035 1036/******************************************************************************* 1037 * 1038 * Function btm_remove_sco_links 1039 * 1040 * Description This function is called to remove all sco links for an ACL 1041 * link. 1042 * 1043 * Returns void 1044 * 1045 ******************************************************************************/ 1046void btm_remove_sco_links(const RawAddress& bda) { 1047#if (BTM_MAX_SCO_LINKS > 0) 1048 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 1049 uint16_t xx; 1050 1051 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 1052 if (p->rem_bd_known && p->esco.data.bd_addr == bda) { 1053 BTM_RemoveSco(xx); 1054 } 1055 } 1056#endif 1057} 1058 1059/******************************************************************************* 1060 * 1061 * Function btm_sco_removed 1062 * 1063 * Description This function is called by BTIF when an SCO connection 1064 * is removed. 1065 * 1066 * Returns void 1067 * 1068 ******************************************************************************/ 1069void btm_sco_removed(uint16_t hci_handle, uint8_t reason) { 1070#if (BTM_MAX_SCO_LINKS > 0) 1071 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 1072 uint16_t xx; 1073#endif 1074 1075 btm_cb.sco_cb.sco_disc_reason = reason; 1076 1077#if (BTM_MAX_SCO_LINKS > 0) 1078 p = &btm_cb.sco_cb.sco_db[0]; 1079 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 1080 if ((p->state != SCO_ST_UNUSED) && (p->state != SCO_ST_LISTENING) && 1081 (p->hci_handle == hci_handle)) { 1082 btm_sco_flush_sco_data(xx); 1083 1084 p->state = SCO_ST_UNUSED; 1085 p->hci_handle = BTM_INVALID_HCI_HANDLE; 1086 p->rem_bd_known = false; 1087 p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */ 1088 (*p->p_disc_cb)(xx); 1089 1090 return; 1091 } 1092 } 1093#endif 1094} 1095 1096/******************************************************************************* 1097 * 1098 * Function btm_sco_acl_removed 1099 * 1100 * Description This function is called when an ACL connection is 1101 * removed. If the BD address is NULL, it is assumed that 1102 * the local device is down, and all SCO links are removed. 1103 * If a specific BD address is passed, only SCO connections 1104 * to that BD address are removed. 1105 * 1106 * Returns void 1107 * 1108 ******************************************************************************/ 1109void btm_sco_acl_removed(const RawAddress* bda) { 1110#if (BTM_MAX_SCO_LINKS > 0) 1111 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 1112 uint16_t xx; 1113 1114 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 1115 if (p->state != SCO_ST_UNUSED) { 1116 if ((!bda) || (p->esco.data.bd_addr == *bda && p->rem_bd_known)) { 1117 btm_sco_flush_sco_data(xx); 1118 1119 p->state = SCO_ST_UNUSED; 1120 p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */ 1121 (*p->p_disc_cb)(xx); 1122 } 1123 } 1124 } 1125#endif 1126} 1127 1128/******************************************************************************* 1129 * 1130 * Function BTM_SetScoPacketTypes 1131 * 1132 * Description This function is called to set the packet types used for 1133 * a specific SCO connection, 1134 * 1135 * Parameters pkt_types - One or more of the following 1136 * BTM_SCO_PKT_TYPES_MASK_HV1 1137 * BTM_SCO_PKT_TYPES_MASK_HV2 1138 * BTM_SCO_PKT_TYPES_MASK_HV3 1139 * BTM_SCO_PKT_TYPES_MASK_EV3 1140 * BTM_SCO_PKT_TYPES_MASK_EV4 1141 * BTM_SCO_PKT_TYPES_MASK_EV5 1142 * BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 1143 * BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 1144 * BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 1145 * BTM_SCO_PKT_TYPES_MASK_NO_3_EV5 1146 * 1147 * BTM_SCO_LINK_ALL_MASK - enables all supported types 1148 * 1149 * Returns status of the operation 1150 * 1151 ******************************************************************************/ 1152tBTM_STATUS BTM_SetScoPacketTypes(uint16_t sco_inx, uint16_t pkt_types) { 1153#if (BTM_MAX_SCO_LINKS > 0) 1154 tBTM_CHG_ESCO_PARAMS parms; 1155 tSCO_CONN* p; 1156 1157 /* Validity check */ 1158 if (sco_inx >= BTM_MAX_SCO_LINKS) return (BTM_UNKNOWN_ADDR); 1159 1160 p = &btm_cb.sco_cb.sco_db[sco_inx]; 1161 parms.packet_types = pkt_types; 1162 1163 /* Keep the other parameters the same for SCO */ 1164 parms.max_latency_ms = p->esco.setup.max_latency_ms; 1165 parms.retransmission_effort = p->esco.setup.retransmission_effort; 1166 1167 return (BTM_ChangeEScoLinkParms(sco_inx, &parms)); 1168#else 1169 return (BTM_UNKNOWN_ADDR); 1170#endif 1171} 1172 1173/******************************************************************************* 1174 * 1175 * Function BTM_ReadScoPacketTypes 1176 * 1177 * Description This function is read the packet types used for a specific 1178 * SCO connection. 1179 * 1180 * Returns Packet types supported for the connection 1181 * One or more of the following (bitmask): 1182 * BTM_SCO_PKT_TYPES_MASK_HV1 1183 * BTM_SCO_PKT_TYPES_MASK_HV2 1184 * BTM_SCO_PKT_TYPES_MASK_HV3 1185 * BTM_SCO_PKT_TYPES_MASK_EV3 1186 * BTM_SCO_PKT_TYPES_MASK_EV4 1187 * BTM_SCO_PKT_TYPES_MASK_EV5 1188 * BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 1189 * BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 1190 * BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 1191 * BTM_SCO_PKT_TYPES_MASK_NO_3_EV5 1192 * 1193 ******************************************************************************/ 1194uint16_t BTM_ReadScoPacketTypes(uint16_t sco_inx) { 1195#if (BTM_MAX_SCO_LINKS > 0) 1196 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx]; 1197 1198 /* Validity check */ 1199 if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->state == SCO_ST_CONNECTED)) 1200 return (p->esco.setup.packet_types); 1201 else 1202 return (0); 1203#else 1204 return (0); 1205#endif 1206} 1207 1208/******************************************************************************* 1209 * 1210 * Function BTM_ReadScoDiscReason 1211 * 1212 * Description This function is returns the reason why an (e)SCO connection 1213 * has been removed. It contains the value until read, or until 1214 * another (e)SCO connection has disconnected. 1215 * 1216 * Returns HCI reason or BTM_INVALID_SCO_DISC_REASON if not set. 1217 * 1218 ******************************************************************************/ 1219uint16_t BTM_ReadScoDiscReason(void) { 1220 uint16_t res = btm_cb.sco_cb.sco_disc_reason; 1221 btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON; 1222 return (res); 1223} 1224 1225/******************************************************************************* 1226 * 1227 * Function BTM_ReadDeviceScoPacketTypes 1228 * 1229 * Description This function is read the SCO packet types that 1230 * the device supports. 1231 * 1232 * Returns Packet types supported by the device. 1233 * One or more of the following (bitmask): 1234 * BTM_SCO_PKT_TYPES_MASK_HV1 1235 * BTM_SCO_PKT_TYPES_MASK_HV2 1236 * BTM_SCO_PKT_TYPES_MASK_HV3 1237 * BTM_SCO_PKT_TYPES_MASK_EV3 1238 * BTM_SCO_PKT_TYPES_MASK_EV4 1239 * BTM_SCO_PKT_TYPES_MASK_EV5 1240 * BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 1241 * BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 1242 * BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 1243 * BTM_SCO_PKT_TYPES_MASK_NO_3_EV5 1244 * 1245 ******************************************************************************/ 1246uint16_t BTM_ReadDeviceScoPacketTypes(void) { 1247 return (btm_cb.btm_sco_pkt_types_supported); 1248} 1249 1250/******************************************************************************* 1251 * 1252 * Function BTM_ReadScoHandle 1253 * 1254 * Description This function is used to read the HCI handle used for a 1255 * specific SCO connection, 1256 * 1257 * Returns handle for the connection, or 0xFFFF if invalid SCO index. 1258 * 1259 ******************************************************************************/ 1260uint16_t BTM_ReadScoHandle(uint16_t sco_inx) { 1261#if (BTM_MAX_SCO_LINKS > 0) 1262 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx]; 1263 1264 /* Validity check */ 1265 if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->state == SCO_ST_CONNECTED)) 1266 return (p->hci_handle); 1267 else 1268 return (BTM_INVALID_HCI_HANDLE); 1269#else 1270 return (BTM_INVALID_HCI_HANDLE); 1271#endif 1272} 1273 1274/******************************************************************************* 1275 * 1276 * Function BTM_ReadScoBdAddr 1277 * 1278 * Description This function is read the remote BD Address for a specific 1279 * SCO connection, 1280 * 1281 * Returns pointer to BD address or NULL if not known 1282 * 1283 ******************************************************************************/ 1284const RawAddress* BTM_ReadScoBdAddr(uint16_t sco_inx) { 1285#if (BTM_MAX_SCO_LINKS > 0) 1286 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx]; 1287 1288 /* Validity check */ 1289 if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->rem_bd_known)) 1290 return &(p->esco.data.bd_addr); 1291 else 1292 return (NULL); 1293#else 1294 return (NULL); 1295#endif 1296} 1297 1298/******************************************************************************* 1299 * 1300 * Function BTM_SetEScoMode 1301 * 1302 * Description This function sets up the negotiated parameters for SCO or 1303 * eSCO, and sets as the default mode used for outgoing calls 1304 * to BTM_CreateSco. It does not change any currently active 1305 * (e)SCO links. 1306 * Note: Incoming (e)SCO connections will always use packet 1307 * types supported by the controller. If eSCO is not 1308 * desired the feature should be disabled in the 1309 * controller's feature mask. 1310 * 1311 * Returns BTM_SUCCESS if the successful. 1312 * BTM_BUSY if there are one or more active (e)SCO links. 1313 * 1314 ******************************************************************************/ 1315tBTM_STATUS BTM_SetEScoMode(enh_esco_params_t* p_parms) { 1316 enh_esco_params_t* p_def = &btm_cb.sco_cb.def_esco_parms; 1317 1318 if (btm_cb.sco_cb.esco_supported) { 1319 *p_def = *p_parms; 1320 } else { 1321 /* Load defaults for SCO only */ 1322 *p_def = esco_parameters_for_codec(ESCO_CODEC_CVSD); 1323 p_def->packet_types &= BTM_SCO_LINK_ONLY_MASK; 1324 p_def->retransmission_effort = ESCO_RETRANSMISSION_OFF; 1325 p_def->max_latency_ms = 12; 1326 BTM_TRACE_WARNING("%s: eSCO not supported", __func__); 1327 } 1328 1329 BTM_TRACE_API( 1330 "%s: txbw 0x%08x, rxbw 0x%08x, max_lat 0x%04x, " 1331 "pkt 0x%04x, rtx effort 0x%02x", 1332 __func__, p_def->transmit_bandwidth, p_def->receive_bandwidth, 1333 p_def->max_latency_ms, p_def->packet_types, p_def->retransmission_effort); 1334 1335 return BTM_SUCCESS; 1336} 1337 1338/******************************************************************************* 1339 * 1340 * Function BTM_RegForEScoEvts 1341 * 1342 * Description This function registers a SCO event callback with the 1343 * specified instance. It should be used to received 1344 * connection indication events and change of link parameter 1345 * events. 1346 * 1347 * Returns BTM_SUCCESS if the successful. 1348 * BTM_ILLEGAL_VALUE if there is an illegal sco_inx 1349 * BTM_MODE_UNSUPPORTED if controller version is not BT1.2 or 1350 * later or does not support eSCO. 1351 * 1352 ******************************************************************************/ 1353tBTM_STATUS BTM_RegForEScoEvts(uint16_t sco_inx, 1354 tBTM_ESCO_CBACK* p_esco_cback) { 1355#if (BTM_MAX_SCO_LINKS > 0) 1356 if (!btm_cb.sco_cb.esco_supported) { 1357 btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = NULL; 1358 return (BTM_MODE_UNSUPPORTED); 1359 } 1360 1361 if (sco_inx < BTM_MAX_SCO_LINKS && 1362 btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_UNUSED) { 1363 btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = p_esco_cback; 1364 return (BTM_SUCCESS); 1365 } 1366 return (BTM_ILLEGAL_VALUE); 1367#else 1368 return (BTM_MODE_UNSUPPORTED); 1369#endif 1370} 1371 1372/******************************************************************************* 1373 * 1374 * Function BTM_ReadEScoLinkParms 1375 * 1376 * Description This function returns the current eSCO link parameters for 1377 * the specified handle. This can be called anytime a 1378 * connection is active, but is typically called after 1379 * receiving the SCO opened callback. 1380 * 1381 * Note: If called over a 1.1 controller, only the packet types 1382 * field has meaning. 1383 * 1384 * Returns BTM_SUCCESS if returned data is valid connection. 1385 * BTM_WRONG_MODE if no connection with a peer device or bad 1386 * sco_inx. 1387 * 1388 ******************************************************************************/ 1389tBTM_STATUS BTM_ReadEScoLinkParms(uint16_t sco_inx, tBTM_ESCO_DATA* p_parms) { 1390#if (BTM_MAX_SCO_LINKS > 0) 1391 uint8_t index; 1392 1393 BTM_TRACE_API("%s: -> sco_inx 0x%04x", __func__, sco_inx); 1394 1395 if (sco_inx < BTM_MAX_SCO_LINKS && 1396 btm_cb.sco_cb.sco_db[sco_inx].state >= SCO_ST_CONNECTED) { 1397 *p_parms = btm_cb.sco_cb.sco_db[sco_inx].esco.data; 1398 return (BTM_SUCCESS); 1399 } 1400 1401 if (sco_inx == BTM_FIRST_ACTIVE_SCO_INDEX) { 1402 for (index = 0; index < BTM_MAX_SCO_LINKS; index++) { 1403 if (btm_cb.sco_cb.sco_db[index].state >= SCO_ST_CONNECTED) { 1404 BTM_TRACE_API("%s: the first active SCO index is %d", __func__, index); 1405 *p_parms = btm_cb.sco_cb.sco_db[index].esco.data; 1406 return (BTM_SUCCESS); 1407 } 1408 } 1409 } 1410 1411#endif 1412 1413 BTM_TRACE_API("BTM_ReadEScoLinkParms cannot find the SCO index!"); 1414 memset(p_parms, 0, sizeof(tBTM_ESCO_DATA)); 1415 return (BTM_WRONG_MODE); 1416} 1417 1418/******************************************************************************* 1419 * 1420 * Function BTM_ChangeEScoLinkParms 1421 * 1422 * Description This function requests renegotiation of the parameters on 1423 * the current eSCO Link. If any of the changes are accepted 1424 * by the controllers, the BTM_ESCO_CHG_EVT event is sent in 1425 * the tBTM_ESCO_CBACK function with the current settings of 1426 * the link. The callback is registered through the call to 1427 * BTM_SetEScoMode. 1428 * 1429 * Note: If called over a SCO link (including 1.1 controller), 1430 * a change packet type request is sent out instead. 1431 * 1432 * Returns BTM_CMD_STARTED if command is successfully initiated. 1433 * BTM_NO_RESOURCES - not enough resources to initiate command. 1434 * BTM_WRONG_MODE if no connection with a peer device or bad 1435 * sco_inx. 1436 * 1437 ******************************************************************************/ 1438tBTM_STATUS BTM_ChangeEScoLinkParms(uint16_t sco_inx, 1439 tBTM_CHG_ESCO_PARAMS* p_parms) { 1440#if (BTM_MAX_SCO_LINKS > 0) 1441 1442 /* Make sure sco handle is valid and on an active link */ 1443 if (sco_inx >= BTM_MAX_SCO_LINKS || 1444 btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_CONNECTED) 1445 return (BTM_WRONG_MODE); 1446 1447 tSCO_CONN* p_sco = &btm_cb.sco_cb.sco_db[sco_inx]; 1448 enh_esco_params_t* p_setup = &p_sco->esco.setup; 1449 1450 /* Save the previous types in case command fails */ 1451 uint16_t saved_packet_types = p_setup->packet_types; 1452 1453 /* If SCO connection OR eSCO not supported just send change packet types */ 1454 if (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO || 1455 !btm_cb.sco_cb.esco_supported) { 1456 p_setup->packet_types = 1457 p_parms->packet_types & 1458 (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_LINK_ONLY_MASK); 1459 1460 BTM_TRACE_API("%s: SCO Link for handle 0x%04x, pkt 0x%04x", __func__, 1461 p_sco->hci_handle, p_setup->packet_types); 1462 1463 BTM_TRACE_API("%s: SCO Link for handle 0x%04x, pkt 0x%04x", __func__, 1464 p_sco->hci_handle, p_setup->packet_types); 1465 1466 btsnd_hcic_change_conn_type(p_sco->hci_handle, 1467 BTM_ESCO_2_SCO(p_setup->packet_types)); 1468 } else /* eSCO is supported and the link type is eSCO */ 1469 { 1470 uint16_t temp_packet_types = 1471 (p_parms->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK & 1472 btm_cb.btm_sco_pkt_types_supported); 1473 1474 /* OR in any exception packet types */ 1475 temp_packet_types |= 1476 ((p_parms->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) | 1477 (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK)); 1478 p_setup->packet_types = temp_packet_types; 1479 1480 BTM_TRACE_API("%s -> eSCO Link for handle 0x%04x", __func__, 1481 p_sco->hci_handle); 1482 BTM_TRACE_API( 1483 " txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, pkt 0x%04x", 1484 p_setup->transmit_bandwidth, p_setup->receive_bandwidth, 1485 p_parms->max_latency_ms, p_parms->retransmission_effort, 1486 temp_packet_types); 1487 1488 /* Use Enhanced Synchronous commands if supported */ 1489 if (controller_get_interface() 1490 ->supports_enhanced_setup_synchronous_connection()) { 1491 /* Use the saved SCO routing */ 1492 p_setup->input_data_path = p_setup->output_data_path = 1493 btm_cb.sco_cb.sco_route; 1494 1495 btsnd_hcic_enhanced_set_up_synchronous_connection(p_sco->hci_handle, 1496 p_setup); 1497 p_setup->packet_types = saved_packet_types; 1498 } else { /* Use older command */ 1499 uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup); 1500 /* When changing an existing link, only change latency, retrans, and 1501 * pkts */ 1502 btsnd_hcic_setup_esco_conn(p_sco->hci_handle, p_setup->transmit_bandwidth, 1503 p_setup->receive_bandwidth, 1504 p_parms->max_latency_ms, voice_content_format, 1505 p_parms->retransmission_effort, 1506 p_setup->packet_types); 1507 } 1508 1509 BTM_TRACE_API( 1510 "%s: txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, pkt 0x%04x", 1511 __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth, 1512 p_parms->max_latency_ms, p_parms->retransmission_effort, 1513 temp_packet_types); 1514 } 1515 1516 return (BTM_CMD_STARTED); 1517#else 1518 return (BTM_WRONG_MODE); 1519#endif 1520} 1521 1522/******************************************************************************* 1523 * 1524 * Function BTM_EScoConnRsp 1525 * 1526 * Description This function is called upon receipt of an (e)SCO connection 1527 * request event (BTM_ESCO_CONN_REQ_EVT) to accept or reject 1528 * the request. Parameters used to negotiate eSCO links. 1529 * If p_parms is NULL, then values set through BTM_SetEScoMode 1530 * are used. 1531 * If the link type of the incoming request is SCO, then only 1532 * the tx_bw, max_latency, content format, and packet_types are 1533 * valid. The hci_status parameter should be 1534 * ([0x0] to accept, [0x0d..0x0f] to reject) 1535 * 1536 * 1537 * Returns void 1538 * 1539 ******************************************************************************/ 1540void BTM_EScoConnRsp(uint16_t sco_inx, uint8_t hci_status, 1541 enh_esco_params_t* p_parms) { 1542#if (BTM_MAX_SCO_LINKS > 0) 1543 if (sco_inx < BTM_MAX_SCO_LINKS && 1544 btm_cb.sco_cb.sco_db[sco_inx].state == SCO_ST_W4_CONN_RSP) { 1545 btm_esco_conn_rsp(sco_inx, hci_status, 1546 btm_cb.sco_cb.sco_db[sco_inx].esco.data.bd_addr, p_parms); 1547 } 1548#endif 1549} 1550 1551/******************************************************************************* 1552 * 1553 * Function btm_read_def_esco_mode 1554 * 1555 * Description This function copies the current default esco settings into 1556 * the return buffer. 1557 * 1558 * Returns tBTM_SCO_TYPE 1559 * 1560 ******************************************************************************/ 1561void btm_read_def_esco_mode(enh_esco_params_t* p_parms) { 1562#if (BTM_MAX_SCO_LINKS > 0) 1563 *p_parms = btm_cb.sco_cb.def_esco_parms; 1564#endif 1565} 1566 1567/******************************************************************************* 1568 * 1569 * Function btm_esco_proc_conn_chg 1570 * 1571 * Description This function is called by BTIF when an SCO connection 1572 * is changed. 1573 * 1574 * Returns void 1575 * 1576 ******************************************************************************/ 1577void btm_esco_proc_conn_chg(uint8_t status, uint16_t handle, 1578 uint8_t tx_interval, uint8_t retrans_window, 1579 uint16_t rx_pkt_len, uint16_t tx_pkt_len) { 1580#if (BTM_MAX_SCO_LINKS > 0) 1581 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 1582 tBTM_CHG_ESCO_EVT_DATA data; 1583 uint16_t xx; 1584 1585 BTM_TRACE_EVENT("btm_esco_proc_conn_chg -> handle 0x%04x, status 0x%02x", 1586 handle, status); 1587 1588 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 1589 if (p->state == SCO_ST_CONNECTED && handle == p->hci_handle) { 1590 /* If upper layer wants notification */ 1591 if (p->esco.p_esco_cback) { 1592 data.bd_addr = p->esco.data.bd_addr; 1593 data.hci_status = status; 1594 data.sco_inx = xx; 1595 data.rx_pkt_len = p->esco.data.rx_pkt_len = rx_pkt_len; 1596 data.tx_pkt_len = p->esco.data.tx_pkt_len = tx_pkt_len; 1597 data.tx_interval = p->esco.data.tx_interval = tx_interval; 1598 data.retrans_window = p->esco.data.retrans_window = retrans_window; 1599 1600 tBTM_ESCO_EVT_DATA btm_esco_evt_data; 1601 btm_esco_evt_data.chg_evt = data; 1602 (*p->esco.p_esco_cback)(BTM_ESCO_CHG_EVT, &btm_esco_evt_data); 1603 } 1604 return; 1605 } 1606 } 1607#endif 1608} 1609 1610/******************************************************************************* 1611 * 1612 * Function btm_is_sco_active 1613 * 1614 * Description This function is called to see if a SCO handle is already in 1615 * use. 1616 * 1617 * Returns bool 1618 * 1619 ******************************************************************************/ 1620bool btm_is_sco_active(uint16_t handle) { 1621#if (BTM_MAX_SCO_LINKS > 0) 1622 uint16_t xx; 1623 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 1624 1625 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 1626 if (handle == p->hci_handle && p->state == SCO_ST_CONNECTED) return (true); 1627 } 1628#endif 1629 return (false); 1630} 1631 1632/******************************************************************************* 1633 * 1634 * Function BTM_GetNumScoLinks 1635 * 1636 * Description This function returns the number of active sco links. 1637 * 1638 * Returns uint8_t 1639 * 1640 ******************************************************************************/ 1641uint8_t BTM_GetNumScoLinks(void) { 1642#if (BTM_MAX_SCO_LINKS > 0) 1643 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 1644 uint16_t xx; 1645 uint8_t num_scos = 0; 1646 1647 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 1648 switch (p->state) { 1649 case SCO_ST_W4_CONN_RSP: 1650 case SCO_ST_CONNECTING: 1651 case SCO_ST_CONNECTED: 1652 case SCO_ST_DISCONNECTING: 1653 case SCO_ST_PEND_UNPARK: 1654 num_scos++; 1655 } 1656 } 1657 return (num_scos); 1658#else 1659 return (0); 1660#endif 1661} 1662 1663/******************************************************************************* 1664 * 1665 * Function btm_is_sco_active_by_bdaddr 1666 * 1667 * Description This function is called to see if a SCO connection is active 1668 * for a bd address. 1669 * 1670 * Returns bool 1671 * 1672 ******************************************************************************/ 1673bool btm_is_sco_active_by_bdaddr(const RawAddress& remote_bda) { 1674#if (BTM_MAX_SCO_LINKS > 0) 1675 uint8_t xx; 1676 tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; 1677 1678 /* If any SCO is being established to the remote BD address, refuse this */ 1679 for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { 1680 if (p->esco.data.bd_addr == remote_bda && p->state == SCO_ST_CONNECTED) { 1681 return (true); 1682 } 1683 } 1684#endif 1685 return (false); 1686} 1687 1688/******************************************************************************* 1689 * 1690 * Function btm_sco_voice_settings_2_legacy 1691 * 1692 * Description This function is called to convert the Enhanced eSCO 1693 * parameters into voice setting parameter mask used 1694 * for legacy setup synchronous connection HCI commands 1695 * 1696 * Returns UINT16 - 16-bit mask for voice settings 1697 * 1698 * HCI_INP_CODING_LINEAR 0x0000 (0000000000) 1699 * HCI_INP_CODING_U_LAW 0x0100 (0100000000) 1700 * HCI_INP_CODING_A_LAW 0x0200 (1000000000) 1701 * HCI_INP_CODING_MASK 0x0300 (1100000000) 1702 * 1703 * HCI_INP_DATA_FMT_1S_COMPLEMENT 0x0000 (0000000000) 1704 * HCI_INP_DATA_FMT_2S_COMPLEMENT 0x0040 (0001000000) 1705 * HCI_INP_DATA_FMT_SIGN_MAGNITUDE 0x0080 (0010000000) 1706 * HCI_INP_DATA_FMT_UNSIGNED 0x00c0 (0011000000) 1707 * HCI_INP_DATA_FMT_MASK 0x00c0 (0011000000) 1708 * 1709 * HCI_INP_SAMPLE_SIZE_8BIT 0x0000 (0000000000) 1710 * HCI_INP_SAMPLE_SIZE_16BIT 0x0020 (0000100000) 1711 * HCI_INP_SAMPLE_SIZE_MASK 0x0020 (0000100000) 1712 * 1713 * HCI_INP_LINEAR_PCM_BIT_POS_MASK 0x001c (0000011100) 1714 * HCI_INP_LINEAR_PCM_BIT_POS_OFFS 2 1715 * 1716 * HCI_AIR_CODING_FORMAT_CVSD 0x0000 (0000000000) 1717 * HCI_AIR_CODING_FORMAT_U_LAW 0x0001 (0000000001) 1718 * HCI_AIR_CODING_FORMAT_A_LAW 0x0002 (0000000010) 1719 * HCI_AIR_CODING_FORMAT_TRANSPNT 0x0003 (0000000011) 1720 * HCI_AIR_CODING_FORMAT_MASK 0x0003 (0000000011) 1721 * 1722 * default (0001100000) 1723 * HCI_DEFAULT_VOICE_SETTINGS (HCI_INP_CODING_LINEAR \ 1724 * | HCI_INP_DATA_FMT_2S_COMPLEMENT \ 1725 * | HCI_INP_SAMPLE_SIZE_16BIT \ 1726 * | HCI_AIR_CODING_FORMAT_CVSD) 1727 * 1728 ******************************************************************************/ 1729static uint16_t btm_sco_voice_settings_to_legacy(enh_esco_params_t* p_params) { 1730 uint16_t voice_settings = 0; 1731 1732 /* Convert Input Coding Format: If no uLaw or aLAW then Linear will be used 1733 * (0) */ 1734 if (p_params->input_coding_format.coding_format == ESCO_CODING_FORMAT_ULAW) 1735 voice_settings |= HCI_INP_CODING_U_LAW; 1736 else if (p_params->input_coding_format.coding_format == 1737 ESCO_CODING_FORMAT_ALAW) 1738 voice_settings |= HCI_INP_CODING_A_LAW; 1739 /* else default value of '0 is good 'Linear' */ 1740 1741 /* Convert Input Data Format. Use 2's Compliment as the default */ 1742 switch (p_params->input_pcm_data_format) { 1743 case ESCO_PCM_DATA_FORMAT_1_COMP: 1744 /* voice_settings |= HCI_INP_DATA_FMT_1S_COMPLEMENT; value is '0' 1745 * already */ 1746 break; 1747 1748 case ESCO_PCM_DATA_FORMAT_SIGN: 1749 voice_settings |= HCI_INP_DATA_FMT_SIGN_MAGNITUDE; 1750 break; 1751 1752 case ESCO_PCM_DATA_FORMAT_UNSIGN: 1753 voice_settings |= HCI_INP_DATA_FMT_UNSIGNED; 1754 break; 1755 1756 default: /* 2's Compliment */ 1757 voice_settings |= HCI_INP_DATA_FMT_2S_COMPLEMENT; 1758 break; 1759 } 1760 1761 /* Convert Over the Air Coding. Use CVSD as the default */ 1762 switch (p_params->transmit_coding_format.coding_format) { 1763 case ESCO_CODING_FORMAT_ULAW: 1764 voice_settings |= HCI_AIR_CODING_FORMAT_U_LAW; 1765 break; 1766 1767 case ESCO_CODING_FORMAT_ALAW: 1768 voice_settings |= HCI_AIR_CODING_FORMAT_A_LAW; 1769 break; 1770 1771 case ESCO_CODING_FORMAT_MSBC: 1772 voice_settings |= HCI_AIR_CODING_FORMAT_TRANSPNT; 1773 break; 1774 1775 default: /* CVSD (0) */ 1776 break; 1777 } 1778 1779 /* Convert PCM payload MSB position (0000011100) */ 1780 voice_settings |= (uint16_t)(((p_params->input_pcm_payload_msb_position & 0x7) 1781 << HCI_INP_LINEAR_PCM_BIT_POS_OFFS)); 1782 1783 /* Convert Input Sample Size (0000011100) */ 1784 if (p_params->input_coded_data_size == 16) 1785 voice_settings |= HCI_INP_SAMPLE_SIZE_16BIT; 1786 else /* Use 8 bit for all others */ 1787 voice_settings |= HCI_INP_SAMPLE_SIZE_8BIT; 1788 1789 BTM_TRACE_DEBUG("%s: voice setting for legacy 0x%03x", __func__, 1790 voice_settings); 1791 1792 return (voice_settings); 1793} 1794 1795#else /* SCO_EXCLUDED == TRUE (Link in stubs) */ 1796 1797tBTM_STATUS BTM_CreateSco(const RawAddress* remote_bda, bool is_orig, 1798 uint16_t pkt_types, uint16_t* p_sco_inx, 1799 tBTM_SCO_CB* p_conn_cb, tBTM_SCO_CB* p_disc_cb) { 1800 return (BTM_NO_RESOURCES); 1801} 1802tBTM_STATUS BTM_RemoveSco(uint16_t sco_inx) { return (BTM_NO_RESOURCES); } 1803tBTM_STATUS BTM_SetScoPacketTypes(uint16_t sco_inx, uint16_t pkt_types) { 1804 return (BTM_NO_RESOURCES); 1805} 1806uint16_t BTM_ReadScoPacketTypes(uint16_t sco_inx) { return (0); } 1807uint16_t BTM_ReadDeviceScoPacketTypes(void) { return (0); } 1808uint16_t BTM_ReadScoHandle(uint16_t sco_inx) { 1809 return (BTM_INVALID_HCI_HANDLE); 1810} 1811const RawAddress* BTM_ReadScoBdAddr(uint16_t sco_inx) { 1812 return ((uint8_t*)NULL); 1813} 1814uint16_t BTM_ReadScoDiscReason(void) { return (BTM_INVALID_SCO_DISC_REASON); } 1815tBTM_STATUS BTM_SetEScoMode(enh_esco_params_t* p_parms) { 1816 return (BTM_MODE_UNSUPPORTED); 1817} 1818tBTM_STATUS BTM_RegForEScoEvts(uint16_t sco_inx, 1819 tBTM_ESCO_CBACK* p_esco_cback) { 1820 return (BTM_ILLEGAL_VALUE); 1821} 1822tBTM_STATUS BTM_ReadEScoLinkParms(uint16_t sco_inx, tBTM_ESCO_DATA* p_parms) { 1823 return (BTM_MODE_UNSUPPORTED); 1824} 1825tBTM_STATUS BTM_ChangeEScoLinkParms(uint16_t sco_inx, 1826 tBTM_CHG_ESCO_PARAMS* p_parms) { 1827 return (BTM_MODE_UNSUPPORTED); 1828} 1829void BTM_EScoConnRsp(uint16_t sco_inx, uint8_t hci_status, 1830 enh_esco_params_t* p_parms) {} 1831uint8_t BTM_GetNumScoLinks(void) { return (0); } 1832 1833#endif /* If SCO is being used */ 1834