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 */
40 enum {
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 };
47 typedef uint8_t tBTA_HD_STATE;
48
49 /* state machine actions */
50 enum {
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
77 typedef void (*tBTA_HD_ACTION)(tBTA_HD_DATA* p_data);
78
79 /* action functions */
80 const 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
96 const 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
119 const 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
142 const 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
171 const 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 */
212 typedef const uint8_t (*tBTA_HD_ST_TBL)[BTA_HD_NUM_COLS];
213
214 /* state table */
215 const 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
223 tBTA_HD_CB bta_hd_cb;
224 #endif
225
226 static const char* bta_hd_evt_code(tBTA_HD_INT_EVT evt_code);
227 static 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 ******************************************************************************/
bta_hd_sm_execute(uint16_t event,tBTA_HD_DATA * p_data)238 void 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 ******************************************************************************/
bta_hd_hdl_event(BT_HDR * p_msg)280 bool 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
bta_hd_evt_code(tBTA_HD_INT_EVT evt_code)307 static 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
bta_hd_state_code(tBTA_HD_STATE state_code)350 static 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