Home | History | Annotate | Download | only in hh
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2005-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 HID host main functions and state machine.
     22  *
     23  ******************************************************************************/
     24 
     25 #include "bt_target.h"
     26 
     27 #if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
     28 
     29 #include <string.h>
     30 
     31 #include "bta_hh_api.h"
     32 #include "bta_hh_int.h"
     33 #include "gki.h"
     34 
     35 /*****************************************************************************
     36 ** Constants and types
     37 *****************************************************************************/
     38 
     39 /* state machine action enumeration list */
     40 enum
     41 {
     42     BTA_HH_API_DISC_ACT,        /* HID host process API close action    */
     43     BTA_HH_OPEN_ACT,            /* HID host process BTA_HH_EVT_OPEN     */
     44     BTA_HH_CLOSE_ACT,           /* HID host process BTA_HH_EVT_CLOSE    */
     45     BTA_HH_DATA_ACT,            /* HID host receive data report         */
     46     BTA_HH_CTRL_DAT_ACT,
     47     BTA_HH_HANDSK_ACT,
     48     BTA_HH_START_SDP,           /* HID host inquery                     */
     49     BTA_HH_SDP_CMPL,
     50     BTA_HH_WRITE_DEV_ACT,
     51     BTA_HH_GET_DSCP_ACT,
     52     BTA_HH_MAINT_DEV_ACT,
     53     BTA_HH_OPEN_CMPL_ACT,
     54     BTA_HH_NUM_ACTIONS
     55 };
     56 
     57 #define BTA_HH_IGNORE       BTA_HH_NUM_ACTIONS
     58 
     59 /* type for action functions */
     60 typedef void (*tBTA_HH_ACTION)(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
     61 
     62 /* action functions */
     63 const tBTA_HH_ACTION bta_hh_action[] =
     64 {
     65     bta_hh_api_disc_act,
     66     bta_hh_open_act,
     67     bta_hh_close_act,
     68     bta_hh_data_act,
     69     bta_hh_ctrl_dat_act,
     70     bta_hh_handsk_act,
     71     bta_hh_start_sdp,
     72     bta_hh_sdp_cmpl,
     73     bta_hh_write_dev_act,
     74     bta_hh_get_dscp_act,
     75     bta_hh_maint_dev_act,
     76     bta_hh_open_cmpl_act
     77 };
     78 
     79 /* state table information */
     80 #define BTA_HH_ACTION                   0       /* position of action */
     81 #define BTA_HH_NEXT_STATE               1       /* position of next state */
     82 #define BTA_HH_NUM_COLS                 2       /* number of columns */
     83 
     84 /* state table for idle state */
     85 const UINT8 bta_hh_st_idle[][BTA_HH_NUM_COLS] =
     86 {
     87 /* Event                          Action                    Next state */
     88 /* BTA_HH_API_OPEN_EVT      */    {BTA_HH_START_SDP,     BTA_HH_W4_CONN_ST },
     89 /* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
     90 /* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_OPEN_ACT,      BTA_HH_W4_CONN_ST },
     91 /* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_CLOSE_ACT,     BTA_HH_IDLE_ST    },
     92 /* BTA_HH_INT_DATA_EVT      */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
     93 /* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
     94 /* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
     95 /* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
     96 /* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
     97 /* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
     98 /* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST    },
     99 /* BTA_HH_OPEN_CMPL_EVT        */  {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST    }
    100 };
    101 
    102 
    103 const UINT8 bta_hh_st_w4_conn[][BTA_HH_NUM_COLS] =
    104 {
    105 /* Event                          Action                 Next state */
    106 /* BTA_HH_API_OPEN_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
    107 /* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
    108 /* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_OPEN_ACT,      BTA_HH_W4_CONN_ST },
    109 /* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_CLOSE_ACT,     BTA_HH_IDLE_ST    },
    110 /* BTA_HH_INT_DATA_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
    111 /* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
    112 /* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
    113 /* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_SDP_CMPL,      BTA_HH_W4_CONN_ST },
    114 /* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_IGNORE  ,      BTA_HH_W4_CONN_ST },
    115 /* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
    116 /* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST    },
    117 /* BTA_HH_OPEN_CMPL_EVT     */    {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST    }
    118 };
    119 
    120 
    121 const UINT8 bta_hh_st_connected[][BTA_HH_NUM_COLS] =
    122 {
    123 /* Event                          Action                 Next state */
    124 /* BTA_HH_API_OPEN_EVT      */    {BTA_HH_IGNORE,        BTA_HH_CONN_ST    },
    125 /* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_API_DISC_ACT,  BTA_HH_CONN_ST    },
    126 /* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_OPEN_ACT,      BTA_HH_CONN_ST    },
    127 /* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_CLOSE_ACT,     BTA_HH_IDLE_ST    },
    128 /* BTA_HH_INT_DATA_EVT      */    {BTA_HH_DATA_ACT,      BTA_HH_CONN_ST    },
    129 /* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_CTRL_DAT_ACT,  BTA_HH_CONN_ST    },
    130 /* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_HANDSK_ACT,    BTA_HH_CONN_ST    },
    131 /* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_IGNORE,         BTA_HH_CONN_ST       },
    132 /* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_WRITE_DEV_ACT, BTA_HH_CONN_ST    },
    133 /* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_GET_DSCP_ACT,  BTA_HH_CONN_ST    },
    134 /* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_CONN_ST    },
    135 /* BTA_HH_OPEN_CMPL_EVT        */    {BTA_HH_IGNORE,         BTA_HH_CONN_ST    }
    136 };
    137 
    138 /* type for state table */
    139 typedef const UINT8 (*tBTA_HH_ST_TBL)[BTA_HH_NUM_COLS];
    140 
    141 /* state table */
    142 const tBTA_HH_ST_TBL bta_hh_st_tbl[] =
    143 {
    144     bta_hh_st_idle,
    145     bta_hh_st_w4_conn,
    146     bta_hh_st_connected
    147 };
    148 
    149 /*****************************************************************************
    150 ** Global data
    151 *****************************************************************************/
    152 #if BTA_DYNAMIC_MEMORY == FALSE
    153 tBTA_HH_CB  bta_hh_cb;
    154 #endif
    155 /*****************************************************************************
    156 ** Static functions
    157 *****************************************************************************/
    158 #if BTA_HH_DEBUG == TRUE
    159 static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code);
    160 static char *bta_hh_state_code(tBTA_HH_STATE state_code);
    161 #endif
    162 
    163 /*******************************************************************************
    164 **
    165 ** Function         bta_hh_sm_execute
    166 **
    167 ** Description      State machine event handling function for HID Host
    168 **
    169 **
    170 ** Returns          void
    171 **
    172 *******************************************************************************/
    173 void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA * p_data)
    174 {
    175     tBTA_HH_ST_TBL  state_table;
    176     UINT8           action;
    177     tBTA_HH         cback_data;
    178     tBTA_HH_EVT     cback_event = 0;
    179 #if BTA_HH_DEBUG == TRUE
    180     tBTA_HH_STATE   in_state ;
    181     UINT16          debug_event = event;
    182 #endif
    183 
    184     memset(&cback_data, 0, sizeof(tBTA_HH));
    185 
    186     /* handle exception, no valid control block was found */
    187     if (!p_cb)
    188     {
    189         /* BTA HH enabled already? otherwise ignore the event although it's bad*/
    190         if (bta_hh_cb.p_cback != NULL)
    191         {
    192             switch (event)
    193             {
    194             /* no control block available for new connection */
    195             case BTA_HH_API_OPEN_EVT:
    196                 cback_event = BTA_HH_OPEN_EVT;
    197                 /* build cback data */
    198                 bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr);
    199                 cback_data.conn.status  = BTA_HH_ERR_DB_FULL;
    200                 cback_data.conn.handle  = BTA_HH_INVALID_HANDLE;
    201                 break;
    202             /* DB full, BTA_HhAddDev */
    203             case BTA_HH_API_MAINT_DEV_EVT:
    204                 cback_event = p_data->api_maintdev.sub_event;
    205 
    206                 if (p_data->api_maintdev.sub_event == BTA_HH_ADD_DEV_EVT)
    207                 {
    208                     bdcpy(cback_data.dev_info.bda, p_data->api_maintdev.bda);
    209                     cback_data.dev_info.status    = BTA_HH_ERR_DB_FULL;
    210                     cback_data.dev_info.handle    = BTA_HH_INVALID_HANDLE;
    211                 }
    212                 else
    213                 {
    214                     cback_data.dev_info.status    = BTA_HH_ERR_HDL;
    215                     cback_data.dev_info.handle    = (UINT8)p_data->api_maintdev.hdr.layer_specific;
    216                 }
    217                 break;
    218             case BTA_HH_API_WRITE_DEV_EVT:
    219                 cback_event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
    220                         BTA_HH_FST_TRANS_CB_EVT;
    221                 if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL ||
    222                     p_data->api_sndcmd.t_type == HID_TRANS_SET_REPORT ||
    223                     p_data->api_sndcmd.t_type == HID_TRANS_SET_IDLE)
    224                 {
    225                     cback_data.dev_status.status = BTA_HH_ERR_HDL;
    226                     cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
    227                 }
    228                 else if (p_data->api_sndcmd.t_type != HID_TRANS_DATA &&
    229                     p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
    230                 {
    231                     cback_data.hs_data.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
    232                     cback_data.hs_data.status = BTA_HH_ERR_HDL;
    233                     /* hs_data.rsp_data will be all zero, which is not valid value */
    234                 }
    235                 else if (p_data->api_sndcmd.t_type == HID_TRANS_CONTROL &&
    236                          p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
    237                 {
    238                     cback_data.status = BTA_HH_ERR_HDL;
    239                     cback_event = BTA_HH_VC_UNPLUG_EVT;
    240                 }
    241                 else
    242                     cback_event = 0;
    243                 break;
    244 
    245             case BTA_HH_API_CLOSE_EVT:
    246                 cback_event = BTA_HH_CLOSE_EVT;
    247 
    248                 cback_data.dev_status.status = BTA_HH_ERR_HDL;
    249                 cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
    250                 break;
    251 
    252             default:
    253                 /* invalid handle, call bad API event */
    254                 APPL_TRACE_ERROR1("wrong device handle: [%d]", p_data->hdr.layer_specific);
    255                 break;
    256             }
    257            if (cback_event)
    258                (* bta_hh_cb.p_cback)(cback_event, &cback_data);
    259         }
    260     }
    261     /* corresponding CB is found, go to state machine */
    262     else
    263     {
    264 #if BTA_HH_DEBUG == TRUE
    265         in_state = p_cb->state;
    266         APPL_TRACE_EVENT3("bta_hh_sm_execute: State 0x%02x [%s], Event [%s]",
    267                           in_state, bta_hh_state_code(in_state),
    268                           bta_hh_evt_code(debug_event));
    269 #endif
    270 
    271         state_table = bta_hh_st_tbl[p_cb->state - 1];
    272 
    273         event &= 0xff;
    274 
    275         p_cb->state = state_table[event][BTA_HH_NEXT_STATE] ;
    276 
    277         if ((action = state_table[event][BTA_HH_ACTION]) != BTA_HH_IGNORE)
    278         {
    279             (*bta_hh_action[action])(p_cb, p_data);
    280         }
    281 
    282 #if BTA_HH_DEBUG == TRUE
    283         if (in_state != p_cb->state)
    284         {
    285             APPL_TRACE_DEBUG3("HH State Change: [%s] -> [%s] after Event [%s]",
    286                           bta_hh_state_code(in_state),
    287                           bta_hh_state_code(p_cb->state),
    288                           bta_hh_evt_code(debug_event));
    289         }
    290 #endif
    291     }
    292 
    293     return;
    294 }
    295 /*******************************************************************************
    296 **
    297 ** Function         bta_hh_hdl_event
    298 **
    299 ** Description      HID host main event handling function.
    300 **
    301 **
    302 ** Returns          void
    303 **
    304 *******************************************************************************/
    305 BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
    306 {
    307     UINT8           index = BTA_HH_IDX_INVALID;
    308     tBTA_HH_DEV_CB *p_cb = NULL;
    309 
    310     switch (p_msg->event)
    311     {
    312         case BTA_HH_API_ENABLE_EVT:
    313             bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
    314             break;
    315 
    316         case BTA_HH_API_DISABLE_EVT:
    317             bta_hh_api_disable();
    318             break;
    319 
    320         case BTA_HH_DISC_CMPL_EVT:          /* disable complete */
    321             bta_hh_disc_cmpl();
    322             break;
    323 
    324         default:
    325             /* all events processed in state machine need to find corresponding
    326                 CB before proceed */
    327             if (p_msg->event == BTA_HH_API_OPEN_EVT)
    328             {
    329                 index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr);
    330             }
    331             else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT)
    332             {
    333                 /* if add device */
    334                 if (((tBTA_HH_MAINT_DEV *)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT)
    335                 {
    336                     index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV *)p_msg)->bda);
    337                 }
    338                 else /* else remove device by handle */
    339                 {
    340                     index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
    341 // btla-specific ++
    342                     /* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination
    343                       * then we can get into a situation where remove_bonding is called with the index set to 0 (without getting
    344                       * cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN.
    345                       * So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
    346                       * force the index to be IDX_INVALID
    347                       */
    348                     if (bta_hh_cb.kdev[index].in_use == FALSE) {
    349                            index = BTA_HH_IDX_INVALID;
    350                     }
    351 // btla-specific --
    352                 }
    353             }
    354             else
    355                 index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
    356 
    357             if (index != BTA_HH_IDX_INVALID)
    358                 p_cb = &bta_hh_cb.kdev[index];
    359 
    360 #if BTA_HH_DEBUG
    361             APPL_TRACE_DEBUG2("bta_hh_hdl_event:: handle = %d dev_cb[%d] ", p_msg->layer_specific, index);
    362 #endif
    363             bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA *) p_msg);
    364     }
    365     return (TRUE);
    366 }
    367 
    368 /*****************************************************************************
    369 **  Debug Functions
    370 *****************************************************************************/
    371 #if BTA_HH_DEBUG
    372 /*******************************************************************************
    373 **
    374 ** Function         bta_hh_evt_code
    375 **
    376 ** Description
    377 **
    378 ** Returns          void
    379 **
    380 *******************************************************************************/
    381 static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code)
    382 {
    383   switch(evt_code)
    384     {
    385     case BTA_HH_API_DISABLE_EVT:
    386         return "BTA_HH_API_DISABLE_EVT";
    387     case BTA_HH_API_ENABLE_EVT:
    388         return "BTA_HH_API_ENABLE_EVT";
    389     case BTA_HH_API_OPEN_EVT:
    390         return "BTA_HH_API_OPEN_EVT";
    391     case BTA_HH_API_CLOSE_EVT:
    392         return "BTA_HH_API_CLOSE_EVT";
    393     case BTA_HH_INT_OPEN_EVT:
    394         return "BTA_HH_INT_OPEN_EVT";
    395     case BTA_HH_INT_CLOSE_EVT:
    396         return "BTA_HH_INT_CLOSE_EVT";
    397     case BTA_HH_INT_HANDSK_EVT:
    398         return "BTA_HH_INT_HANDSK_EVT";
    399     case BTA_HH_INT_DATA_EVT:
    400         return "BTA_HH_INT_DATA_EVT";
    401     case BTA_HH_INT_CTRL_DATA:
    402         return "BTA_HH_INT_CTRL_DATA";
    403     case BTA_HH_API_WRITE_DEV_EVT:
    404         return "BTA_HH_API_WRITE_DEV_EVT";
    405     case BTA_HH_SDP_CMPL_EVT:
    406         return "BTA_HH_SDP_CMPL_EVT";
    407     case BTA_HH_DISC_CMPL_EVT:
    408         return "BTA_HH_DISC_CMPL_EVT";
    409     case BTA_HH_API_MAINT_DEV_EVT:
    410         return "BTA_HH_API_MAINT_DEV_EVT";
    411     case BTA_HH_API_GET_DSCP_EVT:
    412         return "BTA_HH_API_GET_DSCP_EVT";
    413     case BTA_HH_OPEN_CMPL_EVT:
    414         return "BTA_HH_OPEN_CMPL_EVT";
    415     default:
    416         return "unknown HID Host event code";
    417     }
    418 }
    419 
    420 /*******************************************************************************
    421 **
    422 ** Function         bta_hh_state_code
    423 **
    424 ** Description      get string representation of HID host state code.
    425 **
    426 ** Returns          void
    427 **
    428 *******************************************************************************/
    429 static char *bta_hh_state_code(tBTA_HH_STATE state_code)
    430 {
    431     switch (state_code)
    432     {
    433     case BTA_HH_NULL_ST:
    434         return"BTA_HH_NULL_ST";
    435     case BTA_HH_IDLE_ST:
    436         return "BTA_HH_IDLE_ST";
    437     case BTA_HH_W4_CONN_ST:
    438         return "BTA_HH_W4_CONN_ST";
    439     case BTA_HH_CONN_ST:
    440         return "BTA_HH_CONN_ST";
    441     default:
    442         return "unknown HID Host state";
    443     }
    444 }
    445 
    446 #endif  /* Debug Functions */
    447 
    448 #endif /* BTA_HH_INCLUDED */
    449