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