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