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