1 /******************************************************************************
3 * Copyright (c) 2014 The Android Open Source Project
4 * Copyright (C) 2004-2012 Broadcom Corporation
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:
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 ******************************************************************************/
20 #include "bta_hf_client_int.h"
21 #include "common/bt_trace.h"
23 #include "common/bt_defs.h"
24 #include "common/bt_target.h"
25 #include "osi/allocator.h"
26 #if (BTM_SCO_HCI_INCLUDED == TRUE )
27 #include "bta/bta_hf_client_co.h"
28 #include "hci/hci_audio.h"
31 #if (BTA_HF_INCLUDED == TRUE)
32 #define BTA_HF_CLIENT_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
33 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
34 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
35 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
37 static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
40 .rx_bw = BTM_64KBITS_RATE,
41 .tx_bw = BTM_64KBITS_RATE,
43 .voice_contfmt = BTM_VOICE_SETTING_CVSD,
44 .packet_types = (BTM_SCO_LINK_ONLY_MASK |
45 BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
46 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
47 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
48 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
49 .retrans_effort = BTM_ESCO_RETRANS_OFF,
53 .rx_bw = BTM_64KBITS_RATE,
54 .tx_bw = BTM_64KBITS_RATE,
56 .voice_contfmt = BTM_VOICE_SETTING_CVSD,
57 /* Allow controller to use all types available except 5-slot EDR */
58 .packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
59 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
60 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
61 .retrans_effort = BTM_ESCO_RETRANS_POWER,
65 .rx_bw = BTM_64KBITS_RATE,
66 .tx_bw = BTM_64KBITS_RATE,
68 .voice_contfmt = BTM_VOICE_SETTING_TRANS,
69 /* Packet Types : EV3 + 2-EV3 */
70 .packet_types = (BTM_SCO_PKT_TYPES_MASK_EV3 |
71 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
72 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
73 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
74 .retrans_effort = BTM_ESCO_RETRANS_QUALITY,
79 BTA_HF_CLIENT_SCO_LISTEN_E,
80 BTA_HF_CLIENT_SCO_OPEN_E, /* open request */
81 BTA_HF_CLIENT_SCO_CLOSE_E, /* close request */
82 BTA_HF_CLIENT_SCO_SHUTDOWN_E, /* shutdown request */
83 BTA_HF_CLIENT_SCO_CONN_OPEN_E, /* sco opened */
84 BTA_HF_CLIENT_SCO_CONN_CLOSE_E, /* sco closed */
85 #if (BTM_SCO_HCI_INCLUDED == TRUE )
86 BTA_HF_CLIENT_SCO_CI_DATA_E, /* sco data ready */
87 #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */
90 static void bta_hf_client_sco_event(UINT8 event);
91 /*******************************************************************************
93 ** Function bta_hf_client_remove_sco
95 ** Description Removes the specified SCO from the system.
96 ** If only_active is TRUE, then SCO is only removed if connected
98 ** Returns BOOLEAN - TRUE if Sco removal was started
100 *******************************************************************************/
101 static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active)
103 BOOLEAN removed_started = FALSE;
106 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, only_active);
108 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) {
109 status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx);
111 APPL_TRACE_DEBUG("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status);
113 if (status == BTM_CMD_STARTED) {
114 removed_started = TRUE;
116 /* If no connection reset the sco handle */
117 else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) ) {
118 bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
121 return removed_started;
124 /*******************************************************************************
126 ** Function bta_hf_client_cback_sco
128 ** Description Call application callback function with SCO event.
133 *******************************************************************************/
134 void bta_hf_client_cback_sco(UINT8 event)
136 tBTA_HF_CLIENT_HDR evt;
138 memset(&evt, 0, sizeof(evt));
141 (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT_HDR *) &evt);
144 #if (BTM_SCO_HCI_INCLUDED == TRUE )
145 /*******************************************************************************
147 ** Function bta_hf_client_sco_read_cback
149 ** Description Callback function is the callback function for incoming
150 ** SCO data over HCI.
154 *******************************************************************************/
155 static void bta_hf_client_sco_read_cback (UINT16 sco_idx, BT_HDR *p_data, tBTM_SCO_DATA_FLAG status)
157 if (status != BTM_SCO_DATA_CORRECT)
159 APPL_TRACE_DEBUG("%s: status(%d)", __FUNCTION__, status);
162 bta_hf_client_sco_co_in_data (p_data, status);
165 #endif /* BTM_SCO_HCI_INCLUDED */
167 /*******************************************************************************
169 ** Function bta_hf_client_sco_conn_rsp
171 ** Description Process the SCO connection request
176 *******************************************************************************/
177 static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
179 tBTM_ESCO_PARAMS resp;
180 UINT8 hci_status = HCI_SUCCESS;
181 #if (BTM_SCO_HCI_INCLUDED == TRUE )
182 tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM};
183 UINT32 pcm_sample_rate;
185 APPL_TRACE_DEBUG("%s", __FUNCTION__);
187 if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST) {
188 if (p_data->link_type == BTM_LINK_TYPE_SCO) {
189 resp = bta_hf_client_esco_params[0];
191 resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec];
194 /* tell sys to stop av if any */
195 bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
197 #if (BTM_SCO_HCI_INCLUDED == TRUE )
198 bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_SETUP, 0);
199 pcm_sample_rate = BTA_HFP_SCO_SAMP_RATE_8K;
201 /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
202 BTM_ConfigScoPath(bta_hf_client_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, 0),
203 bta_hf_client_sco_read_cback, NULL, TRUE);
206 hci_status = HCI_ERR_HOST_REJECT_DEVICE;
209 BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
212 #if (BTM_SCO_HCI_INCLUDED == TRUE )
213 /*******************************************************************************
215 ** Function bta_ag_ci_sco_data
217 ** Description Process the SCO data ready callin event
222 *******************************************************************************/
223 void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data)
226 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CI_DATA_E);
229 /*******************************************************************************
231 ** Function bta_hf_client_sco_connreq_cback
233 ** Description BTM eSCO connection requests and eSCO change requests
234 ** Only the connection requests are processed by BTA.
238 *******************************************************************************/
239 static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
241 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, event);
243 if (event != BTM_ESCO_CONN_REQ_EVT) {
247 /* TODO check remote bdaddr, should allow connect only from device with
250 bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx;
252 bta_hf_client_sco_conn_rsp(&p_data->conn_evt);
254 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
257 /*******************************************************************************
259 ** Function bta_hf_client_sco_conn_cback
261 ** Description BTM SCO connection callback.
266 *******************************************************************************/
267 static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
271 tBTM_ESCO_DATA sco_data;
273 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
275 rem_bd = BTM_ReadScoBdAddr(sco_idx);
276 BTM_ReadEScoLinkParms (sco_idx, &sco_data);
278 if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 &&
279 bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) {
281 bta_hf_client_cb.scb.link_type = sco_data.link_type;
282 bta_hf_client_cb.scb.tx_interval = sco_data.tx_interval;
283 bta_hf_client_cb.scb.retrans_window = sco_data.retrans_window;
284 bta_hf_client_cb.scb.air_mode = sco_data.air_mode;
285 if (sco_data.air_mode == BTM_SCO_AIR_MODE_CVSD) {
286 bta_hf_client_cb.scb.out_pkt_len = sco_data.tx_pkt_len * 2;
287 bta_hf_client_cb.scb.in_pkt_len = sco_data.rx_pkt_len * 2;
289 bta_hf_client_cb.scb.out_pkt_len = sco_data.tx_pkt_len;
290 bta_hf_client_cb.scb.in_pkt_len = sco_data.rx_pkt_len;
293 if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
294 p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT;
295 p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;
296 bta_sys_sendmsg(p_buf);
299 /* no match found; disconnect sco, init sco variables */
301 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
302 BTM_RemoveSco(sco_idx);
306 /*******************************************************************************
308 ** Function bta_hf_client_sco_disc_cback
310 ** Description BTM SCO disconnection callback.
315 *******************************************************************************/
316 static void bta_hf_client_sco_disc_cback(UINT16 sco_idx)
320 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
322 if (bta_hf_client_cb.scb.sco_idx == sco_idx) {
323 #if (BTM_SCO_HCI_INCLUDED == TRUE )
324 tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, TRUE);
325 APPL_TRACE_DEBUG("%s close config status = %d", __FUNCTION__, status);
327 /* SCO clean up here */
328 bta_hf_client_sco_co_close();
330 if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
331 p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT;
332 p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;;
333 bta_sys_sendmsg(p_buf);
338 /*******************************************************************************
340 ** Function bta_hf_client_create_sco
347 *******************************************************************************/
348 static void bta_hf_client_sco_create(BOOLEAN is_orig)
351 UINT8 *p_bd_addr = NULL;
352 tBTM_ESCO_PARAMS params;
353 #if (BTM_SCO_HCI_INCLUDED == TRUE )
354 tBTM_SCO_ROUTE_TYPE sco_route;
355 tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM};
356 UINT32 pcm_sample_rate;
358 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig);
360 /* Make sure this sco handle is not already in use */
361 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) {
362 APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__,
363 bta_hf_client_cb.scb.sco_idx);
367 params = bta_hf_client_esco_params[1];
369 /* if initiating set current scb and peer bd addr */
371 /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
372 if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only) {
373 BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, ¶ms);
374 /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
375 if ((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
376 || !((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO)) {
377 bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
378 APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
381 if (bta_hf_client_cb.scb.retry_with_sco_only) {
382 APPL_TRACE_API("retrying with SCO only");
384 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
386 BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms);
389 /* tell sys to stop av if any */
390 bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
392 #if (BTM_SCO_HCI_INCLUDED == TRUE )
393 /* Allow any platform specific pre-SCO set up to take place */
394 bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_SETUP, 0);
396 pcm_sample_rate = BTA_HFP_SCO_SAMP_RATE_8K;
397 sco_route = bta_hf_client_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, 0);
399 /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
400 BTM_ConfigScoPath(sco_route, bta_hf_client_sco_read_cback, NULL, TRUE);
404 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
407 p_bd_addr = bta_hf_client_cb.scb.peer_addr;
409 status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
410 &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback,
411 bta_hf_client_sco_disc_cback);
412 if (status == BTM_CMD_STARTED && !is_orig) {
413 if (!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback)) {
414 APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__);
418 APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
419 __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx,
420 status, params.packet_types);
424 /*******************************************************************************
426 ** Function bta_hf_client_sco_event
428 ** Description Handle SCO events
433 *******************************************************************************/
434 static void bta_hf_client_sco_event(UINT8 event)
436 APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__,
437 bta_hf_client_cb.scb.sco_state, event);
439 #if (BTM_SCO_HCI_INCLUDED == TRUE )
440 tBTA_HF_CLIENT_SCB *p_scb = &bta_hf_client_cb.scb;
444 #if (BTM_SCO_HCI_INCLUDED == TRUE )
445 if (event == BTA_HF_CLIENT_SCO_CI_DATA_E) {
446 UINT16 pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE;
447 UINT16 len_to_send = 0;
450 p_buf = osi_calloc(sizeof(BT_HDR) + pkt_offset + p_scb->out_pkt_len);
452 APPL_TRACE_WARNING("%s, no mem", __FUNCTION__);
456 p_buf->offset = pkt_offset;
457 len_to_send = bta_hf_client_sco_co_out_data(p_buf->data + pkt_offset);
458 p_buf->len = len_to_send;
459 if (len_to_send == p_scb->out_pkt_len) {
460 // expect to get the exact size of data from upper layer
461 if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) {
462 tBTM_STATUS write_stat = BTM_WriteScoData(p_scb->sco_idx, p_buf);
463 if (write_stat != BTM_SUCCESS) {
479 switch (bta_hf_client_cb.scb.sco_state) {
480 case BTA_HF_CLIENT_SCO_SHUTDOWN_ST:
482 case BTA_HF_CLIENT_SCO_LISTEN_E:
483 /* create sco listen connection */
484 bta_hf_client_sco_create(FALSE);
485 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
489 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event);
494 case BTA_HF_CLIENT_SCO_LISTEN_ST:
496 case BTA_HF_CLIENT_SCO_LISTEN_E:
497 /* create sco listen connection (Additional channel) */
498 bta_hf_client_sco_create(FALSE);
501 case BTA_HF_CLIENT_SCO_OPEN_E:
502 /* remove listening connection */
503 bta_hf_client_sco_remove(FALSE);
505 /* create sco connection to peer */
506 bta_hf_client_sco_create(TRUE);
507 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
510 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
511 /* remove listening connection */
512 bta_hf_client_sco_remove(FALSE);
514 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
517 case BTA_HF_CLIENT_SCO_CLOSE_E:
518 /* remove listening connection */
519 /* Ignore the event. We need to keep listening SCO for the active SLC */
520 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
523 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
524 /* sco failed; create sco listen connection */
525 bta_hf_client_sco_create(FALSE);
526 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
530 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
535 case BTA_HF_CLIENT_SCO_OPENING_ST:
537 case BTA_HF_CLIENT_SCO_CLOSE_E:
538 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST;
541 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
542 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
545 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
546 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST;
549 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
550 /* sco failed; create sco listen connection */
551 bta_hf_client_sco_create(FALSE);
552 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
556 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event);
561 case BTA_HF_CLIENT_SCO_OPEN_CL_ST:
563 case BTA_HF_CLIENT_SCO_OPEN_E:
564 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
567 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
568 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
571 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
572 /* close sco connection */
573 bta_hf_client_sco_remove(TRUE);
575 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
578 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
579 /* sco failed; create sco listen connection */
581 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
585 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event);
590 case BTA_HF_CLIENT_SCO_OPEN_ST:
592 case BTA_HF_CLIENT_SCO_CLOSE_E:
593 /* close sco connection if active */
594 if (bta_hf_client_sco_remove(TRUE)) {
595 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
599 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
600 /* remove all listening connections */
601 bta_hf_client_sco_remove(FALSE);
603 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
606 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
607 /* peer closed sco; create sco listen connection */
608 bta_hf_client_sco_create(FALSE);
609 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
613 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event);
618 case BTA_HF_CLIENT_SCO_CLOSING_ST:
620 case BTA_HF_CLIENT_SCO_OPEN_E:
621 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST;
624 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
625 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
628 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
629 /* peer closed sco; create sco listen connection */
630 bta_hf_client_sco_create(FALSE);
632 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
636 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event);
641 case BTA_HF_CLIENT_SCO_CLOSE_OP_ST:
643 case BTA_HF_CLIENT_SCO_CLOSE_E:
644 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
647 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
648 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
651 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
652 /* open sco connection */
653 bta_hf_client_sco_create(TRUE);
654 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
658 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event);
663 case BTA_HF_CLIENT_SCO_SHUTTING_ST:
665 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
666 /* close sco connection; wait for conn close event */
667 bta_hf_client_sco_remove(TRUE);
670 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
671 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
674 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
675 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
679 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event);
689 /*******************************************************************************
691 ** Function bta_hf_client_sco_listen
693 ** Description Initialize SCO listener
698 *******************************************************************************/
699 void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data)
703 APPL_TRACE_DEBUG("%s", __FUNCTION__);
705 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E);
708 /*******************************************************************************
710 ** Function bta_hf_client_sco_shutdown
717 *******************************************************************************/
718 void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data)
722 APPL_TRACE_DEBUG("%s", __FUNCTION__);
724 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E);
727 /*******************************************************************************
729 ** Function bta_hf_client_sco_conn_open
736 *******************************************************************************/
737 void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data)
741 APPL_TRACE_DEBUG("%s", __FUNCTION__);
743 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E);
745 bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
746 #if (BTM_SCO_HCI_INCLUDED == TRUE)
747 bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_ON, 0);
748 /* open SCO codec if SCO is routed through transport */
749 bta_hf_client_sco_co_open(bta_hf_client_cb.scb.sco_idx, bta_hf_client_cb.scb.air_mode,
750 bta_hf_client_cb.scb.out_pkt_len, BTA_HF_CLIENT_CI_SCO_DATA_EVT);
753 if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {
754 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT);
756 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT);
759 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
762 /*******************************************************************************
764 ** Function bta_hf_client_sco_conn_close
771 *******************************************************************************/
772 void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data)
774 APPL_TRACE_DEBUG("%s", __FUNCTION__);
776 /* clear current scb */
777 bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
779 /* retry_with_sco_only, will be set only when initiator
780 ** and HFClient is first trying to establish an eSCO connection */
781 if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn) {
782 bta_hf_client_sco_create(TRUE);
784 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E);
786 bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
788 bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
790 /* call app callback */
791 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
793 if (bta_hf_client_cb.scb.sco_close_rfc == TRUE) {
794 bta_hf_client_cb.scb.sco_close_rfc = FALSE;
795 bta_hf_client_rfc_do_close(p_data);
798 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
801 /*******************************************************************************
803 ** Function bta_hf_client_sco_open
810 *******************************************************************************/
811 void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data)
815 APPL_TRACE_DEBUG("%s", __FUNCTION__);
817 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E);
820 /*******************************************************************************
822 ** Function bta_hf_client_sco_close
829 *******************************************************************************/
830 void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data)
834 APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx);
836 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) {
837 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E);
841 #endif /* #if (BTA_HF_INCLUDED == TRUE) */