Home | History | Annotate | Download | only in ag
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2004-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 the audio gateway functions controlling the RFCOMM
     22  *  connections.
     23  *
     24  ******************************************************************************/
     25 
     26 #include <string.h>
     27 #include "bta_api.h"
     28 #include "bta_sys.h"
     29 #include "bta_ag_api.h"
     30 #include "bta_ag_int.h"
     31 #include "bta_ag_co.h"
     32 #include "btm_api.h"
     33 #include "port_api.h"
     34 #include "rfcdefs.h"
     35 #include "gki.h"
     36 #include "bd.h"
     37 #include "utl.h"
     38 
     39 /* Event mask for RfCOMM port callback */
     40 #define BTA_AG_PORT_EV_MASK         PORT_EV_RXCHAR
     41 
     42 /* each scb has its own rfcomm callbacks */
     43 void bta_ag_port_cback_1(UINT32 code, UINT16 port_handle);
     44 void bta_ag_port_cback_2(UINT32 code, UINT16 port_handle);
     45 void bta_ag_port_cback_3(UINT32 code, UINT16 port_handle);
     46 
     47 void bta_ag_mgmt_cback_1(UINT32 code, UINT16 port_handle);
     48 void bta_ag_mgmt_cback_2(UINT32 code, UINT16 port_handle);
     49 void bta_ag_mgmt_cback_3(UINT32 code, UINT16 port_handle);
     50 
     51 int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len);
     52 int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len);
     53 int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len);
     54 
     55 /* rfcomm callback function tables */
     56 typedef tPORT_CALLBACK *tBTA_AG_PORT_CBACK;
     57 const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] =
     58 {
     59     bta_ag_port_cback_1,
     60     bta_ag_port_cback_2,
     61     bta_ag_port_cback_3
     62 };
     63 
     64 const tBTA_AG_PORT_CBACK bta_ag_mgmt_cback_tbl[] =
     65 {
     66     bta_ag_mgmt_cback_1,
     67     bta_ag_mgmt_cback_2,
     68     bta_ag_mgmt_cback_3
     69 };
     70 
     71 typedef tPORT_DATA_CALLBACK *tBTA_AG_DATA_CBACK;
     72 const tBTA_AG_DATA_CBACK bta_ag_data_cback_tbl[] =
     73 {
     74     bta_ag_data_cback_1,
     75     bta_ag_data_cback_2,
     76     bta_ag_data_cback_3
     77 };
     78 
     79 /*******************************************************************************
     80 **
     81 ** Function         bta_ag_port_cback
     82 **
     83 ** Description      RFCOMM Port callback
     84 **
     85 **
     86 ** Returns          void
     87 **
     88 *******************************************************************************/
     89 static void bta_ag_port_cback(UINT32 code, UINT16 port_handle, UINT16 handle)
     90 {
     91     BT_HDR      *p_buf;
     92     tBTA_AG_SCB *p_scb;
     93     UNUSED(code);
     94 
     95     if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL)
     96     {
     97         /* ignore port events for port handles other than connected handle */
     98         if (port_handle != p_scb->conn_handle)
     99         {
    100             APPL_TRACE_DEBUG("ag_port_cback ignoring handle:%d conn_handle = %d other handle = %d",
    101                               port_handle, p_scb->conn_handle, handle);
    102             return;
    103         }
    104 
    105         if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
    106         {
    107             p_buf->event = BTA_AG_RFC_DATA_EVT;
    108             p_buf->layer_specific = handle;
    109             bta_sys_sendmsg(p_buf);
    110         }
    111     }
    112 }
    113 
    114 /*******************************************************************************
    115 **
    116 ** Function         bta_ag_mgmt_cback
    117 **
    118 ** Description      RFCOMM management callback
    119 **
    120 **
    121 ** Returns          void
    122 **
    123 *******************************************************************************/
    124 static void bta_ag_mgmt_cback(UINT32 code, UINT16 port_handle, UINT16 handle)
    125 {
    126     tBTA_AG_RFC     *p_buf;
    127     tBTA_AG_SCB     *p_scb;
    128     UINT16          event;
    129     UINT8           i;
    130     BOOLEAN         found_handle = FALSE;
    131 
    132     APPL_TRACE_DEBUG("ag_mgmt_cback : code = %d, port_handle = %d, handle = %d",
    133                         code, port_handle, handle);
    134 
    135     if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL)
    136     {
    137         /* ignore close event for port handles other than connected handle */
    138         if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle))
    139         {
    140             APPL_TRACE_DEBUG("ag_mgmt_cback ignoring handle:%d", port_handle);
    141             return;
    142         }
    143 
    144         if (code == PORT_SUCCESS)
    145         {
    146             if (p_scb->conn_handle)     /* Outgoing connection */
    147             {
    148                 if (port_handle == p_scb->conn_handle)
    149                     found_handle = TRUE;
    150             }
    151             else                        /* Incoming connection */
    152             {
    153                 for (i = 0; i < BTA_AG_NUM_IDX; i++)
    154                 {
    155                     if (port_handle == p_scb->serv_handle[i])
    156                         found_handle = TRUE;
    157                 }
    158             }
    159 
    160             if (!found_handle)
    161             {
    162                 APPL_TRACE_ERROR ("bta_ag_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle);
    163                 return;
    164             }
    165 
    166             event = BTA_AG_RFC_OPEN_EVT;
    167         }
    168         /* distinguish server close events */
    169         else if (port_handle == p_scb->conn_handle)
    170         {
    171             event = BTA_AG_RFC_CLOSE_EVT;
    172         }
    173         else
    174         {
    175             event = BTA_AG_RFC_SRV_CLOSE_EVT;
    176         }
    177 
    178         if ((p_buf = (tBTA_AG_RFC *) GKI_getbuf(sizeof(tBTA_AG_RFC))) != NULL)
    179         {
    180             p_buf->hdr.event = event;
    181             p_buf->hdr.layer_specific = handle;
    182             p_buf->port_handle = port_handle;
    183             bta_sys_sendmsg(p_buf);
    184         }
    185     }
    186 }
    187 
    188 /*******************************************************************************
    189 **
    190 ** Function         bta_ag_data_cback
    191 **
    192 ** Description      RFCOMM data callback
    193 **
    194 **
    195 ** Returns          void
    196 **
    197 *******************************************************************************/
    198 static int bta_ag_data_cback(UINT16 port_handle, void *p_data, UINT16 len, UINT16 handle)
    199 {
    200     UNUSED(port_handle);
    201 
    202     /* call data call-out directly */
    203     bta_ag_co_tx_write(handle, (UINT8 *) p_data, len);
    204     return 0;
    205 }
    206 
    207 /*******************************************************************************
    208 **
    209 ** Function         bta_ag_port_cback_1 to 3
    210 **                  bta_ag_mgmt_cback_1 to 3
    211 **
    212 ** Description      RFCOMM callback functions.  This is an easy way to
    213 **                  distinguish scb from the callback.
    214 **
    215 **
    216 ** Returns          void
    217 **
    218 *******************************************************************************/
    219 void bta_ag_mgmt_cback_1(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 1);}
    220 void bta_ag_mgmt_cback_2(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 2);}
    221 void bta_ag_mgmt_cback_3(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 3);}
    222 void bta_ag_port_cback_1(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 1);}
    223 void bta_ag_port_cback_2(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 2);}
    224 void bta_ag_port_cback_3(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 3);}
    225 
    226 /*******************************************************************************
    227 **
    228 ** Function         bta_ag_data_cback_1 to 3
    229 **
    230 ** Description      RFCOMM data callback functions.  This is an easy way to
    231 **                  distinguish scb from the callback.
    232 **
    233 **
    234 ** Returns          void
    235 **
    236 *******************************************************************************/
    237 int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len)
    238 {
    239     return bta_ag_data_cback(port_handle, p_data, len, 1);
    240 }
    241 int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len)
    242 {
    243     return bta_ag_data_cback(port_handle, p_data, len, 2);
    244 }
    245 int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len)
    246 {
    247     return bta_ag_data_cback(port_handle, p_data, len, 3);
    248 }
    249 
    250 /*******************************************************************************
    251 **
    252 ** Function         bta_ag_setup_port
    253 **
    254 ** Description      Setup RFCOMM port for use by AG.
    255 **
    256 **
    257 ** Returns          void
    258 **
    259 *******************************************************************************/
    260 void bta_ag_setup_port(tBTA_AG_SCB *p_scb, UINT16 handle)
    261 {
    262     UINT16 i = bta_ag_scb_to_idx(p_scb) - 1;
    263 
    264     /* set up data callback if using pass through mode */
    265     if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH)
    266     {
    267         PORT_SetDataCallback(handle, bta_ag_data_cback_tbl[i]);
    268     }
    269 
    270     PORT_SetEventMask(handle, BTA_AG_PORT_EV_MASK);
    271     PORT_SetEventCallback(handle, bta_ag_port_cback_tbl[i]);
    272 }
    273 
    274 /*******************************************************************************
    275 **
    276 ** Function         bta_ag_start_servers
    277 **
    278 ** Description      Setup RFCOMM servers for use by AG.
    279 **
    280 **
    281 ** Returns          void
    282 **
    283 *******************************************************************************/
    284 void bta_ag_start_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services)
    285 {
    286     int i;
    287     int bta_ag_port_status;
    288 
    289     services >>= BTA_HSP_SERVICE_ID;
    290     for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1)
    291     {
    292         /* if service is set in mask */
    293         if (services & 1)
    294         {
    295             BTM_SetSecurityLevel(FALSE, "", bta_ag_sec_id[i], p_scb->serv_sec_mask,
    296                 BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_ag_cb.profile[i].scn);
    297 
    298             bta_ag_port_status =  RFCOMM_CreateConnection(bta_ag_uuid[i], bta_ag_cb.profile[i].scn,
    299                 TRUE, BTA_AG_MTU, (UINT8 *) bd_addr_any, &(p_scb->serv_handle[i]),
    300                 bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
    301 
    302             if( bta_ag_port_status  == PORT_SUCCESS )
    303             {
    304                 bta_ag_setup_port(p_scb, p_scb->serv_handle[i]);
    305             }
    306             else
    307             {
    308                 /* TODO: CR#137125 to handle to error properly */
    309                 APPL_TRACE_DEBUG("bta_ag_start_servers: RFCOMM_CreateConnection returned error:%d", bta_ag_port_status);
    310             }
    311         }
    312     }
    313 }
    314 
    315 /*******************************************************************************
    316 **
    317 ** Function         bta_ag_close_servers
    318 **
    319 ** Description      Close RFCOMM servers port for use by AG.
    320 **
    321 **
    322 ** Returns          void
    323 **
    324 *******************************************************************************/
    325 void bta_ag_close_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services)
    326 {
    327     int i;
    328 
    329     services >>= BTA_HSP_SERVICE_ID;
    330     for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1)
    331     {
    332         /* if service is set in mask */
    333         if (services & 1)
    334         {
    335             RFCOMM_RemoveServer(p_scb->serv_handle[i]);
    336             p_scb->serv_handle[i] = 0;
    337         }
    338     }
    339 }
    340 
    341 /*******************************************************************************
    342 **
    343 ** Function         bta_ag_is_server_closed
    344 **
    345 ** Description      Returns TRUE if all servers are closed.
    346 **
    347 **
    348 ** Returns          TRUE if all servers are closed, FALSE otherwise
    349 **
    350 *******************************************************************************/
    351 BOOLEAN bta_ag_is_server_closed (tBTA_AG_SCB *p_scb)
    352 {
    353     UINT8 xx;
    354     BOOLEAN is_closed = TRUE;
    355 
    356     for (xx = 0; xx < BTA_AG_NUM_IDX; xx++)
    357     {
    358         if (p_scb->serv_handle[xx] != 0)
    359             is_closed = FALSE;
    360     }
    361 
    362     return is_closed;
    363 }
    364 
    365 /*******************************************************************************
    366 **
    367 ** Function         bta_ag_rfc_do_open
    368 **
    369 ** Description      Open an RFCOMM connection to the peer device.
    370 **
    371 **
    372 ** Returns          void
    373 **
    374 *******************************************************************************/
    375 void bta_ag_rfc_do_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    376 {
    377     BTM_SetSecurityLevel(TRUE, "", bta_ag_sec_id[p_scb->conn_service],
    378         p_scb->cli_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, p_scb->peer_scn);
    379 
    380     if (RFCOMM_CreateConnection(bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn,
    381             FALSE, BTA_AG_MTU, p_scb->peer_addr, &(p_scb->conn_handle),
    382             bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]) == PORT_SUCCESS)
    383     {
    384         bta_ag_setup_port(p_scb, p_scb->conn_handle);
    385         APPL_TRACE_DEBUG("bta_ag_rfc_do_open : conn_handle = %d", p_scb->conn_handle);
    386     }
    387     /* RFCOMM create connection failed; send ourselves RFCOMM close event */
    388     else
    389     {
    390         bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, p_data);
    391     }
    392 }
    393 
    394 /*******************************************************************************
    395 **
    396 ** Function         bta_ag_rfc_do_close
    397 **
    398 ** Description      Close RFCOMM connection.
    399 **
    400 **
    401 ** Returns          void
    402 **
    403 *******************************************************************************/
    404 void bta_ag_rfc_do_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    405 {
    406     tBTA_AG_RFC     *p_buf;
    407     UNUSED(p_data);
    408 
    409     if (p_scb->conn_handle)
    410     {
    411         RFCOMM_RemoveConnection(p_scb->conn_handle);
    412     }
    413     else
    414     {
    415         /* Close API was called while AG is in Opening state.               */
    416         /* Need to trigger the state machine to send callback to the app    */
    417         /* and move back to INIT state.                                     */
    418         if ((p_buf = (tBTA_AG_RFC *) GKI_getbuf(sizeof(tBTA_AG_RFC))) != NULL)
    419         {
    420             p_buf->hdr.event = BTA_AG_RFC_CLOSE_EVT;
    421             p_buf->hdr.layer_specific = bta_ag_scb_to_idx(p_scb);
    422             bta_sys_sendmsg(p_buf);
    423         }
    424 
    425         /* Cancel SDP if it had been started. */
    426         /*
    427         if(p_scb->p_disc_db)
    428         {
    429             (void)SDP_CancelServiceSearch (p_scb->p_disc_db);
    430         }
    431         */
    432     }
    433 
    434 #ifdef _WIN32_WCE
    435     {
    436         /* Windows versions of RFCOMM does NOT generate a closed callback when we close */
    437         tPORT_CALLBACK *rfc_mgmt_cback = bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1];
    438 
    439         if (rfc_mgmt_cback)
    440         {
    441             (rfc_mgmt_cback)(PORT_CLOSED, p_scb->conn_handle);
    442         }
    443     }
    444 #endif
    445 }
    446 
    447