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 "bta/bta_hf_client_api.h"
22 #include "common/bt_trace.h"
23 #include <string.h>
24 #include "common/bt_defs.h"
25 #include "common/bt_target.h"
26 #include "osi/allocator.h"
27 #if (BTM_SCO_HCI_INCLUDED == TRUE )
28 #include "bta/bta_hf_client_co.h"
29 #include "hci/hci_audio.h"
30 #endif
31 
32 #if BT_HF_CLIENT_BQB_INCLUDED
33 static BOOLEAN s_bta_hf_client_bqb_esco_s1_flag = false;
34 #endif /* BT_HF_CLIENT_BQB_INCLUDED */
35 
36 #if (BTA_HF_INCLUDED == TRUE)
37 #define BTA_HF_CLIENT_NO_EDR_ESCO  (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
38                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
39                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
40                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
41 
42 #define BTA_HF_CLIENT_SCO_PARAM_IDX_CVSD      0   /* SCO setting for CVSD     */
43 #define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3  1   /* eSCO setting for CVSD S3 */
44 #define BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2  2   /* eSCO setting for mSBC T2 */
45 #define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4  3   /* eSCO setting for CVSD S4 */
46 #define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S1  4   /* eSCO setting for CVSD S1 */
47 
48 static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
49     /* SCO CVSD */
50     {
51         .rx_bw = BTM_64KBITS_RATE,
52         .tx_bw = BTM_64KBITS_RATE,
53         .max_latency = 10,
54         .voice_contfmt = BTM_VOICE_SETTING_CVSD,
55         .packet_types = (BTM_SCO_PKT_TYPES_MASK_HV1 |
56         BTM_SCO_PKT_TYPES_MASK_HV3 |
57         BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
58         BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
59         BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
60         BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
61         .retrans_effort = BTM_ESCO_RETRANS_OFF,
62     },
63     /* ESCO CVSD */
64     {
65         .rx_bw = BTM_64KBITS_RATE,
66         .tx_bw = BTM_64KBITS_RATE,
67         .max_latency = 10,
68         .voice_contfmt = BTM_VOICE_SETTING_CVSD,
69         /* Packet Types : 2-EV3 */
70         .packet_types = (BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
71         BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
72         BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
73         .retrans_effort = BTM_ESCO_RETRANS_POWER,
74     },
75     /* ESCO mSBC */
76     {
77         .rx_bw = BTM_64KBITS_RATE,
78         .tx_bw = BTM_64KBITS_RATE,
79         .max_latency = 13,
80         .voice_contfmt = BTM_VOICE_SETTING_TRANS,
81         /* Packet Types : 2-EV3 */
82         .packet_types = (BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
83         BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
84         BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
85         .retrans_effort = BTM_ESCO_RETRANS_QUALITY,
86     },
87     /* HFP 1.7+ */
88     /* ESCO CVSD S4 */
89     {
90         .rx_bw = BTM_64KBITS_RATE,
91         .tx_bw = BTM_64KBITS_RATE,
92         .max_latency = 12,
93         .voice_contfmt = BTM_VOICE_SETTING_CVSD,
94         /* Packet Types : 2-EV3 */
95         .packet_types = (BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
96         BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
97         BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
98         .retrans_effort = BTM_ESCO_RETRANS_QUALITY,
99     },
100     /* ESCO CVSD S1 */
101 #if BT_HF_CLIENT_BQB_INCLUDED
102     {
103         .rx_bw = BTM_64KBITS_RATE,
104         .tx_bw = BTM_64KBITS_RATE,
105         .max_latency = 7,
106         .voice_contfmt = BTM_VOICE_SETTING_CVSD,
107         /* Packet Types : EV3 */
108         .packet_types = (HCI_ESCO_PKT_TYPES_MASK_EV3 |
109         BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
110         BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
111         BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
112         BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
113         .retrans_effort = BTM_ESCO_RETRANS_POWER,
114     }
115 #endif /* BT_HF_CLIENT_BQB_INCLUDED */
116 };
117 
118 enum {
119     BTA_HF_CLIENT_SCO_LISTEN_E,
120     BTA_HF_CLIENT_SCO_OPEN_E,          /* open request */
121     BTA_HF_CLIENT_SCO_CLOSE_E,         /* close request */
122     BTA_HF_CLIENT_SCO_SHUTDOWN_E,      /* shutdown request */
123     BTA_HF_CLIENT_SCO_CONN_OPEN_E,     /* sco opened */
124     BTA_HF_CLIENT_SCO_CONN_CLOSE_E,    /* sco closed */
125 #if (BTM_SCO_HCI_INCLUDED == TRUE )
126     BTA_HF_CLIENT_SCO_CI_DATA_E,       /* sco data ready */
127 #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */
128 };
129 
130 /*******************************************************************************
131 **
132 ** Function     bta_hf_client_bqb_esco_s1_ctrl
133 **
134 ** Description  Control the usage of CVSD eSCO S1 parameter for BQB test
135 **
136 ** Returns      void
137 **
138 *******************************************************************************/
139 #if BT_HF_CLIENT_BQB_INCLUDED
bta_hf_client_bqb_esco_s1_ctrl(BOOLEAN enable)140 void bta_hf_client_bqb_esco_s1_ctrl(BOOLEAN enable)
141 {
142     s_bta_hf_client_bqb_esco_s1_flag = enable;
143 }
144 #endif /* BT_HF_CLIENT_BQB_INCLUDED */
145 
146 static void bta_hf_client_sco_event(UINT8 event);
147 /*******************************************************************************
148 **
149 ** Function         bta_hf_client_remove_sco
150 **
151 ** Description      Removes the specified SCO from the system.
152 **                  If only_active is TRUE, then SCO is only removed if connected
153 **
154 ** Returns          BOOLEAN   - TRUE if Sco removal was started
155 **
156 *******************************************************************************/
bta_hf_client_sco_remove(BOOLEAN only_active)157 static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active)
158 {
159     BOOLEAN     removed_started = FALSE;
160     tBTM_STATUS status;
161 
162     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, only_active);
163 
164     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) {
165         status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx);
166 
167         APPL_TRACE_DEBUG("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status);
168 
169         if (status == BTM_CMD_STARTED) {
170             removed_started = TRUE;
171         }
172         /* If no connection reset the sco handle */
173         else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) ) {
174             bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
175         }
176     }
177     return removed_started;
178 }
179 
180 /*******************************************************************************
181 **
182 ** Function         bta_hf_client_cback_sco
183 **
184 ** Description      Call application callback function with SCO event.
185 **
186 **
187 ** Returns          void
188 **
189 *******************************************************************************/
bta_hf_client_cback_sco(UINT8 event)190 void bta_hf_client_cback_sco(UINT8 event)
191 {
192     tBTA_HF_CLIENT_HDR    evt;
193 
194     memset(&evt, 0, sizeof(evt));
195     evt.sync_conn_handle = BTM_ReadScoHandle(bta_hf_client_cb.scb.sco_idx);
196 
197     /* call app cback */
198     (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT_HDR *) &evt);
199 }
200 
201 #if (BTM_SCO_HCI_INCLUDED == TRUE )
202 /*******************************************************************************
203 **
204 ** Function         bta_hf_client_sco_read_cback
205 **
206 ** Description      Callback function is the callback function for incoming
207 **                  SCO data over HCI.
208 **
209 ** Returns          void
210 **
211 *******************************************************************************/
bta_hf_client_sco_read_cback(UINT16 sco_idx,BT_HDR * p_data,tBTM_SCO_DATA_FLAG status)212 static void bta_hf_client_sco_read_cback (UINT16 sco_idx, BT_HDR *p_data, tBTM_SCO_DATA_FLAG status)
213 {
214     if (status != BTM_SCO_DATA_CORRECT)
215     {
216         APPL_TRACE_DEBUG("%s: status(%d)", __FUNCTION__, status);
217     }
218 
219     bta_hf_client_sco_co_in_data (p_data, status);
220     osi_free(p_data);
221 }
222 #endif /* BTM_SCO_HCI_INCLUDED */
223 
224 /*******************************************************************************
225 **
226 ** Function         bta_hf_client_sco_conn_rsp
227 **
228 ** Description      Process the SCO connection request
229 **
230 **
231 ** Returns          void
232 **
233 *******************************************************************************/
bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA * p_data)234 static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
235 {
236     tBTM_ESCO_PARAMS    resp;
237     UINT8               hci_status = HCI_SUCCESS;
238     UINT8            index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3;
239 #if (BTM_SCO_HCI_INCLUDED == TRUE )
240     tBTA_HFP_CODEC_INFO     codec_info = {BTA_HFP_SCO_CODEC_PCM};
241     UINT32              pcm_sample_rate;
242 #endif
243 
244     APPL_TRACE_DEBUG("%s: negotiated codec = %d", __FUNCTION__, bta_hf_client_cb.scb.negotiated_codec);
245 
246     if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST) {
247         if (p_data->link_type == BTM_LINK_TYPE_SCO) {
248             index = BTA_HF_CLIENT_SCO_PARAM_IDX_CVSD;
249         } else {
250             if ((bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_CVSD) &&
251                  (bta_hf_client_cb.scb.features && BTA_HF_CLIENT_FEAT_ESCO_S4) &&
252                  (bta_hf_client_cb.scb.peer_features && BTA_HF_CLIENT_PEER_ESCO_S4)) {
253                 index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4;
254 #if BT_HF_CLIENT_BQB_INCLUDED
255                 if (s_bta_hf_client_bqb_esco_s1_flag == true) {
256                     index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S1;
257                 }
258 #endif /* BT_HF_CLIENT_BQB_INCLUDED */
259             } else if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {
260                 index = BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2;
261             }
262         }
263         resp = bta_hf_client_esco_params[index];
264 
265         /* tell sys to stop av if any */
266         bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
267 
268 #if (BTM_SCO_HCI_INCLUDED == TRUE )
269         bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_SETUP, 0);
270         pcm_sample_rate = BTA_HFP_SCO_SAMP_RATE_8K;
271 
272         /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
273         BTM_ConfigScoPath(bta_hf_client_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, 0),
274             bta_hf_client_sco_read_cback, NULL, TRUE);
275 #endif
276     } else {
277         hci_status = HCI_ERR_HOST_REJECT_DEVICE;
278     }
279 
280     BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
281 }
282 
283 #if (BTM_SCO_HCI_INCLUDED == TRUE)
284 /*******************************************************************************
285 **
286 ** Function         bta_hf_client_pkt_stat_nums
287 **
288 ** Description      Get the packet status number
289 **
290 **
291 ** Returns          void
292 **
293 *******************************************************************************/
bta_hf_client_pkt_stat_nums(tBTA_HF_CLIENT_DATA * p_data)294 void bta_hf_client_pkt_stat_nums(tBTA_HF_CLIENT_DATA *p_data)
295 {
296     tBTA_SCO_PKT_STAT_NUMS pkt_stat_nums;
297     uint16_t sync_conn_handle = p_data->pkt_stat.sync_conn_handle;
298     BTM_PktStatNumsGet(sync_conn_handle, (tBTM_SCO_PKT_STAT_NUMS *) &pkt_stat_nums);
299 
300     /* call app cback */
301     if (bta_hf_client_cb.p_cback) {
302         (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_PKT_STAT_NUMS_GET_EVT, (void*) &pkt_stat_nums);
303     }
304 }
305 
306 /*******************************************************************************
307 **
308 ** Function         bta_hf_client_ci_sco_data
309 **
310 ** Description      Process the SCO data ready callin event
311 **
312 **
313 ** Returns          void
314 **
315 *******************************************************************************/
bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA * p_data)316 void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data)
317 {
318     UNUSED(p_data);
319     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CI_DATA_E);
320 }
321 #endif
322 
323 /*******************************************************************************
324 **
325 ** Function         bta_hf_client_sco_connreq_cback
326 **
327 ** Description      BTM eSCO connection requests and eSCO change requests
328 **                  Only the connection requests are processed by BTA.
329 **
330 ** Returns          void
331 **
332 *******************************************************************************/
bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event,tBTM_ESCO_EVT_DATA * p_data)333 static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
334 {
335     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, event);
336 
337     if (event != BTM_ESCO_CONN_REQ_EVT) {
338         return;
339     }
340 
341     /* TODO check remote bdaddr, should allow connect only from device with
342      * active SLC  */
343 
344     bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx;
345 
346     bta_hf_client_sco_conn_rsp(&p_data->conn_evt);
347 
348     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
349 }
350 
351 /*******************************************************************************
352 **
353 ** Function         bta_hf_client_sco_conn_cback
354 **
355 ** Description      BTM SCO connection callback.
356 **
357 **
358 ** Returns          void
359 **
360 *******************************************************************************/
bta_hf_client_sco_conn_cback(UINT16 sco_idx)361 static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
362 {
363     BT_HDR  *p_buf;
364     UINT8 *rem_bd;
365     tBTM_ESCO_DATA sco_data;
366 
367     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
368 
369     rem_bd = BTM_ReadScoBdAddr(sco_idx);
370     BTM_ReadEScoLinkParms (sco_idx, &sco_data);
371 
372     if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 &&
373             bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) {
374 
375         bta_hf_client_cb.scb.link_type = sco_data.link_type;
376         bta_hf_client_cb.scb.tx_interval = sco_data.tx_interval;
377         bta_hf_client_cb.scb.retrans_window = sco_data.retrans_window;
378         bta_hf_client_cb.scb.air_mode = sco_data.air_mode;
379         if (sco_data.air_mode == BTM_SCO_AIR_MODE_CVSD) {
380             bta_hf_client_cb.scb.out_pkt_len = sco_data.tx_pkt_len * 2;
381             bta_hf_client_cb.scb.in_pkt_len = sco_data.rx_pkt_len * 2;
382         } else {
383             bta_hf_client_cb.scb.out_pkt_len = sco_data.tx_pkt_len;
384             bta_hf_client_cb.scb.in_pkt_len = sco_data.rx_pkt_len;
385         }
386 
387         if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
388             p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT;
389             p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;
390             bta_sys_sendmsg(p_buf);
391         }
392     }
393     /* no match found; disconnect sco, init sco variables */
394     else {
395         bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
396         BTM_RemoveSco(sco_idx);
397     }
398 }
399 
400 /*******************************************************************************
401 **
402 ** Function         bta_hf_client_sco_disc_cback
403 **
404 ** Description      BTM SCO disconnection callback.
405 **
406 **
407 ** Returns          void
408 **
409 *******************************************************************************/
bta_hf_client_sco_disc_cback(UINT16 sco_idx)410 static void bta_hf_client_sco_disc_cback(UINT16 sco_idx)
411 {
412     BT_HDR  *p_buf;
413 
414     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
415 
416     if (bta_hf_client_cb.scb.sco_idx == sco_idx) {
417 #if (BTM_SCO_HCI_INCLUDED == TRUE )
418         tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, TRUE);
419         APPL_TRACE_DEBUG("%s close config status = %d", __FUNCTION__, status);
420         UNUSED(status);
421         /* SCO clean up here */
422         bta_hf_client_sco_co_close();
423 #endif
424         if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
425             p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT;
426             p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;;
427             bta_sys_sendmsg(p_buf);
428         }
429     }
430 }
431 
432 /*******************************************************************************
433 **
434 ** Function         bta_hf_client_sco_create
435 **
436 ** Description
437 **
438 **
439 ** Returns          void
440 **
441 *******************************************************************************/
bta_hf_client_sco_create(BOOLEAN is_orig)442 static void bta_hf_client_sco_create(BOOLEAN is_orig)
443 {
444     tBTM_STATUS       status;
445     UINT8            *p_bd_addr = NULL;
446     tBTM_ESCO_PARAMS params;
447     UINT8            index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3;
448 #if (BTM_SCO_HCI_INCLUDED == TRUE )
449     tBTM_SCO_ROUTE_TYPE sco_route;
450     tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM};
451     UINT32              pcm_sample_rate;
452 #endif
453     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig);
454 
455     /* Make sure this sco handle is not already in use */
456     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) {
457         APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__,
458                            bta_hf_client_cb.scb.sco_idx);
459         return;
460     }
461 
462     if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_CVSD) {
463         if ((bta_hf_client_cb.scb.features && BTA_HF_CLIENT_FEAT_ESCO_S4) &&
464                 (bta_hf_client_cb.scb.peer_features && BTA_HF_CLIENT_PEER_ESCO_S4)) {
465             index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4;
466         }
467     } else if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {
468         index = BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2;
469     }
470     params = bta_hf_client_esco_params[index];
471 
472     /* if initiating set current scb and peer bd addr */
473     if (is_orig) {
474         /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
475         if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only) {
476             BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &params);
477             /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
478             if ((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
479                     || !((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO)) {
480                 bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
481                 APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
482             }
483         } else {
484             if (bta_hf_client_cb.scb.retry_with_sco_only) {
485                 APPL_TRACE_API("retrying with SCO only");
486             }
487             bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
488 
489             BTM_SetEScoMode(BTM_LINK_TYPE_SCO, &params);
490         }
491 
492         /* tell sys to stop av if any */
493         bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
494 
495 #if (BTM_SCO_HCI_INCLUDED == TRUE )
496         /* Allow any platform specific pre-SCO set up to take place */
497         bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_SETUP, 0);
498 
499         pcm_sample_rate = BTA_HFP_SCO_SAMP_RATE_8K;
500         sco_route = bta_hf_client_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, 0);
501 
502         /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
503         BTM_ConfigScoPath(sco_route, bta_hf_client_sco_read_cback, NULL, TRUE);
504 #endif
505 
506     } else {
507         bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
508     }
509 
510     p_bd_addr = bta_hf_client_cb.scb.peer_addr;
511 
512     status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
513                            &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback,
514                            bta_hf_client_sco_disc_cback);
515     if (status == BTM_CMD_STARTED && !is_orig) {
516         if (!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback)) {
517             APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__);
518         }
519     }
520 
521     APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
522                    __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx,
523                    status, params.packet_types);
524 }
525 
526 
527 /*******************************************************************************
528 **
529 ** Function         bta_hf_client_sco_event
530 **
531 ** Description      Handle SCO events
532 **
533 **
534 ** Returns          void
535 **
536 *******************************************************************************/
bta_hf_client_sco_event(UINT8 event)537 static void bta_hf_client_sco_event(UINT8 event)
538 {
539     APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__,
540                      bta_hf_client_cb.scb.sco_state, event);
541 
542 #if (BTM_SCO_HCI_INCLUDED == TRUE )
543     tBTA_HF_CLIENT_SCB *p_scb = &bta_hf_client_cb.scb;
544     BT_HDR  *p_buf;
545 #endif
546 
547 #if (BTM_SCO_HCI_INCLUDED == TRUE )
548     if (event == BTA_HF_CLIENT_SCO_CI_DATA_E) {
549         UINT16 pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE;
550         UINT16 len_to_send = 0;
551         while (true)
552         {
553             p_buf = osi_calloc(sizeof(BT_HDR) + pkt_offset + p_scb->out_pkt_len);
554             if (!p_buf) {
555                 APPL_TRACE_WARNING("%s, no mem", __FUNCTION__);
556                 break;
557             }
558 
559             p_buf->offset = pkt_offset;
560             len_to_send = bta_hf_client_sco_co_out_data(p_buf->data + pkt_offset);
561             p_buf->len = len_to_send;
562             if (len_to_send == p_scb->out_pkt_len) {
563                 // expect to get the exact size of data from upper layer
564                 if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) {
565                     tBTM_STATUS write_stat = BTM_WriteScoData(p_scb->sco_idx, p_buf);
566                     if (write_stat != BTM_SUCCESS) {
567                         break;
568                     }
569                 } else {
570                     osi_free(p_buf);
571                 }
572             } else {
573                 osi_free(p_buf);
574                 break;
575             }
576         }
577 
578         return;
579     }
580 #endif
581 
582     switch (bta_hf_client_cb.scb.sco_state) {
583     case BTA_HF_CLIENT_SCO_SHUTDOWN_ST:
584         switch (event) {
585         case BTA_HF_CLIENT_SCO_LISTEN_E:
586             /* create sco listen connection */
587             bta_hf_client_sco_create(FALSE);
588             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
589             break;
590 
591         default:
592             APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event);
593             break;
594         }
595         break;
596 
597     case BTA_HF_CLIENT_SCO_LISTEN_ST:
598         switch (event) {
599         case BTA_HF_CLIENT_SCO_LISTEN_E:
600             /* create sco listen connection (Additional channel) */
601             bta_hf_client_sco_create(FALSE);
602             break;
603 
604         case BTA_HF_CLIENT_SCO_OPEN_E:
605             /* remove listening connection */
606             bta_hf_client_sco_remove(FALSE);
607 
608             /* create sco connection to peer */
609             bta_hf_client_sco_create(TRUE);
610             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
611             break;
612 
613         case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
614             /* remove listening connection */
615             bta_hf_client_sco_remove(FALSE);
616 
617             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
618             break;
619 
620         case BTA_HF_CLIENT_SCO_CLOSE_E:
621             /* remove listening connection */
622             /* Ignore the event. We need to keep listening SCO for the active SLC */
623             APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
624             break;
625 
626         case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
627             /* sco failed; create sco listen connection */
628             bta_hf_client_sco_create(FALSE);
629             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
630             break;
631 
632         default:
633             APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
634             break;
635         }
636         break;
637 
638     case BTA_HF_CLIENT_SCO_OPENING_ST:
639         switch (event) {
640         case BTA_HF_CLIENT_SCO_CLOSE_E:
641             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST;
642             break;
643 
644         case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
645             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
646             break;
647 
648         case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
649             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST;
650             break;
651 
652         case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
653             /* sco failed; create sco listen connection */
654             bta_hf_client_sco_create(FALSE);
655             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
656             break;
657 
658         default:
659             APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event);
660             break;
661         }
662         break;
663 
664     case BTA_HF_CLIENT_SCO_OPEN_CL_ST:
665         switch (event) {
666         case BTA_HF_CLIENT_SCO_OPEN_E:
667             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
668             break;
669 
670         case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
671             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
672             break;
673 
674         case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
675             /* close sco connection */
676             bta_hf_client_sco_remove(TRUE);
677 
678             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
679             break;
680 
681         case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
682             /* sco failed; create sco listen connection */
683 
684             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
685             break;
686 
687         default:
688             APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event);
689             break;
690         }
691         break;
692 
693     case BTA_HF_CLIENT_SCO_OPEN_ST:
694         switch (event) {
695         case BTA_HF_CLIENT_SCO_CLOSE_E:
696             /* close sco connection if active */
697             if (bta_hf_client_sco_remove(TRUE)) {
698                 bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
699             }
700             break;
701 
702         case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
703             /* remove all listening connections */
704             bta_hf_client_sco_remove(FALSE);
705 
706             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
707             break;
708 
709         case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
710             /* peer closed sco; create sco listen connection */
711             bta_hf_client_sco_create(FALSE);
712             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
713             break;
714 
715         default:
716             APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event);
717             break;
718         }
719         break;
720 
721     case BTA_HF_CLIENT_SCO_CLOSING_ST:
722         switch (event) {
723         case BTA_HF_CLIENT_SCO_OPEN_E:
724             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST;
725             break;
726 
727         case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
728             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
729             break;
730 
731         case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
732             /* peer closed sco; create sco listen connection */
733             bta_hf_client_sco_create(FALSE);
734 
735             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
736             break;
737 
738         default:
739             APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event);
740             break;
741         }
742         break;
743 
744     case BTA_HF_CLIENT_SCO_CLOSE_OP_ST:
745         switch (event) {
746         case BTA_HF_CLIENT_SCO_CLOSE_E:
747             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
748             break;
749 
750         case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
751             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
752             break;
753 
754         case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
755             /* open sco connection */
756             bta_hf_client_sco_create(TRUE);
757             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
758             break;
759 
760         default:
761             APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event);
762             break;
763         }
764         break;
765 
766     case BTA_HF_CLIENT_SCO_SHUTTING_ST:
767         switch (event) {
768         case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
769             /* close sco connection; wait for conn close event */
770             bta_hf_client_sco_remove(TRUE);
771             break;
772 
773         case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
774             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
775             break;
776 
777         case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
778             bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
779             break;
780 
781         default:
782             APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event);
783             break;
784         }
785         break;
786 
787     default:
788         break;
789     }
790 }
791 
792 /*******************************************************************************
793 **
794 ** Function         bta_hf_client_sco_listen
795 **
796 ** Description      Initialize SCO listener
797 **
798 **
799 ** Returns          void
800 **
801 *******************************************************************************/
bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA * p_data)802 void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data)
803 {
804     UNUSED(p_data);
805 
806     APPL_TRACE_DEBUG("%s", __FUNCTION__);
807 
808     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E);
809 }
810 
811 /*******************************************************************************
812 **
813 ** Function         bta_hf_client_sco_shutdown
814 **
815 ** Description
816 **
817 **
818 ** Returns          void
819 **
820 *******************************************************************************/
bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA * p_data)821 void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data)
822 {
823     UNUSED(p_data);
824 
825     APPL_TRACE_DEBUG("%s", __FUNCTION__);
826 
827     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E);
828 }
829 
830 /*******************************************************************************
831 **
832 ** Function         bta_hf_client_sco_conn_open
833 **
834 ** Description
835 **
836 **
837 ** Returns          void
838 **
839 *******************************************************************************/
bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA * p_data)840 void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data)
841 {
842     UNUSED(p_data);
843 
844     APPL_TRACE_DEBUG("%s", __FUNCTION__);
845 
846     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E);
847 
848     bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
849 #if (BTM_SCO_HCI_INCLUDED == TRUE)
850     bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_ON, 0);
851     /* open SCO codec if SCO is routed through transport */
852     bta_hf_client_sco_co_open(bta_hf_client_cb.scb.sco_idx, bta_hf_client_cb.scb.air_mode,
853                                 bta_hf_client_cb.scb.out_pkt_len, BTA_HF_CLIENT_CI_SCO_DATA_EVT);
854 #endif
855 
856     if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {
857         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT);
858     } else {
859         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT);
860     }
861 
862     bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
863 }
864 
865 /*******************************************************************************
866 **
867 ** Function         bta_hf_client_sco_conn_close
868 **
869 ** Description
870 **
871 **
872 ** Returns          void
873 **
874 *******************************************************************************/
bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA * p_data)875 void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data)
876 {
877     APPL_TRACE_DEBUG("%s", __FUNCTION__);
878 
879     /* clear current scb */
880     bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
881 
882     /* retry_with_sco_only, will be set only when initiator
883     ** and HFClient is first trying to establish an eSCO connection */
884     if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn) {
885         bta_hf_client_sco_create(TRUE);
886     } else {
887         bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E);
888 
889         bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
890 
891         bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
892 
893         /* call app callback */
894         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
895 
896         if (bta_hf_client_cb.scb.sco_close_rfc == TRUE) {
897             bta_hf_client_cb.scb.sco_close_rfc = FALSE;
898             bta_hf_client_rfc_do_close(p_data);
899         }
900     }
901     bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
902 }
903 
904 /*******************************************************************************
905 **
906 ** Function         bta_hf_client_sco_open
907 **
908 ** Description
909 **
910 **
911 ** Returns          void
912 **
913 *******************************************************************************/
bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA * p_data)914 void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data)
915 {
916     UNUSED(p_data);
917 
918     APPL_TRACE_DEBUG("%s", __FUNCTION__);
919 
920     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E);
921 }
922 
923 /*******************************************************************************
924 **
925 ** Function         bta_hf_client_sco_close
926 **
927 ** Description
928 **
929 **
930 ** Returns          void
931 **
932 *******************************************************************************/
bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA * p_data)933 void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data)
934 {
935     UNUSED(p_data);
936 
937     APPL_TRACE_DEBUG("%s  0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx);
938 
939     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) {
940         bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E);
941     }
942 }
943 
944 #endif /* #if (BTA_HF_INCLUDED == TRUE) */
945