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"
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)
30 static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
33 .rx_bw = BTM_64KBITS_RATE,
34 .tx_bw = BTM_64KBITS_RATE,
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,
46 .rx_bw = BTM_64KBITS_RATE,
47 .tx_bw = BTM_64KBITS_RATE,
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,
58 .rx_bw = BTM_64KBITS_RATE,
59 .tx_bw = BTM_64KBITS_RATE,
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,
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 */
81 /*******************************************************************************
83 ** Function bta_hf_client_remove_sco
85 ** Description Removes the specified SCO from the system.
86 ** If only_active is TRUE, then SCO is only removed if connected
88 ** Returns BOOLEAN - TRUE if Sco removal was started
90 *******************************************************************************/
91 static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active)
93 BOOLEAN removed_started = FALSE;
96 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, only_active);
98 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
100 status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx);
102 APPL_TRACE_DEBUG("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status);
104 if (status == BTM_CMD_STARTED)
106 removed_started = TRUE;
108 /* If no connection reset the sco handle */
109 else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) )
111 bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
114 return removed_started;
117 /*******************************************************************************
119 ** Function bta_hf_client_cback_sco
121 ** Description Call application callback function with SCO event.
126 *******************************************************************************/
127 void bta_hf_client_cback_sco(UINT8 event)
131 memset(&evt, 0, sizeof(evt));
134 (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT *) &evt);
137 /*******************************************************************************
139 ** Function bta_hf_client_sco_conn_rsp
141 ** Description Process the SCO connection request
146 *******************************************************************************/
147 static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
149 tBTM_ESCO_PARAMS resp;
150 UINT8 hci_status = HCI_SUCCESS;
152 APPL_TRACE_DEBUG("%s", __FUNCTION__);
154 if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST)
156 if (p_data->link_type == BTM_LINK_TYPE_SCO)
158 resp = bta_hf_client_esco_params[0];
162 resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec];
165 /* tell sys to stop av if any */
166 bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
170 hci_status = HCI_ERR_HOST_REJECT_DEVICE;
173 BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
176 /*******************************************************************************
178 ** Function bta_hf_client_sco_connreq_cback
180 ** Description BTM eSCO connection requests and eSCO change requests
181 ** Only the connection requests are processed by BTA.
185 *******************************************************************************/
186 static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
188 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, event);
190 if (event != BTM_ESCO_CONN_REQ_EVT)
195 /* TODO check remote bdaddr, should allow connect only from device with
198 bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx;
200 bta_hf_client_sco_conn_rsp(&p_data->conn_evt);
202 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
205 /*******************************************************************************
207 ** Function bta_hf_client_sco_conn_cback
209 ** Description BTM SCO connection callback.
214 *******************************************************************************/
215 static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
220 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
222 rem_bd = BTM_ReadScoBdAddr(sco_idx);
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)
227 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
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);
234 /* no match found; disconnect sco, init sco variables */
237 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
238 BTM_RemoveSco(sco_idx);
242 /*******************************************************************************
244 ** Function bta_hf_client_sco_disc_cback
246 ** Description BTM SCO disconnection callback.
251 *******************************************************************************/
252 static void bta_hf_client_sco_disc_cback(UINT16 sco_idx)
256 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
258 if (bta_hf_client_cb.scb.sco_idx == sco_idx)
260 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
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);
269 /*******************************************************************************
271 ** Function bta_hf_client_create_sco
278 *******************************************************************************/
279 static void bta_hf_client_sco_create(BOOLEAN is_orig)
282 UINT8 *p_bd_addr = NULL;
283 tBTM_ESCO_PARAMS params;
285 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig);
287 /* Make sure this sco handle is not already in use */
288 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
290 APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__,
291 bta_hf_client_cb.scb.sco_idx);
295 params = bta_hf_client_esco_params[1];
297 /* if initiating set current scb and peer bd addr */
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)
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))
308 bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
309 APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
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;
318 BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms);
321 /* tell sys to stop av if any */
322 bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
326 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
329 p_bd_addr = bta_hf_client_cb.scb.peer_addr;
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)
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__);
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);
346 /*******************************************************************************
348 ** Function bta_hf_client_sco_event
350 ** Description Handle SCO events
355 *******************************************************************************/
356 static void bta_hf_client_sco_event(UINT8 event)
358 APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__,
359 bta_hf_client_cb.scb.sco_state, event);
361 switch (bta_hf_client_cb.scb.sco_state)
363 case BTA_HF_CLIENT_SCO_SHUTDOWN_ST:
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;
373 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event);
378 case BTA_HF_CLIENT_SCO_LISTEN_ST:
381 case BTA_HF_CLIENT_SCO_LISTEN_E:
382 /* create sco listen connection (Additional channel) */
383 bta_hf_client_sco_create(FALSE);
386 case BTA_HF_CLIENT_SCO_OPEN_E:
387 /* remove listening connection */
388 bta_hf_client_sco_remove(FALSE);
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;
395 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
396 /* remove listening connection */
397 bta_hf_client_sco_remove(FALSE);
399 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
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);
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;
415 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
420 case BTA_HF_CLIENT_SCO_OPENING_ST:
423 case BTA_HF_CLIENT_SCO_CLOSE_E:
424 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST;
427 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
428 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
431 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
432 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST;
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;
442 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event);
447 case BTA_HF_CLIENT_SCO_OPEN_CL_ST:
450 case BTA_HF_CLIENT_SCO_OPEN_E:
451 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
454 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
455 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
458 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
459 /* close sco connection */
460 bta_hf_client_sco_remove(TRUE);
462 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
465 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
466 /* sco failed; create sco listen connection */
468 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
472 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event);
477 case BTA_HF_CLIENT_SCO_OPEN_ST:
480 case BTA_HF_CLIENT_SCO_CLOSE_E:
481 /* close sco connection if active */
482 if (bta_hf_client_sco_remove(TRUE))
484 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
488 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
489 /* remove all listening connections */
490 bta_hf_client_sco_remove(FALSE);
492 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
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;
502 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event);
507 case BTA_HF_CLIENT_SCO_CLOSING_ST:
510 case BTA_HF_CLIENT_SCO_OPEN_E:
511 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST;
514 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
515 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
518 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
519 /* peer closed sco; create sco listen connection */
520 bta_hf_client_sco_create(FALSE);
522 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
526 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event);
531 case BTA_HF_CLIENT_SCO_CLOSE_OP_ST:
534 case BTA_HF_CLIENT_SCO_CLOSE_E:
535 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
538 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
539 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
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;
549 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event);
554 case BTA_HF_CLIENT_SCO_SHUTTING_ST:
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);
562 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
563 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
566 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
567 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
571 APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event);
581 /*******************************************************************************
583 ** Function bta_hf_client_sco_listen
585 ** Description Initialize SCO listener
590 *******************************************************************************/
591 void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data)
595 APPL_TRACE_DEBUG("%s", __FUNCTION__);
597 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E);
600 /*******************************************************************************
602 ** Function bta_hf_client_sco_shutdown
609 *******************************************************************************/
610 void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data)
614 APPL_TRACE_DEBUG("%s", __FUNCTION__);
616 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E);
619 /*******************************************************************************
621 ** Function bta_hf_client_sco_conn_open
628 *******************************************************************************/
629 void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data)
633 APPL_TRACE_DEBUG("%s", __FUNCTION__);
635 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E);
637 bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
639 if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC)
641 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT);
645 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT);
648 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
651 /*******************************************************************************
653 ** Function bta_hf_client_sco_conn_close
660 *******************************************************************************/
661 void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data)
663 APPL_TRACE_DEBUG("%s", __FUNCTION__);
665 /* clear current scb */
666 bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
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)
672 bta_hf_client_sco_create(TRUE);
676 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E);
678 bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
680 bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
682 /* call app callback */
683 bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
685 if (bta_hf_client_cb.scb.sco_close_rfc == TRUE)
687 bta_hf_client_cb.scb.sco_close_rfc = FALSE;
688 bta_hf_client_rfc_do_close(p_data);
691 bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
694 /*******************************************************************************
696 ** Function bta_hf_client_sco_open
703 *******************************************************************************/
704 void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data)
708 APPL_TRACE_DEBUG("%s", __FUNCTION__);
710 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E);
713 /*******************************************************************************
715 ** Function bta_hf_client_sco_close
722 *******************************************************************************/
723 void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data)
727 APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx);
729 if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
731 bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E);