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_DEBUG ("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     UNUSED(p_data);
    338 
    339     /* reopen registered servers */
    340     bta_ag_start_servers(p_scb, p_scb->reg_services);
    341 
    342     /* reinitialize stuff */
    343 
    344     /* call open cback w. failure */
    345     bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP);
    346 }
    347 
    348 /*******************************************************************************
    349 **
    350 ** Function         bta_ag_open_fail
    351 **
    352 ** Description      open connection failed.
    353 **
    354 **
    355 ** Returns          void
    356 **
    357 *******************************************************************************/
    358 void bta_ag_open_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    359 {
    360     /* call open cback w. failure */
    361     bta_ag_cback_open(p_scb, p_data, BTA_AG_FAIL_RESOURCES);
    362 }
    363 
    364 /*******************************************************************************
    365 **
    366 ** Function         bta_ag_rfc_fail
    367 **
    368 ** Description      RFCOMM connection failed.
    369 **
    370 **
    371 ** Returns          void
    372 **
    373 *******************************************************************************/
    374 void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    375 {
    376     UNUSED(p_data);
    377 
    378     /* reinitialize stuff */
    379     p_scb->conn_handle = 0;
    380     p_scb->conn_service = 0;
    381     p_scb->peer_features = 0;
    382 #if (BTM_WBS_INCLUDED == TRUE )
    383     p_scb->peer_codecs = BTA_AG_CODEC_NONE;
    384     p_scb->sco_codec = BTA_AG_CODEC_NONE;
    385 #endif
    386     p_scb->role = 0;
    387     p_scb->svc_conn = FALSE;
    388     p_scb->hsp_version = HSP_VERSION_1_2;
    389 
    390     /* reopen registered servers */
    391     bta_ag_start_servers(p_scb, p_scb->reg_services);
    392 
    393     /* call open cback w. failure */
    394     bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_RFCOMM);
    395 }
    396 
    397 /*******************************************************************************
    398 **
    399 ** Function         bta_ag_rfc_close
    400 **
    401 ** Description      RFCOMM connection closed.
    402 **
    403 **
    404 ** Returns          void
    405 **
    406 *******************************************************************************/
    407 void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    408 {
    409     tBTA_AG_CLOSE    close;
    410     tBTA_SERVICE_MASK services;
    411     int i, num_active_conn = 0;
    412     UNUSED(p_data);
    413 
    414 #ifdef  _WIN32_WCE
    415     /* The BTE RFCOMM automatically removes the connection when closed, but BTW does not */
    416     if (p_scb->conn_handle != 0)
    417         RFCOMM_RemoveConnection (p_scb->conn_handle);
    418 #endif
    419 
    420     /* reinitialize stuff */
    421     p_scb->conn_service = 0;
    422     p_scb->peer_features = 0;
    423 #if (BTM_WBS_INCLUDED == TRUE )
    424     p_scb->peer_codecs = BTA_AG_CODEC_NONE;
    425     p_scb->sco_codec = BTA_AG_CODEC_NONE;
    426     /* Clear these flags upon SLC teardown */
    427     p_scb->codec_updated = FALSE;
    428     p_scb->codec_fallback = FALSE;
    429     p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
    430 #endif
    431     p_scb->role = 0;
    432     p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    433     p_scb->svc_conn = FALSE;
    434     p_scb->hsp_version = HSP_VERSION_1_2;
    435     bta_ag_at_reinit(&p_scb->at_cb);
    436 
    437     /* stop timers */
    438     bta_sys_stop_timer(&p_scb->act_timer);
    439 #if (BTM_WBS_INCLUDED == TRUE)
    440     bta_sys_stop_timer(&p_scb->cn_timer);
    441 #endif
    442 
    443     close.hdr.handle = bta_ag_scb_to_idx(p_scb);
    444     close.hdr.app_id = p_scb->app_id;
    445     bdcpy(close.bd_addr, p_scb->peer_addr);
    446 
    447     bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    448 
    449     /* call close call-out */
    450     bta_ag_co_data_close(close.hdr.handle);
    451 
    452     /* call close cback */
    453     (*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG *) &close);
    454 
    455     /* if not deregistering (deallocating) reopen registered servers */
    456     if (p_scb->dealloc == FALSE)
    457     {
    458         /* Clear peer bd_addr so instance can be reused */
    459         bdcpy(p_scb->peer_addr, bd_addr_null);
    460 
    461         /* start only unopened server */
    462         services = p_scb->reg_services;
    463         for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++)
    464         {
    465             if(p_scb->serv_handle[i])
    466                 services &= ~((tBTA_SERVICE_MASK)1 << (BTA_HSP_SERVICE_ID + i));
    467         }
    468         bta_ag_start_servers(p_scb, services);
    469 
    470         p_scb->conn_handle = 0;
    471 
    472         /* Make sure SCO state is BTA_AG_SCO_SHUTDOWN_ST */
    473         bta_ag_sco_shutdown(p_scb, NULL);
    474 
    475         /* Check if all the SLCs are down */
    476         for (i = 0; i < BTA_AG_NUM_SCB; i++)
    477         {
    478             if (bta_ag_cb.scb[i].in_use && bta_ag_cb.scb[i].svc_conn)
    479                 num_active_conn++;
    480         }
    481 
    482         if(!num_active_conn)
    483         {
    484             bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    485         }
    486 
    487     }
    488     /* else close port and deallocate scb */
    489     else
    490     {
    491         RFCOMM_RemoveServer(p_scb->conn_handle);
    492         bta_ag_scb_dealloc(p_scb);
    493     }
    494 }
    495 
    496 /*******************************************************************************
    497 **
    498 ** Function         bta_ag_rfc_open
    499 **
    500 ** Description      Handle RFCOMM channel open.
    501 **
    502 **
    503 ** Returns          void
    504 **
    505 *******************************************************************************/
    506 void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    507 {
    508     /* initialize AT feature variables */
    509     p_scb->clip_enabled = FALSE;
    510     p_scb->ccwa_enabled = FALSE;
    511     p_scb->cmer_enabled = FALSE;
    512     p_scb->cmee_enabled = FALSE;
    513     p_scb->inband_enabled = ((p_scb->features & BTA_AG_FEAT_INBAND) == BTA_AG_FEAT_INBAND);
    514 
    515     /* set up AT command interpreter */
    516     p_scb->at_cb.p_at_tbl = (tBTA_AG_AT_CMD *) bta_ag_at_tbl[p_scb->conn_service];
    517     p_scb->at_cb.p_cmd_cback = (tBTA_AG_AT_CMD_CBACK *) bta_ag_at_cback_tbl[p_scb->conn_service];
    518     p_scb->at_cb.p_err_cback = (tBTA_AG_AT_ERR_CBACK *) bta_ag_at_err_cback;
    519     p_scb->at_cb.p_user = p_scb;
    520     p_scb->at_cb.cmd_max_len = BTA_AG_CMD_MAX;
    521     bta_ag_at_init(&p_scb->at_cb);
    522 
    523     /* call app open call-out */
    524     bta_ag_co_data_open(bta_ag_scb_to_idx(p_scb), bta_ag_svc_id[p_scb->conn_service]);
    525 
    526     bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    527 
    528     bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS);
    529 
    530     if (p_scb->conn_service == BTA_AG_HFP)
    531     {
    532         /* if hfp start timer for service level conn */
    533         bta_sys_start_timer(&p_scb->act_timer, BTA_AG_SVC_TOUT_EVT, p_bta_ag_cfg->conn_tout);
    534     }
    535     else
    536     {
    537         /* else service level conn is open */
    538         bta_ag_svc_conn_open(p_scb, p_data);
    539     }
    540 }
    541 
    542 /*******************************************************************************
    543 **
    544 ** Function         bta_ag_rfc_acp_open
    545 **
    546 ** Description      Handle RFCOMM channel open when accepting connection.
    547 **
    548 **
    549 ** Returns          void
    550 **
    551 *******************************************************************************/
    552 void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    553 {
    554     UINT16          lcid;
    555     int             i;
    556     tBTA_AG_SCB     *ag_scb, *other_scb;
    557     BD_ADDR         dev_addr;
    558     int             status;
    559 
    560     /* set role */
    561     p_scb->role = BTA_AG_ACP;
    562 
    563     APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d",
    564                        p_scb->serv_handle[0], p_scb->serv_handle[1]);
    565 
    566     /* get bd addr of peer */
    567     if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid)))
    568     {
    569         APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d", status);
    570     }
    571 
    572     /* Collision Handling */
    573     for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
    574     {
    575         if ((ag_scb->in_use) && (ag_scb->colli_tmr_on))
    576         {
    577             /* stop collision timer */
    578             ag_scb->colli_tmr_on = FALSE;
    579             bta_sys_stop_timer (&ag_scb->colli_timer);
    580 
    581             if (bdcmp (dev_addr, ag_scb->peer_addr) == 0)
    582             {
    583                 /* If incoming and outgoing device are same, nothing more to do.            */
    584                 /* Outgoing conn will be aborted because we have successful incoming conn.  */
    585             }
    586             else
    587             {
    588                 /* Resume outgoing connection. */
    589                 other_scb = bta_ag_get_other_idle_scb (p_scb);
    590                 if (other_scb)
    591                 {
    592                     bdcpy(other_scb->peer_addr, ag_scb->peer_addr);
    593                     other_scb->open_services = ag_scb->open_services;
    594                     other_scb->cli_sec_mask = ag_scb->cli_sec_mask;
    595 
    596                     bta_ag_resume_open (other_scb);
    597                 }
    598             }
    599 
    600             break;
    601         }
    602     }
    603 
    604     bdcpy (p_scb->peer_addr, dev_addr);
    605 
    606     /* determine connected service from port handle */
    607     for (i = 0; i < BTA_AG_NUM_IDX; i++)
    608     {
    609         APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d",
    610                            i, p_scb->serv_handle[i], p_data->rfc.port_handle);
    611 
    612         if (p_scb->serv_handle[i] == p_data->rfc.port_handle)
    613         {
    614             p_scb->conn_service = i;
    615             p_scb->conn_handle = p_data->rfc.port_handle;
    616             break;
    617         }
    618     }
    619 
    620     APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d",
    621                        p_scb->conn_service, p_scb->conn_handle);
    622 
    623     /* close any unopened server */
    624     bta_ag_close_servers(p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service]));
    625 
    626     /* do service discovery to get features */
    627     bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
    628 
    629     /* continue with common open processing */
    630     bta_ag_rfc_open(p_scb, p_data);
    631 
    632 
    633 
    634 }
    635 
    636 /*******************************************************************************
    637 **
    638 ** Function         bta_ag_rfc_data
    639 **
    640 ** Description      Read and process data from RFCOMM.
    641 **
    642 **
    643 ** Returns          void
    644 **
    645 *******************************************************************************/
    646 void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    647 {
    648     UINT16  len;
    649     char    buf[BTA_AG_RFC_READ_MAX];
    650     UNUSED(p_data);
    651 
    652     memset(buf, 0, BTA_AG_RFC_READ_MAX);
    653 
    654     /* do the following */
    655     for(;;)
    656     {
    657         /* read data from rfcomm; if bad status, we're done */
    658         if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) != PORT_SUCCESS)
    659         {
    660             break;
    661         }
    662 
    663         /* if no data, we're done */
    664         if (len == 0)
    665         {
    666             break;
    667         }
    668 
    669         /* run AT command interpreter on data */
    670         bta_ag_at_parse(&p_scb->at_cb, buf, len);
    671 
    672         /* no more data to read, we're done */
    673         if (len < BTA_AG_RFC_READ_MAX)
    674         {
    675             break;
    676         }
    677     }
    678 }
    679 
    680 /*******************************************************************************
    681 **
    682 ** Function         bta_ag_start_close
    683 **
    684 ** Description      Start the process of closing SCO and RFCOMM connection.
    685 **
    686 **
    687 ** Returns          void
    688 **
    689 *******************************************************************************/
    690 void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    691 {
    692     /* Take the link out of sniff and set L2C idle time to 0 */
    693     bta_dm_pm_active(p_scb->peer_addr);
    694     L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0);
    695 
    696     /* if SCO is open close SCO and wait on RFCOMM close */
    697     if (bta_ag_sco_is_open(p_scb))
    698     {
    699         p_scb->post_sco = BTA_AG_POST_SCO_CLOSE_RFC;
    700     }
    701     else
    702     {
    703         p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    704         bta_ag_rfc_do_close(p_scb, p_data);
    705     }
    706 
    707     /* always do SCO shutdown to handle all SCO corner cases */
    708     bta_ag_sco_shutdown(p_scb, p_data);
    709 }
    710 
    711 /*******************************************************************************
    712 **
    713 ** Function         bta_ag_post_sco_open
    714 **
    715 ** Description      Perform post-SCO open action, if any
    716 **
    717 **
    718 ** Returns          void
    719 **
    720 *******************************************************************************/
    721 void bta_ag_post_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    722 {
    723     switch (p_scb->post_sco)
    724     {
    725         case BTA_AG_POST_SCO_RING:
    726             bta_ag_send_ring(p_scb, p_data);
    727             p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    728             break;
    729 
    730         case BTA_AG_POST_SCO_CALL_CONN:
    731             bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
    732             p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    733             break;
    734 
    735         default:
    736             break;
    737     }
    738 }
    739 
    740 /*******************************************************************************
    741 **
    742 ** Function         bta_ag_post_sco_close
    743 **
    744 ** Description      Perform post-SCO close action, if any
    745 **
    746 **
    747 ** Returns          void
    748 **
    749 *******************************************************************************/
    750 void bta_ag_post_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    751 {
    752     switch (p_scb->post_sco)
    753     {
    754         case BTA_AG_POST_SCO_CLOSE_RFC:
    755             bta_ag_rfc_do_close(p_scb, p_data);
    756             p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    757             break;
    758 
    759         case BTA_AG_POST_SCO_CALL_CONN:
    760             bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
    761             p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    762             break;
    763 
    764         case BTA_AG_POST_SCO_CALL_ORIG:
    765             bta_ag_send_call_inds(p_scb, BTA_AG_OUT_CALL_ORIG_RES);
    766             p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    767             break;
    768 
    769         case BTA_AG_POST_SCO_CALL_END:
    770             bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
    771             p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    772             break;
    773 
    774         case BTA_AG_POST_SCO_CALL_END_INCALL:
    775             bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
    776 
    777             /* Sending callsetup IND and Ring were defered to after SCO close. */
    778             bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_RES);
    779 
    780             if (bta_ag_inband_enabled(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
    781             {
    782                 p_scb->post_sco = BTA_AG_POST_SCO_RING;
    783                 bta_ag_sco_open(p_scb, p_data);
    784             }
    785             else
    786             {
    787                 p_scb->post_sco = BTA_AG_POST_SCO_NONE;
    788                 bta_ag_send_ring(p_scb, p_data);
    789             }
    790             break;
    791 
    792         default:
    793             break;
    794     }
    795 }
    796 
    797 /*******************************************************************************
    798 **
    799 ** Function         bta_ag_svc_conn_open
    800 **
    801 ** Description      Service level connection opened
    802 **
    803 **
    804 ** Returns          void
    805 **
    806 *******************************************************************************/
    807 void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    808 {
    809     tBTA_AG_CONN evt;
    810     UNUSED(p_data);
    811 
    812     if (!p_scb->svc_conn)
    813     {
    814         /* set state variable */
    815         p_scb->svc_conn = TRUE;
    816 
    817         /* Clear AT+BIA mask from previous SLC if any. */
    818         p_scb->bia_masked_out = 0;
    819 
    820         /* stop timer */
    821         bta_sys_stop_timer(&p_scb->act_timer);
    822 
    823         /* call callback */
    824         evt.hdr.handle = bta_ag_scb_to_idx(p_scb);
    825         evt.hdr.app_id = p_scb->app_id;
    826         evt.peer_feat = p_scb->peer_features;
    827         bdcpy(evt.bd_addr, p_scb->peer_addr);
    828 #if (BTM_WBS_INCLUDED == TRUE )
    829         evt.peer_codec  = p_scb->peer_codecs;
    830 #endif
    831 
    832         if ((p_scb->call_ind != BTA_AG_CALL_INACTIVE) ||
    833             (p_scb->callsetup_ind != BTA_AG_CALLSETUP_NONE))
    834         {
    835             bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    836         }
    837 
    838         (*bta_ag_cb.p_cback)(BTA_AG_CONN_EVT, (tBTA_AG *) &evt);
    839     }
    840 }
    841 
    842 /*******************************************************************************
    843 **
    844 ** Function         bta_ag_ci_rx_data
    845 **
    846 ** Description      Send result code
    847 **
    848 ** Returns          void
    849 **
    850 *******************************************************************************/
    851 void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    852 {
    853     UINT16 len;
    854     tBTA_AG_CI_RX_WRITE *p_rx_write_msg = (tBTA_AG_CI_RX_WRITE *)p_data;
    855     char *p_data_area = (char *)(p_rx_write_msg+1);     /* Point to data area after header */
    856 
    857     /* send to RFCOMM */
    858     PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len);
    859 }
    860 
    861 /*******************************************************************************
    862 **
    863 ** Function         bta_ag_rcvd_slc_ready
    864 **
    865 ** Description      Handles SLC ready call-in in case of pass-through mode.
    866 **
    867 ** Returns          void
    868 **
    869 *******************************************************************************/
    870 void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    871 {
    872     UNUSED(p_data);
    873 
    874     APPL_TRACE_DEBUG("bta_ag_rcvd_slc_ready: handle = %d", bta_ag_scb_to_idx(p_scb));
    875 
    876     if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH)
    877     {
    878         /* In pass-through mode, BTA knows that SLC is ready only through call-in. */
    879         bta_ag_svc_conn_open(p_scb, NULL);
    880     }
    881 }
    882 
    883 /*******************************************************************************
    884 **
    885 ** Function         bta_ag_setcodec
    886 **
    887 ** Description      Handle API SetCodec
    888 **
    889 **
    890 ** Returns          void
    891 **
    892 *******************************************************************************/
    893 void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    894 {
    895 #if (BTM_WBS_INCLUDED == TRUE )
    896     tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec;
    897     tBTA_AG_VAL        val;
    898 
    899     /* Check if the requested codec type is valid */
    900     if((codec_type != BTA_AG_CODEC_NONE) &&
    901        (codec_type != BTA_AG_CODEC_CVSD) &&
    902        (codec_type != BTA_AG_CODEC_MSBC))
    903     {
    904         val.num = codec_type;
    905         val.hdr.status = BTA_AG_FAIL_RESOURCES;
    906         APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type);
    907         (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val);
    908         return;
    909     }
    910 
    911     if((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) ||
    912         (codec_type == BTA_AG_CODEC_CVSD))
    913     {
    914         p_scb->sco_codec = codec_type;
    915         p_scb->codec_updated = TRUE;
    916         val.num = codec_type;
    917         val.hdr.status = BTA_AG_SUCCESS;
    918         APPL_TRACE_DEBUG("bta_ag_setcodec: Updated codec type %d", codec_type);
    919     }
    920     else
    921     {
    922         val.num = codec_type;
    923         val.hdr.status = BTA_AG_FAIL_RESOURCES;
    924         APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type);
    925     }
    926 
    927     (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val);
    928 #endif
    929 }
    930 
    931