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