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