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