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 <bd.h>
     23 #include <string.h>
     24 #include "bt_utils.h"
     25 
     26 #define BTA_HF_CLIENT_NO_EDR_ESCO  (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
     27                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
     28                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
     29                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
     30 
     31 static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
     32         /* SCO CVSD */
     33         {
     34                 .rx_bw = BTM_64KBITS_RATE,
     35                 .tx_bw = BTM_64KBITS_RATE,
     36                 .max_latency = 10,
     37                 .voice_contfmt = BTM_VOICE_SETTING_CVSD,
     38                 .packet_types = (BTM_SCO_LINK_ONLY_MASK          |
     39                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
     40                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
     41                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
     42                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
     43                  .retrans_effort = BTM_ESCO_RETRANS_POWER,
     44         },
     45         /* ESCO CVSD */
     46         {
     47                 .rx_bw = BTM_64KBITS_RATE,
     48                 .tx_bw = BTM_64KBITS_RATE,
     49                 .max_latency = 10,
     50                 .voice_contfmt = BTM_VOICE_SETTING_CVSD,
     51                 /* Allow controller to use all types available except 5-slot EDR */
     52                 .packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
     53                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
     54                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
     55                 .retrans_effort = BTM_ESCO_RETRANS_POWER,
     56         },
     57         /* ESCO mSBC */
     58         {
     59                 .rx_bw = BTM_64KBITS_RATE,
     60                 .tx_bw = BTM_64KBITS_RATE,
     61                 .max_latency = 13,
     62                 .voice_contfmt = BTM_VOICE_SETTING_TRANS,
     63                 /* Packet Types : EV3 + 2-EV3               */
     64                 .packet_types = (BTM_SCO_PKT_TYPES_MASK_EV3  |
     65                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
     66                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
     67                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
     68                 .retrans_effort = BTM_ESCO_RETRANS_QUALITY,
     69         }
     70 };
     71 
     72 enum
     73 {
     74     BTA_HF_CLIENT_SCO_LISTEN_E,
     75     BTA_HF_CLIENT_SCO_OPEN_E,          /* open request */
     76     BTA_HF_CLIENT_SCO_CLOSE_E,         /* close request */
     77     BTA_HF_CLIENT_SCO_SHUTDOWN_E,      /* shutdown request */
     78     BTA_HF_CLIENT_SCO_CONN_OPEN_E,     /* sco opened */
     79     BTA_HF_CLIENT_SCO_CONN_CLOSE_E,    /* sco closed */
     80 };
     81 
     82 /*******************************************************************************
     83 **
     84 ** Function         bta_hf_client_remove_sco
     85 **
     86 ** Description      Removes the specified SCO from the system.
     87 **                  If only_active is TRUE, then SCO is only removed if connected
     88 **
     89 ** Returns          BOOLEAN   - TRUE if Sco removal was started
     90 **
     91 *******************************************************************************/
     92 static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active)
     93 {
     94     BOOLEAN     removed_started = FALSE;
     95     tBTM_STATUS status;
     96 
     97     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, only_active);
     98 
     99     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
    100     {
    101         status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx);
    102 
    103         APPL_TRACE_DEBUG("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status);
    104 
    105         if (status == BTM_CMD_STARTED)
    106         {
    107             removed_started = TRUE;
    108         }
    109         /* If no connection reset the sco handle */
    110         else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) )
    111         {
    112             bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
    113         }
    114     }
    115     return removed_started;
    116 }
    117 
    118 /*******************************************************************************
    119 **
    120 ** Function         bta_hf_client_cback_sco
    121 **
    122 ** Description      Call application callback function with SCO event.
    123 **
    124 **
    125 ** Returns          void
    126 **
    127 *******************************************************************************/
    128 void bta_hf_client_cback_sco(UINT8 event)
    129 {
    130     tBTA_HF_CLIENT    evt;
    131 
    132     memset(&evt, 0, sizeof(evt));
    133 
    134     /* call app cback */
    135     (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT *) &evt);
    136 }
    137 
    138 /*******************************************************************************
    139 **
    140 ** Function         bta_hf_client_sco_conn_rsp
    141 **
    142 ** Description      Process the SCO connection request
    143 **
    144 **
    145 ** Returns          void
    146 **
    147 *******************************************************************************/
    148 static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
    149 {
    150     tBTM_ESCO_PARAMS    resp;
    151     UINT8               hci_status = HCI_SUCCESS;
    152 
    153     APPL_TRACE_DEBUG("%s", __FUNCTION__);
    154 
    155     if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST)
    156     {
    157         if (p_data->link_type == BTM_LINK_TYPE_SCO)
    158         {
    159             resp = bta_hf_client_esco_params[0];
    160         }
    161         else
    162         {
    163             resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec];
    164         }
    165 
    166         /* tell sys to stop av if any */
    167         bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
    168     }
    169     else
    170     {
    171         hci_status = HCI_ERR_HOST_REJECT_DEVICE;
    172     }
    173 
    174     BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
    175 }
    176 
    177 /*******************************************************************************
    178 **
    179 ** Function         bta_hf_client_sco_connreq_cback
    180 **
    181 ** Description      BTM eSCO connection requests and eSCO change requests
    182 **                  Only the connection requests are processed by BTA.
    183 **
    184 ** Returns          void
    185 **
    186 *******************************************************************************/
    187 static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
    188 {
    189     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, event);
    190 
    191     if (event != BTM_ESCO_CONN_REQ_EVT)
    192     {
    193         return;
    194     }
    195 
    196     /* TODO check remote bdaddr, should allow connect only from device with
    197      * active SLC  */
    198 
    199     bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx;
    200 
    201     bta_hf_client_sco_conn_rsp(&p_data->conn_evt);
    202 
    203     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
    204 }
    205 
    206 /*******************************************************************************
    207 **
    208 ** Function         bta_hf_client_sco_conn_cback
    209 **
    210 ** Description      BTM SCO connection callback.
    211 **
    212 **
    213 ** Returns          void
    214 **
    215 *******************************************************************************/
    216 static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
    217 {
    218     BT_HDR  *p_buf;
    219     UINT8 *rem_bd;
    220 
    221     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
    222 
    223     rem_bd = BTM_ReadScoBdAddr(sco_idx);
    224 
    225     if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 &&
    226             bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx)
    227     {
    228         if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
    229         {
    230             p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT;
    231             p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;
    232             bta_sys_sendmsg(p_buf);
    233         }
    234     }
    235     /* no match found; disconnect sco, init sco variables */
    236     else
    237     {
    238         bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
    239         BTM_RemoveSco(sco_idx);
    240     }
    241 }
    242 
    243 /*******************************************************************************
    244 **
    245 ** Function         bta_hf_client_sco_disc_cback
    246 **
    247 ** Description      BTM SCO disconnection callback.
    248 **
    249 **
    250 ** Returns          void
    251 **
    252 *******************************************************************************/
    253 static void bta_hf_client_sco_disc_cback(UINT16 sco_idx)
    254 {
    255     BT_HDR  *p_buf;
    256 
    257     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
    258 
    259     if (bta_hf_client_cb.scb.sco_idx == sco_idx)
    260     {
    261         if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
    262         {
    263             p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT;
    264             p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;;
    265             bta_sys_sendmsg(p_buf);
    266         }
    267     }
    268 }
    269 
    270 /*******************************************************************************
    271 **
    272 ** Function         bta_hf_client_create_sco
    273 **
    274 ** Description
    275 **
    276 **
    277 ** Returns          void
    278 **
    279 *******************************************************************************/
    280 static void bta_hf_client_sco_create(BOOLEAN is_orig)
    281 {
    282     tBTM_STATUS       status;
    283     UINT8            *p_bd_addr = NULL;
    284     tBTM_ESCO_PARAMS params;
    285 
    286     APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig);
    287 
    288     /* Make sure this sco handle is not already in use */
    289     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
    290     {
    291         APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__,
    292                             bta_hf_client_cb.scb.sco_idx);
    293         return;
    294     }
    295 
    296     params = bta_hf_client_esco_params[1];
    297 
    298     /* if initiating set current scb and peer bd addr */
    299     if (is_orig)
    300     {
    301         /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
    302         if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only)
    303         {
    304             BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &params);
    305             /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
    306             if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
    307                ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO))
    308             {
    309                 bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
    310                 APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
    311             }
    312         }
    313         else
    314         {
    315             if(bta_hf_client_cb.scb.retry_with_sco_only)
    316                 APPL_TRACE_API("retrying with SCO only");
    317             bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
    318 
    319             BTM_SetEScoMode(BTM_LINK_TYPE_SCO, &params);
    320         }
    321 
    322         /* tell sys to stop av if any */
    323         bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
    324     }
    325     else
    326     {
    327         bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
    328     }
    329 
    330     p_bd_addr = bta_hf_client_cb.scb.peer_addr;
    331 
    332     status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
    333                            &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback,
    334                            bta_hf_client_sco_disc_cback);
    335     if (status == BTM_CMD_STARTED && !is_orig)
    336     {
    337         if(!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback))
    338             APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__);
    339     }
    340 
    341     APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
    342                       __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx,
    343                       status, params.packet_types);
    344 }
    345 
    346 
    347 /*******************************************************************************
    348 **
    349 ** Function         bta_hf_client_sco_event
    350 **
    351 ** Description      Handle SCO events
    352 **
    353 **
    354 ** Returns          void
    355 **
    356 *******************************************************************************/
    357 static void bta_hf_client_sco_event(UINT8 event)
    358 {
    359     APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__,
    360                         bta_hf_client_cb.scb.sco_state, event);
    361 
    362     switch (bta_hf_client_cb.scb.sco_state)
    363     {
    364         case BTA_HF_CLIENT_SCO_SHUTDOWN_ST:
    365             switch (event)
    366             {
    367                 case BTA_HF_CLIENT_SCO_LISTEN_E:
    368                     /* create sco listen connection */
    369                     bta_hf_client_sco_create(FALSE);
    370                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
    371                     break;
    372 
    373                 default:
    374                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event);
    375                     break;
    376             }
    377             break;
    378 
    379         case BTA_HF_CLIENT_SCO_LISTEN_ST:
    380             switch (event)
    381             {
    382                 case BTA_HF_CLIENT_SCO_LISTEN_E:
    383                     /* create sco listen connection (Additional channel) */
    384                     bta_hf_client_sco_create(FALSE);
    385                     break;
    386 
    387                 case BTA_HF_CLIENT_SCO_OPEN_E:
    388                     /* remove listening connection */
    389                     bta_hf_client_sco_remove(FALSE);
    390 
    391                     /* create sco connection to peer */
    392                     bta_hf_client_sco_create(TRUE);
    393                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
    394                     break;
    395 
    396                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
    397                     /* remove listening connection */
    398                     bta_hf_client_sco_remove(FALSE);
    399 
    400                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
    401                     break;
    402 
    403                 case BTA_HF_CLIENT_SCO_CLOSE_E:
    404                     /* remove listening connection */
    405                     /* Ignore the event. We need to keep listening SCO for the active SLC */
    406                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
    407                     break;
    408 
    409                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
    410                     /* sco failed; create sco listen connection */
    411                     bta_hf_client_sco_create(FALSE);
    412                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
    413                     break;
    414 
    415                 default:
    416                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
    417                     break;
    418             }
    419             break;
    420 
    421         case BTA_HF_CLIENT_SCO_OPENING_ST:
    422             switch (event)
    423             {
    424                 case BTA_HF_CLIENT_SCO_CLOSE_E:
    425                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST;
    426                     break;
    427 
    428                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
    429                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
    430                     break;
    431 
    432                 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
    433                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST;
    434                     break;
    435 
    436                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
    437                     /* sco failed; create sco listen connection */
    438                     bta_hf_client_sco_create(FALSE);
    439                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
    440                     break;
    441 
    442                 default:
    443                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event);
    444                     break;
    445             }
    446             break;
    447 
    448         case BTA_HF_CLIENT_SCO_OPEN_CL_ST:
    449             switch (event)
    450             {
    451                 case BTA_HF_CLIENT_SCO_OPEN_E:
    452                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
    453                     break;
    454 
    455                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
    456                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
    457                     break;
    458 
    459                 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
    460                     /* close sco connection */
    461                     bta_hf_client_sco_remove(TRUE);
    462 
    463                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
    464                     break;
    465 
    466                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
    467                     /* sco failed; create sco listen connection */
    468 
    469                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
    470                     break;
    471 
    472                 default:
    473                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event);
    474                     break;
    475             }
    476             break;
    477 
    478         case BTA_HF_CLIENT_SCO_OPEN_ST:
    479             switch (event)
    480             {
    481                 case BTA_HF_CLIENT_SCO_CLOSE_E:
    482                     /* close sco connection if active */
    483                     if (bta_hf_client_sco_remove(TRUE))
    484                     {
    485                         bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
    486                     }
    487                     break;
    488 
    489                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
    490                     /* remove all listening connections */
    491                     bta_hf_client_sco_remove(FALSE);
    492 
    493                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
    494                     break;
    495 
    496                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
    497                     /* peer closed sco; create sco listen connection */
    498                     bta_hf_client_sco_create(FALSE);
    499                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
    500                     break;
    501 
    502                 default:
    503                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event);
    504                     break;
    505             }
    506             break;
    507 
    508         case BTA_HF_CLIENT_SCO_CLOSING_ST:
    509             switch (event)
    510             {
    511                 case BTA_HF_CLIENT_SCO_OPEN_E:
    512                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST;
    513                     break;
    514 
    515                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
    516                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
    517                     break;
    518 
    519                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
    520                     /* peer closed sco; create sco listen connection */
    521                     bta_hf_client_sco_create(FALSE);
    522 
    523                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
    524                     break;
    525 
    526                 default:
    527                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event);
    528                     break;
    529             }
    530             break;
    531 
    532         case BTA_HF_CLIENT_SCO_CLOSE_OP_ST:
    533             switch (event)
    534             {
    535                 case BTA_HF_CLIENT_SCO_CLOSE_E:
    536                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
    537                     break;
    538 
    539                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
    540                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
    541                     break;
    542 
    543                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
    544                     /* open sco connection */
    545                     bta_hf_client_sco_create(TRUE);
    546                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
    547                     break;
    548 
    549                 default:
    550                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event);
    551                     break;
    552             }
    553             break;
    554 
    555         case BTA_HF_CLIENT_SCO_SHUTTING_ST:
    556             switch (event)
    557             {
    558                 case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
    559                     /* close sco connection; wait for conn close event */
    560                     bta_hf_client_sco_remove(TRUE);
    561                     break;
    562 
    563                 case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
    564                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
    565                     break;
    566 
    567                 case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
    568                     bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
    569                     break;
    570 
    571                 default:
    572                     APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event);
    573                     break;
    574             }
    575             break;
    576 
    577         default:
    578             break;
    579     }
    580 }
    581 
    582 /*******************************************************************************
    583 **
    584 ** Function         bta_hf_client_sco_listen
    585 **
    586 ** Description      Initialize SCO listener
    587 **
    588 **
    589 ** Returns          void
    590 **
    591 *******************************************************************************/
    592 void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data)
    593 {
    594     UNUSED(p_data);
    595 
    596     APPL_TRACE_DEBUG("%s", __FUNCTION__);
    597 
    598     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E);
    599 }
    600 
    601 /*******************************************************************************
    602 **
    603 ** Function         bta_hf_client_sco_shutdown
    604 **
    605 ** Description
    606 **
    607 **
    608 ** Returns          void
    609 **
    610 *******************************************************************************/
    611 void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data)
    612 {
    613     UNUSED(p_data);
    614 
    615     APPL_TRACE_DEBUG("%s", __FUNCTION__);
    616 
    617     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E);
    618 }
    619 
    620 /*******************************************************************************
    621 **
    622 ** Function         bta_hf_client_sco_conn_open
    623 **
    624 ** Description
    625 **
    626 **
    627 ** Returns          void
    628 **
    629 *******************************************************************************/
    630 void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data)
    631 {
    632     UNUSED(p_data);
    633 
    634     APPL_TRACE_DEBUG("%s", __FUNCTION__);
    635 
    636     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E);
    637 
    638     bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
    639 
    640     if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC)
    641     {
    642         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT);
    643     }
    644     else
    645     {
    646         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT);
    647     }
    648 
    649     bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
    650 }
    651 
    652 /*******************************************************************************
    653 **
    654 ** Function         bta_hf_client_sco_conn_close
    655 **
    656 ** Description
    657 **
    658 **
    659 ** Returns          void
    660 **
    661 *******************************************************************************/
    662 void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data)
    663 {
    664     APPL_TRACE_DEBUG("%s", __FUNCTION__);
    665 
    666     /* clear current scb */
    667     bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
    668 
    669     /* retry_with_sco_only, will be set only when initiator
    670     ** and HFClient is first trying to establish an eSCO connection */
    671     if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn)
    672     {
    673         bta_hf_client_sco_create(TRUE);
    674     }
    675     else
    676     {
    677         bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E);
    678 
    679         bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
    680 
    681         bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
    682 
    683         /* call app callback */
    684         bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
    685 
    686         if (bta_hf_client_cb.scb.sco_close_rfc == TRUE)
    687         {
    688             bta_hf_client_cb.scb.sco_close_rfc = FALSE;
    689             bta_hf_client_rfc_do_close(p_data);
    690         }
    691     }
    692     bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
    693 }
    694 
    695 /*******************************************************************************
    696 **
    697 ** Function         bta_hf_client_sco_open
    698 **
    699 ** Description
    700 **
    701 **
    702 ** Returns          void
    703 **
    704 *******************************************************************************/
    705 void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data)
    706 {
    707     UNUSED(p_data);
    708 
    709     APPL_TRACE_DEBUG("%s", __FUNCTION__);
    710 
    711     bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E);
    712 }
    713 
    714 /*******************************************************************************
    715 **
    716 ** Function         bta_hf_client_sco_close
    717 **
    718 ** Description
    719 **
    720 **
    721 ** Returns          void
    722 **
    723 *******************************************************************************/
    724 void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data)
    725 {
    726     UNUSED(p_data);
    727 
    728     APPL_TRACE_DEBUG("%s  0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx);
    729 
    730     if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
    731     {
    732         bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E);
    733     }
    734 }
    735