Home | History | Annotate | Download | only in ag
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2003-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  This file contains action functions for the audio gateway.
     22  *
     23  ******************************************************************************/
     24 
     25 #include <string.h>
     26 
     27 #include "bta_ag_api.h"
     28 #include "bta_ag_co.h"
     29 #include "bta_ag_int.h"
     30 #include "bta_api.h"
     31 #include "bta_dm_api.h"
     32 #include "bta_sys.h"
     33 #include "l2c_api.h"
     34 #include "osi/include/osi.h"
     35 #include "port_api.h"
     36 #include "utl.h"
     37 
     38 /*****************************************************************************
     39  *  Constants
     40  ****************************************************************************/
     41 
     42 /* maximum length of data to read from RFCOMM */
     43 #define BTA_AG_RFC_READ_MAX 512
     44 
     45 /* maximum AT command length */
     46 #define BTA_AG_CMD_MAX 512
     47 
     48 const uint16_t bta_ag_uuid[BTA_AG_NUM_IDX] = {
     49     UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY, UUID_SERVCLASS_AG_HANDSFREE};
     50 
     51 const uint8_t bta_ag_sec_id[BTA_AG_NUM_IDX] = {BTM_SEC_SERVICE_HEADSET_AG,
     52                                                BTM_SEC_SERVICE_AG_HANDSFREE};
     53 
     54 const tBTA_SERVICE_ID bta_ag_svc_id[BTA_AG_NUM_IDX] = {BTA_HSP_SERVICE_ID,
     55                                                        BTA_HFP_SERVICE_ID};
     56 
     57 const tBTA_SERVICE_MASK bta_ag_svc_mask[BTA_AG_NUM_IDX] = {
     58     BTA_HSP_SERVICE_MASK, BTA_HFP_SERVICE_MASK};
     59 
     60 typedef void (*tBTA_AG_ATCMD_CBACK)(tBTA_AG_SCB* p_scb, uint16_t cmd,
     61                                     uint8_t arg_type, char* p_arg,
     62                                     int16_t int_arg);
     63 
     64 const tBTA_AG_ATCMD_CBACK bta_ag_at_cback_tbl[BTA_AG_NUM_IDX] = {
     65     bta_ag_at_hsp_cback, bta_ag_at_hfp_cback};
     66 
     67 /*******************************************************************************
     68  *
     69  * Function         bta_ag_cback_open
     70  *
     71  * Description      Send open callback event to application.
     72  *
     73  *
     74  * Returns          void
     75  *
     76  ******************************************************************************/
     77 static void bta_ag_cback_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data,
     78                               tBTA_AG_STATUS status) {
     79   tBTA_AG_OPEN open;
     80 
     81   /* call app callback with open event */
     82   open.hdr.handle = bta_ag_scb_to_idx(p_scb);
     83   open.hdr.app_id = p_scb->app_id;
     84   open.status = status;
     85   open.service_id = bta_ag_svc_id[p_scb->conn_service];
     86   if (p_data) {
     87     /* if p_data is provided then we need to pick the bd address from the open
     88      * api structure */
     89     bdcpy(open.bd_addr, p_data->api_open.bd_addr);
     90   } else {
     91     bdcpy(open.bd_addr, p_scb->peer_addr);
     92   }
     93 
     94   (*bta_ag_cb.p_cback)(BTA_AG_OPEN_EVT, (tBTA_AG*)&open);
     95 }
     96 
     97 /*******************************************************************************
     98  *
     99  * Function         bta_ag_register
    100  *
    101  * Description      This function initializes values of the AG cb and sets up
    102  *                  the SDP record for the services.
    103  *
    104  *
    105  * Returns          void
    106  *
    107  ******************************************************************************/
    108 void bta_ag_register(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    109   tBTA_AG_REGISTER reg;
    110 
    111   /* initialize control block */
    112   p_scb->reg_services = p_data->api_register.services;
    113   p_scb->serv_sec_mask = p_data->api_register.sec_mask;
    114   p_scb->features = p_data->api_register.features;
    115   p_scb->app_id = p_data->api_register.app_id;
    116 
    117   /* create SDP records */
    118   bta_ag_create_records(p_scb, p_data);
    119 
    120   /* start RFCOMM servers */
    121   bta_ag_start_servers(p_scb, p_scb->reg_services);
    122 
    123   /* call app callback with register event */
    124   reg.hdr.handle = bta_ag_scb_to_idx(p_scb);
    125   reg.hdr.app_id = p_scb->app_id;
    126   reg.status = BTA_AG_SUCCESS;
    127   (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG*)&reg);
    128 }
    129 
    130 /*******************************************************************************
    131  *
    132  * Function         bta_ag_deregister
    133  *
    134  * Description      This function removes the sdp records, closes the RFCOMM
    135  *                  servers, and deallocates the service control block.
    136  *
    137  *
    138  * Returns          void
    139  *
    140  ******************************************************************************/
    141 void bta_ag_deregister(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    142   /* set dealloc */
    143   p_scb->dealloc = true;
    144 
    145   /* remove sdp records */
    146   bta_ag_del_records(p_scb, p_data);
    147 
    148   /* remove rfcomm servers */
    149   bta_ag_close_servers(p_scb, p_scb->reg_services);
    150 
    151   /* dealloc */
    152   bta_ag_scb_dealloc(p_scb);
    153 }
    154 
    155 /*******************************************************************************
    156  *
    157  * Function         bta_ag_start_dereg
    158  *
    159  * Description      Start a deregister event.
    160  *
    161  *
    162  * Returns          void
    163  *
    164  ******************************************************************************/
    165 void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    166   /* set dealloc */
    167   p_scb->dealloc = true;
    168 
    169   /* remove sdp records */
    170   bta_ag_del_records(p_scb, p_data);
    171 }
    172 
    173 /*******************************************************************************
    174  *
    175  * Function         bta_ag_start_open
    176  *
    177  * Description      This starts an AG open.
    178  *
    179  *
    180  * Returns          void
    181  *
    182  ******************************************************************************/
    183 void bta_ag_start_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    184   BD_ADDR pending_bd_addr;
    185 
    186   /* store parameters */
    187   if (p_data) {
    188     bdcpy(p_scb->peer_addr, p_data->api_open.bd_addr);
    189     p_scb->open_services = p_data->api_open.services;
    190     p_scb->cli_sec_mask = p_data->api_open.sec_mask;
    191   }
    192 
    193   /* Check if RFCOMM has any incoming connection to avoid collision. */
    194   if (PORT_IsOpening(pending_bd_addr)) {
    195     /* Let the incoming connection goes through.                        */
    196     /* Issue collision for this scb for now.                            */
    197     /* We will decide what to do when we find incoming connetion later. */
    198     bta_ag_collision_cback(0, BTA_ID_AG, 0, p_scb->peer_addr);
    199     return;
    200   }
    201 
    202   /* close servers */
    203   bta_ag_close_servers(p_scb, p_scb->reg_services);
    204 
    205   /* set role */
    206   p_scb->role = BTA_AG_INT;
    207 
    208   /* do service search */
    209   bta_ag_do_disc(p_scb, p_scb->open_services);
    210 }
    211 
    212 /*******************************************************************************
    213  *
    214  * Function         bta_ag_disc_int_res
    215  *
    216  * Description      This function handles a discovery result when initiator.
    217  *
    218  *
    219  * Returns          void
    220  *
    221  ******************************************************************************/
    222 void bta_ag_disc_int_res(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    223   uint16_t event = BTA_AG_DISC_FAIL_EVT;
    224 
    225   APPL_TRACE_DEBUG("bta_ag_disc_int_res: Status: %d",
    226                    p_data->disc_result.status);
    227 
    228   /* if found service */
    229   if (p_data->disc_result.status == SDP_SUCCESS ||
    230       p_data->disc_result.status == SDP_DB_FULL) {
    231     /* get attributes */
    232     if (bta_ag_sdp_find_attr(p_scb, p_scb->open_services)) {
    233       /* set connected service */
    234       p_scb->conn_service = bta_ag_service_to_idx(p_scb->open_services);
    235 
    236       /* send ourselves sdp ok event */
    237       event = BTA_AG_DISC_OK_EVT;
    238     }
    239   }
    240 
    241   /* free discovery db */
    242   bta_ag_free_db(p_scb, p_data);
    243 
    244   /* if service not found check if we should search for other service */
    245   if ((event == BTA_AG_DISC_FAIL_EVT) &&
    246       (p_data->disc_result.status == SDP_SUCCESS ||
    247        p_data->disc_result.status == SDP_DB_FULL ||
    248        p_data->disc_result.status == SDP_NO_RECS_MATCH)) {
    249     if ((p_scb->open_services & BTA_HFP_SERVICE_MASK) &&
    250         (p_scb->open_services & BTA_HSP_SERVICE_MASK)) {
    251       /* search for HSP */
    252       p_scb->open_services &= ~BTA_HFP_SERVICE_MASK;
    253       bta_ag_do_disc(p_scb, p_scb->open_services);
    254     } else if ((p_scb->open_services & BTA_HSP_SERVICE_MASK) &&
    255                (p_scb->hsp_version == HSP_VERSION_1_2)) {
    256       /* search for UUID_SERVCLASS_HEADSET instead */
    257       p_scb->hsp_version = HSP_VERSION_1_0;
    258       bta_ag_do_disc(p_scb, p_scb->open_services);
    259     } else {
    260       /* send ourselves sdp ok/fail event */
    261       bta_ag_sm_execute(p_scb, event, p_data);
    262     }
    263   } else {
    264     /* send ourselves sdp ok/fail event */
    265     bta_ag_sm_execute(p_scb, event, p_data);
    266   }
    267 }
    268 
    269 /*******************************************************************************
    270  *
    271  * Function         bta_ag_disc_acp_res
    272  *
    273  * Description      This function handles a discovery result when acceptor.
    274  *
    275  *
    276  * Returns          void
    277  *
    278  ******************************************************************************/
    279 void bta_ag_disc_acp_res(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    280   /* if found service */
    281   if (p_data->disc_result.status == SDP_SUCCESS ||
    282       p_data->disc_result.status == SDP_DB_FULL) {
    283     /* get attributes */
    284     bta_ag_sdp_find_attr(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
    285   }
    286 
    287   /* free discovery db */
    288   bta_ag_free_db(p_scb, p_data);
    289 }
    290 
    291 /*******************************************************************************
    292  *
    293  * Function         bta_ag_disc_fail
    294  *
    295  * Description      This function handles a discovery failure.
    296  *
    297  *
    298  * Returns          void
    299  *
    300  ******************************************************************************/
    301 void bta_ag_disc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
    302   /* reopen registered servers */
    303   bta_ag_start_servers(p_scb, p_scb->reg_services);
    304 
    305   /* reinitialize stuff */
    306 
    307   /* clear the remote BD address */
    308   bdcpy(p_scb->peer_addr, bd_addr_null);
    309 
    310   /* call open cback w. failure */
    311   bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP);
    312 }
    313 
    314 /*******************************************************************************
    315  *
    316  * Function         bta_ag_open_fail
    317  *
    318  * Description      open connection failed.
    319  *
    320  *
    321  * Returns          void
    322  *
    323  ******************************************************************************/
    324 void bta_ag_open_fail(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    325   /* call open cback w. failure */
    326   bta_ag_cback_open(p_scb, p_data, BTA_AG_FAIL_RESOURCES);
    327 }
    328 
    329 /*******************************************************************************
    330  *
    331  * Function         bta_ag_rfc_fail
    332  *
    333  * Description      RFCOMM connection failed.
    334  *
    335  *
    336  * Returns          void
    337  *
    338  ******************************************************************************/
    339 void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
    340   /* reinitialize stuff */
    341   p_scb->conn_handle = 0;
    342   p_scb->conn_service = 0;
    343   p_scb->peer_features = 0;
    344   p_scb->peer_codecs = BTA_AG_CODEC_CVSD;
    345   p_scb->sco_codec = BTA_AG_CODEC_CVSD;
    346   p_scb->role = 0;
    347   p_scb->svc_conn = false;
    348   p_scb->hsp_version = HSP_VERSION_1_2;
    349   /*Clear the BD address*/
    350   bdcpy(p_scb->peer_addr, bd_addr_null);
    351 
    352   /* reopen registered servers */
    353   bta_ag_start_servers(p_scb, p_scb->reg_services);
    354 
    355   /* call open cback w. failure */
    356   bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_RFCOMM);
    357 }
    358 
    359 /*******************************************************************************
    360  *
    361  * Function         bta_ag_rfc_close
    362  *
    363  * Description      RFCOMM connection closed.
    364  *
    365  *
    366  * Returns          void
    367  *
    368  ******************************************************************************/
    369 void bta_ag_rfc_close(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
    370   tBTA_AG_CLOSE close;
    371   tBTA_SERVICE_MASK services;
    372   int i, num_active_conn = 0;
    373 
    374   /* reinitialize stuff */
    375   p_scb->conn_service = 0;
    376   p_scb->peer_features = 0;
    377   p_scb->peer_codecs = BTA_AG_CODEC_CVSD;
    378   p_scb->sco_codec = BTA_AG_CODEC_CVSD;
    379   /* Clear these flags upon SLC teardown */
    380   p_scb->codec_updated = false;
    381   p_scb->codec_fallback = false;
    382   p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
    383   p_scb->role = 0;
    384   p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    385   p_scb->svc_conn = false;
    386   p_scb->hsp_version = HSP_VERSION_1_2;
    387   bta_ag_at_reinit(&p_scb->at_cb);
    388 
    389   memset(&(p_scb->peer_hf_indicators), 0, sizeof(p_scb->peer_hf_indicators));
    390   memset(&(p_scb->local_hf_indicators), 0, sizeof(p_scb->local_hf_indicators));
    391 
    392   /* stop timers */
    393   alarm_cancel(p_scb->ring_timer);
    394   alarm_cancel(p_scb->codec_negotiation_timer);
    395 
    396   close.hdr.handle = bta_ag_scb_to_idx(p_scb);
    397   close.hdr.app_id = p_scb->app_id;
    398   bdcpy(close.bd_addr, p_scb->peer_addr);
    399 
    400   bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    401 
    402   /* call close call-out */
    403   bta_ag_co_data_close(close.hdr.handle);
    404 
    405   /* call close cback */
    406   (*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG*)&close);
    407 
    408   /* if not deregistering (deallocating) reopen registered servers */
    409   if (p_scb->dealloc == false) {
    410     /* Clear peer bd_addr so instance can be reused */
    411     bdcpy(p_scb->peer_addr, bd_addr_null);
    412 
    413     /* start only unopened server */
    414     services = p_scb->reg_services;
    415     for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++) {
    416       if (p_scb->serv_handle[i])
    417         services &= ~((tBTA_SERVICE_MASK)1 << (BTA_HSP_SERVICE_ID + i));
    418     }
    419     bta_ag_start_servers(p_scb, services);
    420 
    421     p_scb->conn_handle = 0;
    422 
    423     /* Make sure SCO state is BTA_AG_SCO_SHUTDOWN_ST */
    424     bta_ag_sco_shutdown(p_scb, NULL);
    425 
    426     /* Check if all the SLCs are down */
    427     for (i = 0; i < BTA_AG_NUM_SCB; i++) {
    428       if (bta_ag_cb.scb[i].in_use && bta_ag_cb.scb[i].svc_conn)
    429         num_active_conn++;
    430     }
    431 
    432     if (!num_active_conn) {
    433       bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    434     }
    435 
    436   }
    437   /* else close port and deallocate scb */
    438   else {
    439     RFCOMM_RemoveServer(p_scb->conn_handle);
    440     bta_ag_scb_dealloc(p_scb);
    441   }
    442 }
    443 
    444 /*******************************************************************************
    445  *
    446  * Function         bta_ag_rfc_open
    447  *
    448  * Description      Handle RFCOMM channel open.
    449  *
    450  *
    451  * Returns          void
    452  *
    453  ******************************************************************************/
    454 void bta_ag_rfc_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    455   /* initialize AT feature variables */
    456   p_scb->clip_enabled = false;
    457   p_scb->ccwa_enabled = false;
    458   p_scb->cmer_enabled = false;
    459   p_scb->cmee_enabled = false;
    460   p_scb->inband_enabled =
    461       ((p_scb->features & BTA_AG_FEAT_INBAND) == BTA_AG_FEAT_INBAND);
    462 
    463   /* set up AT command interpreter */
    464   p_scb->at_cb.p_at_tbl = (tBTA_AG_AT_CMD*)bta_ag_at_tbl[p_scb->conn_service];
    465   p_scb->at_cb.p_cmd_cback =
    466       (tBTA_AG_AT_CMD_CBACK*)bta_ag_at_cback_tbl[p_scb->conn_service];
    467   p_scb->at_cb.p_err_cback = (tBTA_AG_AT_ERR_CBACK*)bta_ag_at_err_cback;
    468   p_scb->at_cb.p_user = p_scb;
    469   p_scb->at_cb.cmd_max_len = BTA_AG_CMD_MAX;
    470   bta_ag_at_init(&p_scb->at_cb);
    471 
    472   /* call app open call-out */
    473   bta_ag_co_data_open(bta_ag_scb_to_idx(p_scb),
    474                       bta_ag_svc_id[p_scb->conn_service]);
    475 
    476   bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    477 
    478   bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS);
    479 
    480   if (p_scb->conn_service == BTA_AG_HFP) {
    481     /* if hfp start timer for service level conn */
    482     bta_sys_start_timer(p_scb->ring_timer, p_bta_ag_cfg->conn_tout,
    483                         BTA_AG_SVC_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));
    484   } else {
    485     /* else service level conn is open */
    486     bta_ag_svc_conn_open(p_scb, p_data);
    487   }
    488 }
    489 
    490 /*******************************************************************************
    491  *
    492  * Function         bta_ag_rfc_acp_open
    493  *
    494  * Description      Handle RFCOMM channel open when accepting connection.
    495  *
    496  *
    497  * Returns          void
    498  *
    499  ******************************************************************************/
    500 void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    501   uint16_t lcid;
    502   int i;
    503   tBTA_AG_SCB *ag_scb, *other_scb;
    504   BD_ADDR dev_addr;
    505   int status;
    506 
    507   /* set role */
    508   p_scb->role = BTA_AG_ACP;
    509 
    510   APPL_TRACE_DEBUG("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d",
    511                    p_scb->serv_handle[0], p_scb->serv_handle[1]);
    512 
    513   /* get bd addr of peer */
    514   if (PORT_SUCCESS != (status = PORT_CheckConnection(p_data->rfc.port_handle,
    515                                                      dev_addr, &lcid))) {
    516     APPL_TRACE_DEBUG(
    517         "bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d",
    518         status);
    519   }
    520 
    521   /* Collision Handling */
    522   for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++) {
    523     if (ag_scb->in_use && alarm_is_scheduled(ag_scb->collision_timer)) {
    524       alarm_cancel(ag_scb->collision_timer);
    525 
    526       if (bdcmp(dev_addr, ag_scb->peer_addr) == 0) {
    527         /* If incoming and outgoing device are same, nothing more to do. */
    528         /* Outgoing conn will be aborted because we have successful incoming
    529          * conn.  */
    530       } else {
    531         /* Resume outgoing connection. */
    532         other_scb = bta_ag_get_other_idle_scb(p_scb);
    533         if (other_scb) {
    534           bdcpy(other_scb->peer_addr, ag_scb->peer_addr);
    535           other_scb->open_services = ag_scb->open_services;
    536           other_scb->cli_sec_mask = ag_scb->cli_sec_mask;
    537 
    538           bta_ag_resume_open(other_scb);
    539         }
    540       }
    541 
    542       break;
    543     }
    544   }
    545 
    546   bdcpy(p_scb->peer_addr, dev_addr);
    547 
    548   /* determine connected service from port handle */
    549   for (i = 0; i < BTA_AG_NUM_IDX; i++) {
    550     APPL_TRACE_DEBUG(
    551         "bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d", i,
    552         p_scb->serv_handle[i], p_data->rfc.port_handle);
    553 
    554     if (p_scb->serv_handle[i] == p_data->rfc.port_handle) {
    555       p_scb->conn_service = i;
    556       p_scb->conn_handle = p_data->rfc.port_handle;
    557       break;
    558     }
    559   }
    560 
    561   APPL_TRACE_DEBUG("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d",
    562                    p_scb->conn_service, p_scb->conn_handle);
    563 
    564   /* close any unopened server */
    565   bta_ag_close_servers(
    566       p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service]));
    567 
    568   /* do service discovery to get features */
    569   bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
    570 
    571   /* continue with common open processing */
    572   bta_ag_rfc_open(p_scb, p_data);
    573 }
    574 
    575 /*******************************************************************************
    576  *
    577  * Function         bta_ag_rfc_data
    578  *
    579  * Description      Read and process data from RFCOMM.
    580  *
    581  *
    582  * Returns          void
    583  *
    584  ******************************************************************************/
    585 void bta_ag_rfc_data(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
    586   uint16_t len;
    587   char buf[BTA_AG_RFC_READ_MAX];
    588 
    589   memset(buf, 0, BTA_AG_RFC_READ_MAX);
    590 
    591   APPL_TRACE_DEBUG("%s", __func__);
    592 
    593   /* do the following */
    594   for (;;) {
    595     /* read data from rfcomm; if bad status, we're done */
    596     if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) !=
    597         PORT_SUCCESS) {
    598       break;
    599     }
    600 
    601     /* if no data, we're done */
    602     if (len == 0) {
    603       break;
    604     }
    605 
    606     /* run AT command interpreter on data */
    607     bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    608     bta_ag_at_parse(&p_scb->at_cb, buf, len);
    609     if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) &&
    610         bta_ag_sco_is_open(p_scb)) {
    611       APPL_TRACE_DEBUG("%s change link policy for SCO", __func__);
    612       bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    613     } else {
    614       bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    615     }
    616 
    617     /* no more data to read, we're done */
    618     if (len < BTA_AG_RFC_READ_MAX) {
    619       break;
    620     }
    621   }
    622 }
    623 
    624 /*******************************************************************************
    625  *
    626  * Function         bta_ag_start_close
    627  *
    628  * Description      Start the process of closing SCO and RFCOMM connection.
    629  *
    630  *
    631  * Returns          void
    632  *
    633  ******************************************************************************/
    634 void bta_ag_start_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    635   /* Take the link out of sniff and set L2C idle time to 0 */
    636   bta_dm_pm_active(p_scb->peer_addr);
    637   L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0, BT_TRANSPORT_BR_EDR);
    638 
    639   /* if SCO is open close SCO and wait on RFCOMM close */
    640   if (bta_ag_sco_is_open(p_scb)) {
    641     p_scb->post_sco = BTA_AG_POST_SCO_CLOSE_RFC;
    642   } else {
    643     p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    644     bta_ag_rfc_do_close(p_scb, p_data);
    645   }
    646 
    647   /* always do SCO shutdown to handle all SCO corner cases */
    648   bta_ag_sco_shutdown(p_scb, p_data);
    649 }
    650 
    651 /*******************************************************************************
    652  *
    653  * Function         bta_ag_post_sco_open
    654  *
    655  * Description      Perform post-SCO open action, if any
    656  *
    657  *
    658  * Returns          void
    659  *
    660  ******************************************************************************/
    661 void bta_ag_post_sco_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    662   switch (p_scb->post_sco) {
    663     case BTA_AG_POST_SCO_RING:
    664       bta_ag_send_ring(p_scb, p_data);
    665       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    666       break;
    667 
    668     case BTA_AG_POST_SCO_CALL_CONN:
    669       bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
    670       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    671       break;
    672 
    673     default:
    674       break;
    675   }
    676 }
    677 
    678 /*******************************************************************************
    679  *
    680  * Function         bta_ag_post_sco_close
    681  *
    682  * Description      Perform post-SCO close action, if any
    683  *
    684  *
    685  * Returns          void
    686  *
    687  ******************************************************************************/
    688 void bta_ag_post_sco_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    689   switch (p_scb->post_sco) {
    690     case BTA_AG_POST_SCO_CLOSE_RFC:
    691       bta_ag_rfc_do_close(p_scb, p_data);
    692       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    693       break;
    694 
    695     case BTA_AG_POST_SCO_CALL_CONN:
    696       bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
    697       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    698       break;
    699 
    700     case BTA_AG_POST_SCO_CALL_ORIG:
    701       bta_ag_send_call_inds(p_scb, BTA_AG_OUT_CALL_ORIG_RES);
    702       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    703       break;
    704 
    705     case BTA_AG_POST_SCO_CALL_END:
    706       bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
    707       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    708       break;
    709 
    710     case BTA_AG_POST_SCO_CALL_END_INCALL:
    711       bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
    712 
    713       /* Sending callsetup IND and Ring were defered to after SCO close. */
    714       bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_RES);
    715 
    716       if (bta_ag_inband_enabled(p_scb) &&
    717           !(p_scb->features & BTA_AG_FEAT_NOSCO)) {
    718         p_scb->post_sco = BTA_AG_POST_SCO_RING;
    719         bta_ag_sco_open(p_scb, p_data);
    720       } else {
    721         p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    722         bta_ag_send_ring(p_scb, p_data);
    723       }
    724       break;
    725 
    726     default:
    727       break;
    728   }
    729 }
    730 
    731 /*******************************************************************************
    732  *
    733  * Function         bta_ag_svc_conn_open
    734  *
    735  * Description      Service level connection opened
    736  *
    737  *
    738  * Returns          void
    739  *
    740  ******************************************************************************/
    741 void bta_ag_svc_conn_open(tBTA_AG_SCB* p_scb,
    742                           UNUSED_ATTR tBTA_AG_DATA* p_data) {
    743   tBTA_AG_CONN evt;
    744 
    745   if (!p_scb->svc_conn) {
    746     /* set state variable */
    747     p_scb->svc_conn = true;
    748 
    749     /* Clear AT+BIA mask from previous SLC if any. */
    750     p_scb->bia_masked_out = 0;
    751 
    752     alarm_cancel(p_scb->ring_timer);
    753 
    754     /* call callback */
    755     evt.hdr.handle = bta_ag_scb_to_idx(p_scb);
    756     evt.hdr.app_id = p_scb->app_id;
    757     evt.peer_feat = p_scb->peer_features;
    758     bdcpy(evt.bd_addr, p_scb->peer_addr);
    759     evt.peer_codec = p_scb->peer_codecs;
    760 
    761     if ((p_scb->call_ind != BTA_AG_CALL_INACTIVE) ||
    762         (p_scb->callsetup_ind != BTA_AG_CALLSETUP_NONE)) {
    763       bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    764     }
    765 
    766     (*bta_ag_cb.p_cback)(BTA_AG_CONN_EVT, (tBTA_AG*)&evt);
    767   }
    768 }
    769 
    770 /*******************************************************************************
    771  *
    772  * Function         bta_ag_ci_rx_data
    773  *
    774  * Description      Send result code
    775  *
    776  * Returns          void
    777  *
    778  ******************************************************************************/
    779 void bta_ag_ci_rx_data(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    780   uint16_t len;
    781   tBTA_AG_CI_RX_WRITE* p_rx_write_msg = (tBTA_AG_CI_RX_WRITE*)p_data;
    782   char* p_data_area =
    783       (char*)(p_rx_write_msg + 1); /* Point to data area after header */
    784 
    785   APPL_TRACE_DEBUG("bta_ag_ci_rx_data:");
    786   /* send to RFCOMM */
    787   bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    788   PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len);
    789   if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) && bta_ag_sco_is_open(p_scb)) {
    790     APPL_TRACE_DEBUG("bta_ag_rfc_data, change link policy for SCO");
    791     bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    792   } else {
    793     bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    794   }
    795 }
    796 
    797 /*******************************************************************************
    798  *
    799  * Function         bta_ag_rcvd_slc_ready
    800  *
    801  * Description      Handles SLC ready call-in in case of pass-through mode.
    802  *
    803  * Returns          void
    804  *
    805  ******************************************************************************/
    806 void bta_ag_rcvd_slc_ready(tBTA_AG_SCB* p_scb,
    807                            UNUSED_ATTR tBTA_AG_DATA* p_data) {
    808   APPL_TRACE_DEBUG("bta_ag_rcvd_slc_ready: handle = %d",
    809                    bta_ag_scb_to_idx(p_scb));
    810 
    811   if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH) {
    812     /* In pass-through mode, BTA knows that SLC is ready only through call-in.
    813      */
    814     bta_ag_svc_conn_open(p_scb, NULL);
    815   }
    816 }
    817 
    818 /*******************************************************************************
    819  *
    820  * Function         bta_ag_setcodec
    821  *
    822  * Description      Handle API SetCodec
    823  *
    824  *
    825  * Returns          void
    826  *
    827  ******************************************************************************/
    828 void bta_ag_setcodec(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
    829   tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec;
    830   tBTA_AG_VAL val;
    831 
    832   /* Check if the requested codec type is valid */
    833   if ((codec_type != BTA_AG_CODEC_NONE) && (codec_type != BTA_AG_CODEC_CVSD) &&
    834       (codec_type != BTA_AG_CODEC_MSBC)) {
    835     val.num = codec_type;
    836     val.hdr.status = BTA_AG_FAIL_RESOURCES;
    837     APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d",
    838                      codec_type);
    839     (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG*)&val);
    840     return;
    841   }
    842 
    843   if ((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) ||
    844       (codec_type == BTA_AG_CODEC_CVSD)) {
    845     p_scb->sco_codec = codec_type;
    846     p_scb->codec_updated = true;
    847     val.num = codec_type;
    848     val.hdr.status = BTA_AG_SUCCESS;
    849     APPL_TRACE_DEBUG("bta_ag_setcodec: Updated codec type %d", codec_type);
    850   } else {
    851     val.num = codec_type;
    852     val.hdr.status = BTA_AG_FAIL_RESOURCES;
    853     APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d",
    854                      codec_type);
    855   }
    856 
    857   (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG*)&val);
    858 }
    859