1 /******************************************************************************
2 *
3 * Copyright (c) 2014 The Android Open Source Project
4 * Copyright (C) 2004-2012 Broadcom Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************************/
19
20 #include "bta_hf_client_int.h"
21 #include <bt_trace.h>
22 #include <bd.h>
23 #include <string.h>
24 #include "bt_utils.h"
25
26 #define BTA_HF_CLIENT_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
27 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
28 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
29 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
30
31 static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
32 /* SCO CVSD */
33 {
34 .rx_bw = BTM_64KBITS_RATE,
35 .tx_bw = BTM_64KBITS_RATE,
36 .max_latency = 10,
37 .voice_contfmt = BTM_VOICE_SETTING_CVSD,
38 .packet_types = (BTM_SCO_LINK_ONLY_MASK |
39 BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
40 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
41 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
42 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
43 .retrans_effort = BTM_ESCO_RETRANS_POWER,
44 },
45 /* ESCO CVSD */
46 {
47 .rx_bw = BTM_64KBITS_RATE,
48 .tx_bw = BTM_64KBITS_RATE,
49 .max_latency = 10,
50 .voice_contfmt = BTM_VOICE_SETTING_CVSD,
51 /* Allow controller to use all types available except 5-slot EDR */
52 .packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
53 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
54 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
55 .retrans_effort = BTM_ESCO_RETRANS_POWER,
56 },
57 /* ESCO mSBC */
58 {
59 .rx_bw = BTM_64KBITS_RATE,
60 .tx_bw = BTM_64KBITS_RATE,
61 .max_latency = 13,
62 .voice_contfmt = BTM_VOICE_SETTING_TRANS,
63 /* Packet Types : EV3 + 2-EV3 */
64 .packet_types = (BTM_SCO_PKT_TYPES_MASK_EV3 |
65 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
66 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
67 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
68 .retrans_effort = BTM_ESCO_RETRANS_QUALITY,
69 }
70 };
71
72 enum
73 {
74 BTA_HF_CLIENT_SCO_LISTEN_E,
75 BTA_HF_CLIENT_SCO_OPEN_E, /* open request */
76 BTA_HF_CLIENT_SCO_CLOSE_E, /* close request */
77 BTA_HF_CLIENT_SCO_SHUTDOWN_E, /* shutdown request */
78 BTA_HF_CLIENT_SCO_CONN_OPEN_E, /* sco opened */
79 BTA_HF_CLIENT_SCO_CONN_CLOSE_E, /* sco closed */
80 };
81
82 /*******************************************************************************
83 **
84 ** Function bta_hf_client_remove_sco
85 **
86 ** Description Removes the specified SCO from the system.
87 ** If only_active is TRUE, then SCO is only removed if connected
88 **
89 ** Returns BOOLEAN - TRUE if Sco removal was started
90 **
91 *******************************************************************************/
bta_hf_client_sco_remove(BOOLEAN only_active)92 static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active)
93 {
94 BOOLEAN removed_started = FALSE;
95 tBTM_STATUS status;
96
97 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, only_active);
98
99 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
100 {
101 status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx);
102
103 APPL_TRACE_DEBUG("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status);
104
105 if (status == BTM_CMD_STARTED)
106 {
107 removed_started = TRUE;
108 }
109 /* If no connection reset the sco handle */
110 else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) )
111 {
112 bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
113 }
114 }
115 return removed_started;
116 }
117
118 /*******************************************************************************
119 **
120 ** Function bta_hf_client_cback_sco
121 **
122 ** Description Call application callback function with SCO event.
123 **
124 **
125 ** Returns void
126 **
127 *******************************************************************************/
bta_hf_client_cback_sco(UINT8 event)128 void bta_hf_client_cback_sco(UINT8 event)
129 {
130 tBTA_HF_CLIENT evt;
131
132 memset(&evt, 0, sizeof(evt));
133
134 /* call app cback */
135 (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT *) &evt);
136 }
137
138 /*******************************************************************************
139 **
140 ** Function bta_hf_client_sco_conn_rsp
141 **
142 ** Description Process the SCO connection request
143 **
144 **
145 ** Returns void
146 **
147 *******************************************************************************/
bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA * p_data)148 static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
149 {
150 tBTM_ESCO_PARAMS resp;
151 UINT8 hci_status = HCI_SUCCESS;
152
153 APPL_TRACE_DEBUG("%s", __FUNCTION__);
154
155 if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST)
156 {
157 if (p_data->link_type == BTM_LINK_TYPE_SCO)
158 {
159 resp = bta_hf_client_esco_params[0];
160 }
161 else
162 {
163 resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec];
164 }
165
166 /* tell sys to stop av if any */
167 bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
168 }
169 else
170 {
171 hci_status = HCI_ERR_HOST_REJECT_DEVICE;
172 }
173
174 BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
175 }
176
177 /*******************************************************************************
178 **
179 ** Function bta_hf_client_sco_connreq_cback
180 **
181 ** Description BTM eSCO connection requests and eSCO change requests
182 ** Only the connection requests are processed by BTA.
183 **
184 ** Returns void
185 **
186 *******************************************************************************/
bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event,tBTM_ESCO_EVT_DATA * p_data)187 static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
188 {
189 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, event);
190
191 if (event != BTM_ESCO_CONN_REQ_EVT)
192 {
193 return;
194 }
195
196 /* TODO check remote bdaddr, should allow connect only from device with
197 * active SLC */
198
199 bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx;
200
201 bta_hf_client_sco_conn_rsp(&p_data->conn_evt);
202
203 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
204 }
205
206 /*******************************************************************************
207 **
208 ** Function bta_hf_client_sco_conn_cback
209 **
210 ** Description BTM SCO connection callback.
211 **
212 **
213 ** Returns void
214 **
215 *******************************************************************************/
bta_hf_client_sco_conn_cback(UINT16 sco_idx)216 static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
217 {
218 BT_HDR *p_buf;
219 UINT8 *rem_bd;
220
221 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
222
223 rem_bd = BTM_ReadScoBdAddr(sco_idx);
224
225 if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 &&
226 bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx)
227 {
228 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
229 {
230 p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT;
231 p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;
232 bta_sys_sendmsg(p_buf);
233 }
234 }
235 /* no match found; disconnect sco, init sco variables */
236 else
237 {
238 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
239 BTM_RemoveSco(sco_idx);
240 }
241 }
242
243 /*******************************************************************************
244 **
245 ** Function bta_hf_client_sco_disc_cback
246 **
247 ** Description BTM SCO disconnection callback.
248 **
249 **
250 ** Returns void
251 **
252 *******************************************************************************/
bta_hf_client_sco_disc_cback(UINT16 sco_idx)253 static void bta_hf_client_sco_disc_cback(UINT16 sco_idx)
254 {
255 BT_HDR *p_buf;
256
257 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
258
259 if (bta_hf_client_cb.scb.sco_idx == sco_idx)
260 {
261 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
262 {
263 p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT;
264 p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;;
265 bta_sys_sendmsg(p_buf);
266 }
267 }
268 }
269
270 /*******************************************************************************
271 **
272 ** Function bta_hf_client_create_sco
273 **
274 ** Description
275 **
276 **
277 ** Returns void
278 **
279 *******************************************************************************/
bta_hf_client_sco_create(BOOLEAN is_orig)280 static void bta_hf_client_sco_create(BOOLEAN is_orig)
281 {
282 tBTM_STATUS status;
283 UINT8 *p_bd_addr = NULL;
284 tBTM_ESCO_PARAMS params;
285
286 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig);
287
288 /* Make sure this sco handle is not already in use */
289 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
290 {
291 APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__,
292 bta_hf_client_cb.scb.sco_idx);
293 return;
294 }
295
296 params = bta_hf_client_esco_params[1];
297
298 /* if initiating set current scb and peer bd addr */
299 if (is_orig)
300 {
301 /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
302 if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only)
303 {
304 BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, ¶ms);
305 /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
306 if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
307 ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO))
308 {
309 bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
310 APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
311 }
312 }
313 else
314 {
315 if(bta_hf_client_cb.scb.retry_with_sco_only)
316 APPL_TRACE_API("retrying with SCO only");
317 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
318
319 BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms);
320 }
321
322 /* tell sys to stop av if any */
323 bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
324 }
325 else
326 {
327 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
328 }
329
330 p_bd_addr = bta_hf_client_cb.scb.peer_addr;
331
332 status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
333 &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback,
334 bta_hf_client_sco_disc_cback);
335 if (status == BTM_CMD_STARTED && !is_orig)
336 {
337 if(!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback))
338 APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__);
339 }
340
341 APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
342 __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx,
343 status, params.packet_types);
344 }
345
346
347 /*******************************************************************************
348 **
349 ** Function bta_hf_client_sco_event
350 **
351 ** Description Handle SCO events
352 **
353 **
354 ** Returns void
355 **
356 *******************************************************************************/
bta_hf_client_sco_event(UINT8 event)357 static void bta_hf_client_sco_event(UINT8 event)
358 {
359 APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__,
360 bta_hf_client_cb.scb.sco_state, event);
361
362 switch (bta_hf_client_cb.scb.sco_state)
363 {
364 case BTA_HF_CLIENT_SCO_SHUTDOWN_ST:
365 switch (event)
366 {
367 case BTA_HF_CLIENT_SCO_LISTEN_E:
368 /* create sco listen connection */
369 bta_hf_client_sco_create(FALSE);
370 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
371 break;
372
373 default:
374 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event);
375 break;
376 }
377 break;
378
379 case BTA_HF_CLIENT_SCO_LISTEN_ST:
380 switch (event)
381 {
382 case BTA_HF_CLIENT_SCO_LISTEN_E:
383 /* create sco listen connection (Additional channel) */
384 bta_hf_client_sco_create(FALSE);
385 break;
386
387 case BTA_HF_CLIENT_SCO_OPEN_E:
388 /* remove listening connection */
389 bta_hf_client_sco_remove(FALSE);
390
391 /* create sco connection to peer */
392 bta_hf_client_sco_create(TRUE);
393 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
394 break;
395
396 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
397 /* remove listening connection */
398 bta_hf_client_sco_remove(FALSE);
399
400 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
401 break;
402
403 case BTA_HF_CLIENT_SCO_CLOSE_E:
404 /* remove listening connection */
405 /* Ignore the event. We need to keep listening SCO for the active SLC */
406 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
407 break;
408
409 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
410 /* sco failed; create sco listen connection */
411 bta_hf_client_sco_create(FALSE);
412 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
413 break;
414
415 default:
416 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
417 break;
418 }
419 break;
420
421 case BTA_HF_CLIENT_SCO_OPENING_ST:
422 switch (event)
423 {
424 case BTA_HF_CLIENT_SCO_CLOSE_E:
425 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST;
426 break;
427
428 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
429 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
430 break;
431
432 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
433 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST;
434 break;
435
436 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
437 /* sco failed; create sco listen connection */
438 bta_hf_client_sco_create(FALSE);
439 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
440 break;
441
442 default:
443 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event);
444 break;
445 }
446 break;
447
448 case BTA_HF_CLIENT_SCO_OPEN_CL_ST:
449 switch (event)
450 {
451 case BTA_HF_CLIENT_SCO_OPEN_E:
452 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
453 break;
454
455 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
456 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
457 break;
458
459 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
460 /* close sco connection */
461 bta_hf_client_sco_remove(TRUE);
462
463 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
464 break;
465
466 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
467 /* sco failed; create sco listen connection */
468
469 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
470 break;
471
472 default:
473 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event);
474 break;
475 }
476 break;
477
478 case BTA_HF_CLIENT_SCO_OPEN_ST:
479 switch (event)
480 {
481 case BTA_HF_CLIENT_SCO_CLOSE_E:
482 /* close sco connection if active */
483 if (bta_hf_client_sco_remove(TRUE))
484 {
485 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
486 }
487 break;
488
489 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
490 /* remove all listening connections */
491 bta_hf_client_sco_remove(FALSE);
492
493 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
494 break;
495
496 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
497 /* peer closed sco; create sco listen connection */
498 bta_hf_client_sco_create(FALSE);
499 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
500 break;
501
502 default:
503 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event);
504 break;
505 }
506 break;
507
508 case BTA_HF_CLIENT_SCO_CLOSING_ST:
509 switch (event)
510 {
511 case BTA_HF_CLIENT_SCO_OPEN_E:
512 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST;
513 break;
514
515 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
516 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
517 break;
518
519 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
520 /* peer closed sco; create sco listen connection */
521 bta_hf_client_sco_create(FALSE);
522
523 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
524 break;
525
526 default:
527 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event);
528 break;
529 }
530 break;
531
532 case BTA_HF_CLIENT_SCO_CLOSE_OP_ST:
533 switch (event)
534 {
535 case BTA_HF_CLIENT_SCO_CLOSE_E:
536 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
537 break;
538
539 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
540 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
541 break;
542
543 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
544 /* open sco connection */
545 bta_hf_client_sco_create(TRUE);
546 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
547 break;
548
549 default:
550 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event);
551 break;
552 }
553 break;
554
555 case BTA_HF_CLIENT_SCO_SHUTTING_ST:
556 switch (event)
557 {
558 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
559 /* close sco connection; wait for conn close event */
560 bta_hf_client_sco_remove(TRUE);
561 break;
562
563 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
564 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
565 break;
566
567 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
568 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
569 break;
570
571 default:
572 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event);
573 break;
574 }
575 break;
576
577 default:
578 break;
579 }
580 }
581
582 /*******************************************************************************
583 **
584 ** Function bta_hf_client_sco_listen
585 **
586 ** Description Initialize SCO listener
587 **
588 **
589 ** Returns void
590 **
591 *******************************************************************************/
bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA * p_data)592 void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data)
593 {
594 UNUSED(p_data);
595
596 APPL_TRACE_DEBUG("%s", __FUNCTION__);
597
598 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E);
599 }
600
601 /*******************************************************************************
602 **
603 ** Function bta_hf_client_sco_shutdown
604 **
605 ** Description
606 **
607 **
608 ** Returns void
609 **
610 *******************************************************************************/
bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA * p_data)611 void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data)
612 {
613 UNUSED(p_data);
614
615 APPL_TRACE_DEBUG("%s", __FUNCTION__);
616
617 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E);
618 }
619
620 /*******************************************************************************
621 **
622 ** Function bta_hf_client_sco_conn_open
623 **
624 ** Description
625 **
626 **
627 ** Returns void
628 **
629 *******************************************************************************/
bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA * p_data)630 void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data)
631 {
632 UNUSED(p_data);
633
634 APPL_TRACE_DEBUG("%s", __FUNCTION__);
635
636 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E);
637
638 bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
639
640 if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC)
641 {
642 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT);
643 }
644 else
645 {
646 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT);
647 }
648
649 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
650 }
651
652 /*******************************************************************************
653 **
654 ** Function bta_hf_client_sco_conn_close
655 **
656 ** Description
657 **
658 **
659 ** Returns void
660 **
661 *******************************************************************************/
bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA * p_data)662 void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data)
663 {
664 APPL_TRACE_DEBUG("%s", __FUNCTION__);
665
666 /* clear current scb */
667 bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
668
669 /* retry_with_sco_only, will be set only when initiator
670 ** and HFClient is first trying to establish an eSCO connection */
671 if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn)
672 {
673 bta_hf_client_sco_create(TRUE);
674 }
675 else
676 {
677 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E);
678
679 bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
680
681 bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
682
683 /* call app callback */
684 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
685
686 if (bta_hf_client_cb.scb.sco_close_rfc == TRUE)
687 {
688 bta_hf_client_cb.scb.sco_close_rfc = FALSE;
689 bta_hf_client_rfc_do_close(p_data);
690 }
691 }
692 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
693 }
694
695 /*******************************************************************************
696 **
697 ** Function bta_hf_client_sco_open
698 **
699 ** Description
700 **
701 **
702 ** Returns void
703 **
704 *******************************************************************************/
bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA * p_data)705 void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data)
706 {
707 UNUSED(p_data);
708
709 APPL_TRACE_DEBUG("%s", __FUNCTION__);
710
711 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E);
712 }
713
714 /*******************************************************************************
715 **
716 ** Function bta_hf_client_sco_close
717 **
718 ** Description
719 **
720 **
721 ** Returns void
722 **
723 *******************************************************************************/
bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA * p_data)724 void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data)
725 {
726 UNUSED(p_data);
727
728 APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx);
729
730 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
731 {
732 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E);
733 }
734 }
735