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