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