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