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