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