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