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