1/******************************************************************************
2 *
3 *  Copyright (C) 2016 The Android Open Source Project
4 *  Copyright (C) 2005-2012 Broadcom Corporation
5 *
6 *  Licensed under the Apache License, Version 2.0 (the "License");
7 *  you may not use this file except in compliance with the License.
8 *  You may obtain a copy of the License at:
9 *
10 *  http://www.apache.org/licenses/LICENSE-2.0
11 *
12 *  Unless required by applicable law or agreed to in writing, software
13 *  distributed under the License is distributed on an "AS IS" BASIS,
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 *  See the License for the specific language governing permissions and
16 *  limitations under the License.
17 *
18 ******************************************************************************/
19
20/******************************************************************************
21 *
22 *  This file contains the HID host main functions and state machine.
23 *
24 ******************************************************************************/
25
26#include "bt_target.h"
27
28#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
29
30#include <string.h>
31
32#include "bta_hd_api.h"
33#include "bta_hd_int.h"
34
35/*****************************************************************************
36 * Constants and types
37 ****************************************************************************/
38
39/* state machine states */
40enum {
41  BTA_HD_INIT_ST,
42  BTA_HD_IDLE_ST,              /* not connected, waiting for connection */
43  BTA_HD_CONN_ST,              /* host connected */
44  BTA_HD_TRANSIENT_TO_INIT_ST, /* transient state: going back from CONN to INIT
45                                  */
46};
47typedef uint8_t tBTA_HD_STATE;
48
49/* state machine actions */
50enum {
51  BTA_HD_REGISTER_ACT,
52  BTA_HD_UNREGISTER_ACT,
53  BTA_HD_UNREGISTER2_ACT,
54  BTA_HD_CONNECT_ACT,
55  BTA_HD_DISCONNECT_ACT,
56  BTA_HD_ADD_DEVICE_ACT,
57  BTA_HD_REMOVE_DEVICE_ACT,
58  BTA_HD_SEND_REPORT_ACT,
59  BTA_HD_REPORT_ERROR_ACT,
60  BTA_HD_VC_UNPLUG_ACT,
61
62  BTA_HD_OPEN_ACT,
63  BTA_HD_CLOSE_ACT,
64  BTA_HD_INTR_DATA_ACT,
65  BTA_HD_GET_REPORT_ACT,
66  BTA_HD_SET_REPORT_ACT,
67  BTA_HD_SET_PROTOCOL_ACT,
68  BTA_HD_VC_UNPLUG_DONE_ACT,
69  BTA_HD_SUSPEND_ACT,
70  BTA_HD_EXIT_SUSPEND_ACT,
71
72  BTA_HD_NUM_ACTIONS
73};
74
75#define BTA_HD_IGNORE BTA_HD_NUM_ACTIONS
76
77typedef void (*tBTA_HD_ACTION)(tBTA_HD_DATA* p_data);
78
79/* action functions */
80const tBTA_HD_ACTION bta_hd_action[] = {
81    bta_hd_register_act,       bta_hd_unregister_act,  bta_hd_unregister2_act,
82    bta_hd_connect_act,        bta_hd_disconnect_act,  bta_hd_add_device_act,
83    bta_hd_remove_device_act,  bta_hd_send_report_act, bta_hd_report_error_act,
84    bta_hd_vc_unplug_act,
85
86    bta_hd_open_act,           bta_hd_close_act,       bta_hd_intr_data_act,
87    bta_hd_get_report_act,     bta_hd_set_report_act,  bta_hd_set_protocol_act,
88    bta_hd_vc_unplug_done_act, bta_hd_suspend_act,     bta_hd_exit_suspend_act,
89};
90
91/* state table information */
92#define BTA_HD_ACTION 0     /* position of action */
93#define BTA_HD_NEXT_STATE 1 /* position of next state */
94#define BTA_HD_NUM_COLS 2   /* number of columns */
95
96const uint8_t bta_hd_st_init[][BTA_HD_NUM_COLS] = {
97    /* Event                               Action                     Next state
98       */
99    /* BTA_HD_API_REGISTER_APP_EVT   */ {BTA_HD_REGISTER_ACT, BTA_HD_IDLE_ST},
100    /* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
101    /* BTA_HD_API_CONNECT_EVT        */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
102    /* BTA_HD_API_DISCONNECT_EVT     */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
103    /* BTA_HD_API_ADD_DEVICE_EVT     */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_INIT_ST},
104    /* BTA_HD_API_REMOVE_DEVICE_EVT  */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_INIT_ST},
105    /* BTA_HD_API_SEND_REPORT_EVT    */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
106    /* BTA_HD_API_REPORT_ERROR_EVT   */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
107    /* BTA_HD_API_VC_UNPLUG_EVT      */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
108    /* BTA_HD_INT_OPEN_EVT           */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
109    /* BTA_HD_INT_CLOSE_EVT          */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
110    /* BTA_HD_INT_INTR_DATA_EVT      */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
111    /* BTA_HD_INT_GET_REPORT_EVT     */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
112    /* BTA_HD_INT_SET_REPORT_EVT     */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
113    /* BTA_HD_INT_SET_PROTOCOL_EVT   */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
114    /* BTA_HD_INT_VC_UNPLUG_EVT      */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
115    /* BTA_HD_INT_SUSPEND_EVT        */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
116    /* BTA_HD_INT_EXIT_SUSPEND_EVT   */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
117};
118
119const uint8_t bta_hd_st_idle[][BTA_HD_NUM_COLS] = {
120    /* Event                               Action                     Next state
121       */
122    /* BTA_HD_API_REGISTER_APP_EVT   */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
123    /* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_UNREGISTER_ACT, BTA_HD_INIT_ST},
124    /* BTA_HD_API_CONNECT_EVT        */ {BTA_HD_CONNECT_ACT, BTA_HD_IDLE_ST},
125    /* BTA_HD_API_DISCONNECT_EVT     */ {BTA_HD_DISCONNECT_ACT, BTA_HD_IDLE_ST},
126    /* BTA_HD_API_ADD_DEVICE_EVT     */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_IDLE_ST},
127    /* BTA_HD_API_REMOVE_DEVICE_EVT  */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_IDLE_ST},
128    /* BTA_HD_API_SEND_REPORT_EVT    */ {BTA_HD_SEND_REPORT_ACT, BTA_HD_IDLE_ST},
129    /* BTA_HD_API_REPORT_ERROR_EVT   */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
130    /* BTA_HD_API_VC_UNPLUG_EVT      */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
131    /* BTA_HD_INT_OPEN_EVT           */ {BTA_HD_OPEN_ACT, BTA_HD_CONN_ST},
132    /* BTA_HD_INT_CLOSE_EVT          */ {BTA_HD_CLOSE_ACT, BTA_HD_IDLE_ST},
133    /* BTA_HD_INT_INTR_DATA_EVT      */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
134    /* BTA_HD_INT_GET_REPORT_EVT     */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
135    /* BTA_HD_INT_SET_REPORT_EVT     */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
136    /* BTA_HD_INT_SET_PROTOCOL_EVT   */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
137    /* BTA_HD_INT_VC_UNPLUG_EVT      */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
138    /* BTA_HD_INT_SUSPEND_EVT        */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
139    /* BTA_HD_INT_EXIT_SUSPEND_EVT   */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
140};
141
142const uint8_t bta_hd_st_conn[][BTA_HD_NUM_COLS] = {
143    /* Event                               Action Next state */
144    /* BTA_HD_API_REGISTER_APP_EVT   */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
145    /* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_DISCONNECT_ACT,
146                                         BTA_HD_TRANSIENT_TO_INIT_ST},
147    /* BTA_HD_API_CONNECT_EVT        */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
148    /* BTA_HD_API_DISCONNECT_EVT     */ {BTA_HD_DISCONNECT_ACT, BTA_HD_CONN_ST},
149    /* BTA_HD_API_ADD_DEVICE_EVT     */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_CONN_ST},
150    /* BTA_HD_API_REMOVE_DEVICE_EVT  */ {BTA_HD_REMOVE_DEVICE_ACT,
151                                         BTA_HD_CONN_ST},
152    /* BTA_HD_API_SEND_REPORT_EVT    */ {BTA_HD_SEND_REPORT_ACT,
153                                         BTA_HD_CONN_ST},
154    /* BTA_HD_API_REPORT_ERROR_EVT   */ {BTA_HD_REPORT_ERROR_ACT,
155                                         BTA_HD_CONN_ST},
156    /* BTA_HD_API_VC_UNPLUG_EVT      */ {BTA_HD_VC_UNPLUG_ACT, BTA_HD_CONN_ST},
157    /* BTA_HD_INT_OPEN_EVT           */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
158    /* BTA_HD_INT_CLOSE_EVT          */ {BTA_HD_CLOSE_ACT, BTA_HD_IDLE_ST},
159    /* BTA_HD_INT_INTR_DATA_EVT      */ {BTA_HD_INTR_DATA_ACT, BTA_HD_CONN_ST},
160    /* BTA_HD_INT_GET_REPORT_EVT     */ {BTA_HD_GET_REPORT_ACT, BTA_HD_CONN_ST},
161    /* BTA_HD_INT_SET_REPORT_EVT     */ {BTA_HD_SET_REPORT_ACT, BTA_HD_CONN_ST},
162    /* BTA_HD_INT_SET_PROTOCOL_EVT   */ {BTA_HD_SET_PROTOCOL_ACT,
163                                         BTA_HD_CONN_ST},
164    /* BTA_HD_INT_VC_UNPLUG_EVT      */ {BTA_HD_VC_UNPLUG_DONE_ACT,
165                                         BTA_HD_IDLE_ST},
166    /* BTA_HD_INT_SUSPEND_EVT        */ {BTA_HD_SUSPEND_ACT, BTA_HD_CONN_ST},
167    /* BTA_HD_INT_EXIT_SUSPEND_EVT   */ {BTA_HD_EXIT_SUSPEND_ACT,
168                                         BTA_HD_CONN_ST},
169};
170
171const uint8_t bta_hd_st_transient_to_init[][BTA_HD_NUM_COLS] = {
172    /* Event                               Action Next state */
173    /* BTA_HD_API_REGISTER_APP_EVT   */ {BTA_HD_IGNORE,
174                                         BTA_HD_TRANSIENT_TO_INIT_ST},
175    /* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE,
176                                         BTA_HD_TRANSIENT_TO_INIT_ST},
177    /* BTA_HD_API_CONNECT_EVT        */ {BTA_HD_IGNORE,
178                                         BTA_HD_TRANSIENT_TO_INIT_ST},
179    /* BTA_HD_API_DISCONNECT_EVT     */ {BTA_HD_IGNORE,
180                                         BTA_HD_TRANSIENT_TO_INIT_ST},
181    /* BTA_HD_API_ADD_DEVICE_EVT     */ {BTA_HD_IGNORE,
182                                         BTA_HD_TRANSIENT_TO_INIT_ST},
183    /* BTA_HD_API_REMOVE_DEVICE_EVT  */ {BTA_HD_IGNORE,
184                                         BTA_HD_TRANSIENT_TO_INIT_ST},
185    /* BTA_HD_API_SEND_REPORT_EVT    */ {BTA_HD_IGNORE,
186                                         BTA_HD_TRANSIENT_TO_INIT_ST},
187    /* BTA_HD_API_REPORT_ERROR_EVT   */ {BTA_HD_IGNORE,
188                                         BTA_HD_TRANSIENT_TO_INIT_ST},
189    /* BTA_HD_API_VC_UNPLUG_EVT      */ {BTA_HD_IGNORE,
190                                         BTA_HD_TRANSIENT_TO_INIT_ST},
191    /* BTA_HD_INT_OPEN_EVT           */ {BTA_HD_IGNORE,
192                                         BTA_HD_TRANSIENT_TO_INIT_ST},
193    /* BTA_HD_INT_CLOSE_EVT          */ {BTA_HD_UNREGISTER2_ACT,
194                                         BTA_HD_INIT_ST},
195    /* BTA_HD_INT_INTR_DATA_EVT      */ {BTA_HD_IGNORE,
196                                         BTA_HD_TRANSIENT_TO_INIT_ST},
197    /* BTA_HD_INT_GET_REPORT_EVT     */ {BTA_HD_IGNORE,
198                                         BTA_HD_TRANSIENT_TO_INIT_ST},
199    /* BTA_HD_INT_SET_REPORT_EVT     */ {BTA_HD_IGNORE,
200                                         BTA_HD_TRANSIENT_TO_INIT_ST},
201    /* BTA_HD_INT_SET_PROTOCOL_EVT   */ {BTA_HD_IGNORE,
202                                         BTA_HD_TRANSIENT_TO_INIT_ST},
203    /* BTA_HD_INT_VC_UNPLUG_EVT      */ {BTA_HD_UNREGISTER2_ACT,
204                                         BTA_HD_INIT_ST},
205    /* BTA_HD_INT_SUSPEND_EVT        */ {BTA_HD_IGNORE,
206                                         BTA_HD_TRANSIENT_TO_INIT_ST},
207    /* BTA_HD_INT_EXIT_SUSPEND_EVT   */ {BTA_HD_IGNORE,
208                                         BTA_HD_TRANSIENT_TO_INIT_ST},
209};
210
211/* type for state table */
212typedef const uint8_t (*tBTA_HD_ST_TBL)[BTA_HD_NUM_COLS];
213
214/* state table */
215const tBTA_HD_ST_TBL bta_hd_st_tbl[] = {bta_hd_st_init, bta_hd_st_idle,
216                                        bta_hd_st_conn,
217                                        bta_hd_st_transient_to_init};
218
219/*****************************************************************************
220 * Global data
221 ****************************************************************************/
222#if BTA_DYNAMIC_MEMORY == FALSE
223tBTA_HD_CB bta_hd_cb;
224#endif
225
226static const char* bta_hd_evt_code(tBTA_HD_INT_EVT evt_code);
227static const char* bta_hd_state_code(tBTA_HD_STATE state_code);
228
229/*******************************************************************************
230 *
231 * Function         bta_hd_sm_execute
232 *
233 * Description      State machine event handling function for HID Device
234 *
235 * Returns          void
236 *
237 ******************************************************************************/
238void bta_hd_sm_execute(uint16_t event, tBTA_HD_DATA* p_data) {
239  tBTA_HD_ST_TBL state_table;
240  tBTA_HD_STATE prev_state;
241  uint8_t action;
242  tBTA_HD cback_data;
243
244  APPL_TRACE_EVENT("%s: state=%s (%d) event=%s (%d)", __func__,
245                   bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state,
246                   bta_hd_evt_code(event), event);
247
248  prev_state = bta_hd_cb.state;
249
250  memset(&cback_data, 0, sizeof(tBTA_HD));
251
252  state_table = bta_hd_st_tbl[bta_hd_cb.state];
253
254  event &= 0xff;
255
256  action = state_table[event][BTA_HD_ACTION];
257  if (action < BTA_HD_IGNORE) {
258    (*bta_hd_action[action])(p_data);
259  }
260
261  bta_hd_cb.state = state_table[event][BTA_HD_NEXT_STATE];
262
263  if (bta_hd_cb.state != prev_state) {
264    APPL_TRACE_EVENT("%s: [new] state=%s (%d)", __func__,
265                     bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state);
266  }
267
268  return;
269}
270
271/*******************************************************************************
272 *
273 * Function         bta_hd_hdl_event
274 *
275 * Description      HID device main event handling function.
276 *
277 * Returns          void
278 *
279 ******************************************************************************/
280bool bta_hd_hdl_event(BT_HDR* p_msg) {
281  APPL_TRACE_API("%s: p_msg->event=%d", __func__, p_msg->event);
282
283  switch (p_msg->event) {
284    case BTA_HD_API_ENABLE_EVT:
285      bta_hd_api_enable((tBTA_HD_DATA*)p_msg);
286      break;
287
288    case BTA_HD_API_DISABLE_EVT:
289      if (bta_hd_cb.state == BTA_HD_CONN_ST) {
290        APPL_TRACE_WARNING("%s: host connected, disconnect before disabling",
291                           __func__);
292
293        // unregister (and disconnect)
294        bta_hd_cb.disable_w4_close = TRUE;
295        bta_hd_sm_execute(BTA_HD_API_UNREGISTER_APP_EVT, (tBTA_HD_DATA*)p_msg);
296      } else {
297        bta_hd_api_disable();
298      }
299      break;
300
301    default:
302      bta_hd_sm_execute(p_msg->event, (tBTA_HD_DATA*)p_msg);
303  }
304  return (TRUE);
305}
306
307static const char* bta_hd_evt_code(tBTA_HD_INT_EVT evt_code) {
308  switch (evt_code) {
309    case BTA_HD_API_REGISTER_APP_EVT:
310      return "BTA_HD_API_REGISTER_APP_EVT";
311    case BTA_HD_API_UNREGISTER_APP_EVT:
312      return "BTA_HD_API_UNREGISTER_APP_EVT";
313    case BTA_HD_API_CONNECT_EVT:
314      return "BTA_HD_API_CONNECT_EVT";
315    case BTA_HD_API_DISCONNECT_EVT:
316      return "BTA_HD_API_DISCONNECT_EVT";
317    case BTA_HD_API_ADD_DEVICE_EVT:
318      return "BTA_HD_API_ADD_DEVICE_EVT";
319    case BTA_HD_API_REMOVE_DEVICE_EVT:
320      return "BTA_HD_API_REMOVE_DEVICE_EVT";
321    case BTA_HD_API_SEND_REPORT_EVT:
322      return "BTA_HD_API_SEND_REPORT_EVT";
323    case BTA_HD_API_REPORT_ERROR_EVT:
324      return "BTA_HD_API_REPORT_ERROR_EVT";
325    case BTA_HD_API_VC_UNPLUG_EVT:
326      return "BTA_HD_API_VC_UNPLUG_EVT";
327    case BTA_HD_INT_OPEN_EVT:
328      return "BTA_HD_INT_OPEN_EVT";
329    case BTA_HD_INT_CLOSE_EVT:
330      return "BTA_HD_INT_CLOSE_EVT";
331    case BTA_HD_INT_INTR_DATA_EVT:
332      return "BTA_HD_INT_INTR_DATA_EVT";
333    case BTA_HD_INT_GET_REPORT_EVT:
334      return "BTA_HD_INT_GET_REPORT_EVT";
335    case BTA_HD_INT_SET_REPORT_EVT:
336      return "BTA_HD_INT_SET_REPORT_EVT";
337    case BTA_HD_INT_SET_PROTOCOL_EVT:
338      return "BTA_HD_INT_SET_PROTOCOL_EVT";
339    case BTA_HD_INT_VC_UNPLUG_EVT:
340      return "BTA_HD_INT_VC_UNPLUG_EVT";
341    case BTA_HD_INT_SUSPEND_EVT:
342      return "BTA_HD_INT_SUSPEND_EVT";
343    case BTA_HD_INT_EXIT_SUSPEND_EVT:
344      return "BTA_HD_INT_EXIT_SUSPEND_EVT";
345    default:
346      return "<unknown>";
347  }
348}
349
350static const char* bta_hd_state_code(tBTA_HD_STATE state_code) {
351  switch (state_code) {
352    case BTA_HD_INIT_ST:
353      return "BTA_HD_INIT_ST";
354    case BTA_HD_IDLE_ST:
355      return "BTA_HD_IDLE_ST";
356    case BTA_HD_CONN_ST:
357      return "BTA_HD_CONN_ST";
358    case BTA_HD_TRANSIENT_TO_INIT_ST:
359      return "BTA_HD_TRANSIENT_TO_INIT_ST";
360    default:
361      return "<unknown>";
362  }
363}
364
365#endif /* BTA_HD_INCLUDED */
366