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