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