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