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