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
30static 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
71enum
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*******************************************************************************/
91static 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*******************************************************************************/
127void 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*******************************************************************************/
147static 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*******************************************************************************/
186static 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*******************************************************************************/
215static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
216{
217    UINT8 *rem_bd;
218
219    APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
220
221    rem_bd = BTM_ReadScoBdAddr(sco_idx);
222
223    if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 &&
224            bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx)
225    {
226        BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
227        p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT;
228        p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;
229        bta_sys_sendmsg(p_buf);
230    }
231    /* no match found; disconnect sco, init sco variables */
232    else
233    {
234        bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
235        BTM_RemoveSco(sco_idx);
236    }
237}
238
239/*******************************************************************************
240**
241** Function         bta_hf_client_sco_disc_cback
242**
243** Description      BTM SCO disconnection callback.
244**
245**
246** Returns          void
247**
248*******************************************************************************/
249static void bta_hf_client_sco_disc_cback(UINT16 sco_idx)
250{
251    APPL_TRACE_DEBUG("%s %d", __func__, sco_idx);
252
253    if (bta_hf_client_cb.scb.sco_idx == sco_idx) {
254        BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR));
255        p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT;
256        p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;;
257        bta_sys_sendmsg(p_buf);
258    }
259}
260
261/*******************************************************************************
262**
263** Function         bta_hf_client_create_sco
264**
265** Description
266**
267**
268** Returns          void
269**
270*******************************************************************************/
271static void bta_hf_client_sco_create(BOOLEAN is_orig)
272{
273    tBTM_STATUS       status;
274    UINT8            *p_bd_addr = NULL;
275    tBTM_ESCO_PARAMS params;
276
277    APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig);
278
279    /* Make sure this sco handle is not already in use */
280    if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
281    {
282        APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__,
283                            bta_hf_client_cb.scb.sco_idx);
284        return;
285    }
286
287    params = bta_hf_client_esco_params[1];
288
289    /* if initiating set current scb and peer bd addr */
290    if (is_orig)
291    {
292        /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
293        if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only)
294        {
295            BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &params);
296            /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
297            if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
298               ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO))
299            {
300                bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
301                APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
302            }
303        }
304        else
305        {
306            if(bta_hf_client_cb.scb.retry_with_sco_only)
307                APPL_TRACE_API("retrying with SCO only");
308            bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
309
310            BTM_SetEScoMode(BTM_LINK_TYPE_SCO, &params);
311        }
312
313        /* tell sys to stop av if any */
314        bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
315    }
316    else
317    {
318        bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
319    }
320
321    p_bd_addr = bta_hf_client_cb.scb.peer_addr;
322
323    status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
324                           &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback,
325                           bta_hf_client_sco_disc_cback);
326    if (status == BTM_CMD_STARTED && !is_orig)
327    {
328        if(!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback))
329            APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__);
330    }
331
332    APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
333                      __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx,
334                      status, params.packet_types);
335}
336
337
338/*******************************************************************************
339**
340** Function         bta_hf_client_sco_event
341**
342** Description      Handle SCO events
343**
344**
345** Returns          void
346**
347*******************************************************************************/
348static void bta_hf_client_sco_event(UINT8 event)
349{
350    APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__,
351                        bta_hf_client_cb.scb.sco_state, event);
352
353    switch (bta_hf_client_cb.scb.sco_state)
354    {
355        case BTA_HF_CLIENT_SCO_SHUTDOWN_ST:
356            switch (event)
357            {
358                case BTA_HF_CLIENT_SCO_LISTEN_E:
359                    /* create sco listen connection */
360                    bta_hf_client_sco_create(FALSE);
361                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
362                    break;
363
364                default:
365                    APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event);
366                    break;
367            }
368            break;
369
370        case BTA_HF_CLIENT_SCO_LISTEN_ST:
371            switch (event)
372            {
373                case BTA_HF_CLIENT_SCO_LISTEN_E:
374                    /* create sco listen connection (Additional channel) */
375                    bta_hf_client_sco_create(FALSE);
376                    break;
377
378                case BTA_HF_CLIENT_SCO_OPEN_E:
379                    /* remove listening connection */
380                    bta_hf_client_sco_remove(FALSE);
381
382                    /* create sco connection to peer */
383                    bta_hf_client_sco_create(TRUE);
384                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
385                    break;
386
387                case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
388                    /* remove listening connection */
389                    bta_hf_client_sco_remove(FALSE);
390
391                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
392                    break;
393
394                case BTA_HF_CLIENT_SCO_CLOSE_E:
395                    /* remove listening connection */
396                    /* Ignore the event. We need to keep listening SCO for the active SLC */
397                    APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
398                    break;
399
400                case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
401                    /* sco failed; create sco listen connection */
402                    bta_hf_client_sco_create(FALSE);
403                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
404                    break;
405
406                default:
407                    APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
408                    break;
409            }
410            break;
411
412        case BTA_HF_CLIENT_SCO_OPENING_ST:
413            switch (event)
414            {
415                case BTA_HF_CLIENT_SCO_CLOSE_E:
416                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST;
417                    break;
418
419                case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
420                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
421                    break;
422
423                case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
424                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST;
425                    break;
426
427                case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
428                    /* sco failed; create sco listen connection */
429                    bta_hf_client_sco_create(FALSE);
430                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
431                    break;
432
433                default:
434                    APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event);
435                    break;
436            }
437            break;
438
439        case BTA_HF_CLIENT_SCO_OPEN_CL_ST:
440            switch (event)
441            {
442                case BTA_HF_CLIENT_SCO_OPEN_E:
443                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
444                    break;
445
446                case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
447                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
448                    break;
449
450                case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
451                    /* close sco connection */
452                    bta_hf_client_sco_remove(TRUE);
453
454                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
455                    break;
456
457                case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
458                    /* sco failed; create sco listen connection */
459
460                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
461                    break;
462
463                default:
464                    APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event);
465                    break;
466            }
467            break;
468
469        case BTA_HF_CLIENT_SCO_OPEN_ST:
470            switch (event)
471            {
472                case BTA_HF_CLIENT_SCO_CLOSE_E:
473                    /* close sco connection if active */
474                    if (bta_hf_client_sco_remove(TRUE))
475                    {
476                        bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
477                    }
478                    break;
479
480                case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
481                    /* remove all listening connections */
482                    bta_hf_client_sco_remove(FALSE);
483
484                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
485                    break;
486
487                case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
488                    /* peer closed sco; create sco listen connection */
489                    bta_hf_client_sco_create(FALSE);
490                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
491                    break;
492
493                default:
494                    APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event);
495                    break;
496            }
497            break;
498
499        case BTA_HF_CLIENT_SCO_CLOSING_ST:
500            switch (event)
501            {
502                case BTA_HF_CLIENT_SCO_OPEN_E:
503                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST;
504                    break;
505
506                case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
507                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
508                    break;
509
510                case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
511                    /* peer closed sco; create sco listen connection */
512                    bta_hf_client_sco_create(FALSE);
513
514                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
515                    break;
516
517                default:
518                    APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event);
519                    break;
520            }
521            break;
522
523        case BTA_HF_CLIENT_SCO_CLOSE_OP_ST:
524            switch (event)
525            {
526                case BTA_HF_CLIENT_SCO_CLOSE_E:
527                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
528                    break;
529
530                case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
531                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
532                    break;
533
534                case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
535                    /* open sco connection */
536                    bta_hf_client_sco_create(TRUE);
537                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
538                    break;
539
540                default:
541                    APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event);
542                    break;
543            }
544            break;
545
546        case BTA_HF_CLIENT_SCO_SHUTTING_ST:
547            switch (event)
548            {
549                case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
550                    /* close sco connection; wait for conn close event */
551                    bta_hf_client_sco_remove(TRUE);
552                    break;
553
554                case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
555                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
556                    break;
557
558                case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
559                    bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
560                    break;
561
562                default:
563                    APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event);
564                    break;
565            }
566            break;
567
568        default:
569            break;
570    }
571}
572
573/*******************************************************************************
574**
575** Function         bta_hf_client_sco_listen
576**
577** Description      Initialize SCO listener
578**
579**
580** Returns          void
581**
582*******************************************************************************/
583void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data)
584{
585    UNUSED(p_data);
586
587    APPL_TRACE_DEBUG("%s", __FUNCTION__);
588
589    bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E);
590}
591
592/*******************************************************************************
593**
594** Function         bta_hf_client_sco_shutdown
595**
596** Description
597**
598**
599** Returns          void
600**
601*******************************************************************************/
602void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data)
603{
604    UNUSED(p_data);
605
606    APPL_TRACE_DEBUG("%s", __FUNCTION__);
607
608    bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E);
609}
610
611/*******************************************************************************
612**
613** Function         bta_hf_client_sco_conn_open
614**
615** Description
616**
617**
618** Returns          void
619**
620*******************************************************************************/
621void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data)
622{
623    UNUSED(p_data);
624
625    APPL_TRACE_DEBUG("%s", __FUNCTION__);
626
627    bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E);
628
629    bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
630
631    if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC)
632    {
633        bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT);
634    }
635    else
636    {
637        bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT);
638    }
639
640    bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
641}
642
643/*******************************************************************************
644**
645** Function         bta_hf_client_sco_conn_close
646**
647** Description
648**
649**
650** Returns          void
651**
652*******************************************************************************/
653void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data)
654{
655    APPL_TRACE_DEBUG("%s", __FUNCTION__);
656
657    /* clear current scb */
658    bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
659
660    /* retry_with_sco_only, will be set only when initiator
661    ** and HFClient is first trying to establish an eSCO connection */
662    if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn)
663    {
664        bta_hf_client_sco_create(TRUE);
665    }
666    else
667    {
668        bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E);
669
670        bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
671
672        bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
673
674        /* call app callback */
675        bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
676
677        if (bta_hf_client_cb.scb.sco_close_rfc == TRUE)
678        {
679            bta_hf_client_cb.scb.sco_close_rfc = FALSE;
680            bta_hf_client_rfc_do_close(p_data);
681        }
682    }
683    bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
684}
685
686/*******************************************************************************
687**
688** Function         bta_hf_client_sco_open
689**
690** Description
691**
692**
693** Returns          void
694**
695*******************************************************************************/
696void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data)
697{
698    UNUSED(p_data);
699
700    APPL_TRACE_DEBUG("%s", __FUNCTION__);
701
702    bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E);
703}
704
705/*******************************************************************************
706**
707** Function         bta_hf_client_sco_close
708**
709** Description
710**
711**
712** Returns          void
713**
714*******************************************************************************/
715void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data)
716{
717    UNUSED(p_data);
718
719    APPL_TRACE_DEBUG("%s  0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx);
720
721    if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
722    {
723        bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E);
724    }
725}
726