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