Home | History | Annotate | Download | only in hf_client
      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 
     30 static 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 
     71 enum
     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 *******************************************************************************/
     91 static 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 *******************************************************************************/
    127 void 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 *******************************************************************************/
    147 static 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 *******************************************************************************/
    186 static 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 *******************************************************************************/
    215 static 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 *******************************************************************************/
    249 static 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 *******************************************************************************/
    271 static 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 *******************************************************************************/
    348 static 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 *******************************************************************************/
    583 void 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 *******************************************************************************/
    602 void 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 *******************************************************************************/
    621 void 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 *******************************************************************************/
    653 void 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 *******************************************************************************/
    696 void 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 *******************************************************************************/
    715 void 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