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