1 /******************************************************************************
2 *
3 * Copyright (C) 2016 The Android Open Source Project
4 * Copyright (C) 2009-2012 Broadcom Corporation
5 * Copyright (C) 2019 Blake Felt
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at:
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************************/
20 /************************************************************************************
21 *
22 * Filename: btc_hd.c
23 *
24 * Description: HID Device Profile Bluetooth Interface
25 *
26 *
27 ***********************************************************************************/
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "btc/btc_util.h"
33 #include "btc/btc_manage.h"
34 #include "device/bdaddr.h"
35 #include "btc/btc_storage.h"
36 #include "osi/allocator.h"
37 #include "bta/utl.h"
38 #include "bta/bta_hh_api.h"
39 #include "stack/l2c_api.h"
40 // #include "bta_dm_int.h"
41
42 #if HID_HOST_INCLUDED == TRUE
43 #include "btc_hh.h"
44
45
46 /*******************************************************************************
47 * Static variables
48 ******************************************************************************/
49 btc_hh_cb_t btc_hh_cb;
50 static bdstr_t bdstr;
51
52 /******************************************************************************
53 * Constants & Macros
54 *****************************************************************************/
55 #define COD_MASK 0x07FF
56
57 #define COD_UNCLASSIFIED ((0x1F) << 8)
58 #define COD_HID_KEYBOARD 0x0540
59 #define COD_HID_POINTING 0x0580
60 #define COD_HID_COMBO 0x05C0
61 #define COD_HID_MAJOR 0x0500
62 #define COD_HID_MASK 0x0700
63
64 #define is_hidh_init() (btc_hh_cb.status > BTC_HH_DISABLED)
65 #define BTC_TIMEOUT_VUP_MS (3 * 1000)
66
btc_hh_cb_to_app(esp_hidh_cb_event_t event,esp_hidh_cb_param_t * param)67 static inline void btc_hh_cb_to_app(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param)
68 {
69 esp_hh_cb_t btc_hh_cb = (esp_hh_cb_t)btc_profile_cb_get(BTC_PID_HH);
70 if (btc_hh_cb) {
71 btc_hh_cb(event, param);
72 }
73 }
74
75 /*******************************************************************************
76 *
77 * Function proto_mode_change_to_lower_layer
78 *
79 * Description Change the upper layer protocol mode definition to the lower layer protocol mode definition
80 *
81 * Returns Lower layer protocol mode definition
82 ******************************************************************************/
proto_mode_change_to_lower_layer(esp_hidh_protocol_mode_t protocol_mode)83 static inline tBTA_HH_PROTO_MODE proto_mode_change_to_lower_layer(esp_hidh_protocol_mode_t protocol_mode)
84 {
85 tBTA_HH_PROTO_MODE proto_mode = BTA_HH_PROTO_UNKNOWN;
86
87 switch (protocol_mode) {
88 case ESP_HIDH_REPORT_MODE:
89 proto_mode = BTA_HH_PROTO_RPT_MODE;
90 break;
91 case ESP_HIDH_BOOT_MODE:
92 proto_mode = BTA_HH_PROTO_BOOT_MODE;
93 break;
94 default:
95 break;
96 }
97
98 return proto_mode;
99 }
100
101 /*******************************************************************************
102 *
103 * Function proto_mode_change_to_upper_layer
104 *
105 * Description Change the lower layer protocol mode definition to the upper layer protocol mode definition
106 *
107 * Returns Upper layer protocol mode definition
108 ******************************************************************************/
proto_mode_change_to_upper_layer(tBTA_HH_PROTO_MODE proto_mode)109 static inline esp_hidh_protocol_mode_t proto_mode_change_to_upper_layer(tBTA_HH_PROTO_MODE proto_mode)
110 {
111 esp_hidh_protocol_mode_t protocol_mode = ESP_HIDH_UNSUPPORTED_MODE;
112
113 switch (proto_mode) {
114 case BTA_HH_PROTO_RPT_MODE:
115 protocol_mode = ESP_HIDH_REPORT_MODE;
116 break;
117 case BTA_HH_PROTO_BOOT_MODE:
118 protocol_mode = ESP_HIDH_BOOT_MODE;
119 break;
120 default:
121 break;
122 }
123
124 return protocol_mode;
125 }
126
127 /*******************************************************************************
128 *
129 * Function btc_hh_find_connected_dev_by_handle
130 *
131 * Description Return the connected device pointer of the specified device
132 * handle
133 *
134 * Returns Device entry pointer in the device table
135 ******************************************************************************/
btc_hh_find_connected_dev_by_handle(uint8_t handle)136 btc_hh_device_t *btc_hh_find_connected_dev_by_handle(uint8_t handle)
137 {
138 uint32_t i;
139 for (i = 0; i < BTC_HH_MAX_HID; i++) {
140 if (btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_CONNECTED && btc_hh_cb.devices[i].dev_handle == handle) {
141 return &btc_hh_cb.devices[i];
142 }
143 }
144 return NULL;
145 }
146
147 /*******************************************************************************
148 *
149 * Function btc_hh_find_dev_by_bda
150 *
151 * Description Return the device pointer of the specified bd_addr.
152 *
153 * Returns Device entry pointer in the device table
154 ******************************************************************************/
btc_hh_find_dev_by_bda(BD_ADDR bd_addr)155 static btc_hh_device_t *btc_hh_find_dev_by_bda(BD_ADDR bd_addr)
156 {
157 uint8_t i;
158 for (i = 0; i < BTC_HH_MAX_HID; i++) {
159 if (btc_hh_cb.devices[i].dev_status != ESP_HIDH_CONN_STATE_UNKNOWN &&
160 memcmp(btc_hh_cb.devices[i].bd_addr, bd_addr, BD_ADDR_LEN) == 0) {
161 return &btc_hh_cb.devices[i];
162 }
163 }
164 return NULL;
165 }
166
167 /*******************************************************************************
168 *
169 * Function btc_hh_find_connected_dev_by_bda
170 *
171 * Description Return the connected device pointer of the specified
172 * RawAddress.
173 *
174 * Returns Device entry pointer in the device table
175 ******************************************************************************/
btc_hh_find_connected_dev_by_bda(BD_ADDR bd_addr)176 static btc_hh_device_t *btc_hh_find_connected_dev_by_bda(BD_ADDR bd_addr)
177 {
178 uint32_t i;
179 for (i = 0; i < BTC_HH_MAX_HID; i++) {
180 if (btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_CONNECTED &&
181 memcmp(btc_hh_cb.devices[i].bd_addr, bd_addr, BD_ADDR_LEN) == 0) {
182 return &btc_hh_cb.devices[i];
183 }
184 }
185 return NULL;
186 }
187
188 /*******************************************************************************
189 *
190 * Function btc_hh_stop_vup_timer
191 *
192 * Description stop virtual unplug timer
193 *
194 * Returns void
195 ******************************************************************************/
btc_hh_stop_vup_timer(BD_ADDR bd_addr)196 void btc_hh_stop_vup_timer(BD_ADDR bd_addr)
197 {
198 BTIF_TRACE_API("%s", __func__);
199 btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_bda(bd_addr);
200
201 if (p_dev != NULL) {
202 BTC_TRACE_DEBUG("stop VUP timer");
203 if (p_dev->vup_timer) {
204 osi_alarm_free(p_dev->vup_timer);
205 p_dev->vup_timer = NULL;
206 }
207 }
208 }
209
210 /*******************************************************************************
211 *
212 * Function btc_hh_timer_timeout
213 *
214 * Description Process timer timeout
215 *
216 * Returns void
217 ******************************************************************************/
btc_hh_timer_timeout(void * data)218 void btc_hh_timer_timeout(void *data)
219 {
220 btc_hh_device_t *p_dev = (btc_hh_device_t *)data;
221 bt_status_t status;
222 tBTA_HH p_data;
223 btc_msg_t msg;
224 msg.sig = BTC_SIG_API_CB;
225 msg.pid = BTC_PID_HH;
226 msg.act = BTA_HH_VC_UNPLUG_EVT;
227
228 BTC_TRACE_API("%s", __func__);
229 if (p_dev->dev_status != ESP_HIDH_CONN_STATE_CONNECTED){
230 BTC_TRACE_ERROR("%s Device[%s] is not connected!", __func__,
231 bdaddr_to_string((const bt_bdaddr_t *)p_dev->bd_addr, bdstr, sizeof(bdstr)));
232 return;
233 }
234
235 memset(&p_data, 0, sizeof(tBTA_HH));
236 p_data.dev_status.status = BTA_HH_ERR;
237 p_data.dev_status.handle = p_dev->dev_handle;
238
239 /* switch context to btif task context */
240 status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_HH), NULL, NULL);
241 if (status != BT_STATUS_SUCCESS) {
242 BTC_TRACE_ERROR("%s context transfer failed", __func__);
243 }
244 }
245
246 /*******************************************************************************
247 *
248 * Function btc_hh_start_vup_timer
249 *
250 * Description start virtual unplug timer
251 *
252 * Returns void
253 ******************************************************************************/
btc_hh_start_vup_timer(BD_ADDR bd_addr)254 void btc_hh_start_vup_timer(BD_ADDR bd_addr)
255 {
256 BTC_TRACE_API("%s", __func__);
257
258 btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_bda(bd_addr);
259 if (p_dev == NULL) {
260 BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
261 return;
262 }
263
264 if (p_dev->vup_timer) {
265 osi_alarm_free(p_dev->vup_timer);
266 p_dev->vup_timer = NULL;
267 }
268 if ((p_dev->vup_timer = osi_alarm_new("btc_hh.vup_timer", btc_hh_timer_timeout, p_dev, BTC_TIMEOUT_VUP_MS)) ==
269 NULL) {
270 BTC_TRACE_ERROR("%s unable to malloc vup_timer!", __func__);
271 }
272 }
273
274 /*******************************************************************************
275 *
276 * Function btc_hh_add_added_dev
277 *
278 * Description Add a new device to the added device list.
279 *
280 * Returns true if add successfully, otherwise false.
281 ******************************************************************************/
btc_hh_add_added_dev(BD_ADDR bd_addr,tBTA_HH_ATTR_MASK attr_mask)282 bool btc_hh_add_added_dev(BD_ADDR bd_addr, tBTA_HH_ATTR_MASK attr_mask)
283 {
284 int i;
285 for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
286 if (memcmp(btc_hh_cb.added_devices[i].bd_addr, bd_addr, BD_ADDR_LEN) == 0) {
287 return false;
288 }
289 }
290 for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
291 if (memcmp(btc_hh_cb.added_devices[i].bd_addr, bd_addr_null, BD_ADDR_LEN) == 0) {
292 memcpy(btc_hh_cb.added_devices[i].bd_addr, bd_addr, BD_ADDR_LEN);
293 btc_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
294 btc_hh_cb.added_devices[i].attr_mask = attr_mask;
295 return true;
296 }
297 }
298
299 BTC_TRACE_ERROR("%s: Error, out of space to add device", __func__);
300 return false;
301 }
302
303 /*******************************************************************************
304 **
305 ** Function btc_hh_remove_device
306 **
307 ** Description Remove an added device from the stack.
308 **
309 ** Returns void
310 ******************************************************************************/
btc_hh_remove_device(BD_ADDR bd_addr)311 void btc_hh_remove_device(BD_ADDR bd_addr)
312 {
313 int i;
314 btc_hh_device_t *p_dev;
315 btc_hh_added_device_t *p_added_dev;
316
317 for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
318 p_added_dev = &btc_hh_cb.added_devices[i];
319 if (memcmp(p_added_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0) {
320 BTA_HhRemoveDev(p_added_dev->dev_handle);
321 btc_storage_remove_hid_info((bt_bdaddr_t *)p_added_dev->bd_addr);
322 memset(p_added_dev->bd_addr, 0, 6);
323 p_added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
324 break;
325 }
326 }
327
328 p_dev = btc_hh_find_dev_by_bda(bd_addr);
329 if (p_dev == NULL) {
330 BTC_TRACE_ERROR("%s Oops, can't find device", __func__);
331 return;
332 }
333
334 /* need to notify up-layer device is disconnected to avoid state out of sync
335 * with up-layer */ //[boblane]
336 // HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr), BTHH_CONN_STATE_DISCONNECTED);
337
338 p_dev->dev_status = ESP_HIDH_CONN_STATE_UNKNOWN;
339 p_dev->dev_handle = BTA_HH_INVALID_HANDLE;
340 p_dev->ready_for_data = false;
341
342 if (btc_hh_cb.device_num > 0) {
343 btc_hh_cb.device_num--;
344 } else {
345 BTC_TRACE_WARNING("%s: device_num = 0", __func__);
346 }
347 }
348
bte_hh_arg_deep_copy(btc_msg_t * msg,void * p_dst,void * p_src)349 static void bte_hh_arg_deep_copy(btc_msg_t *msg, void *p_dst, void *p_src)
350 {
351 tBTA_HH *p_dst_data = (tBTA_HH *)p_dst;
352 tBTA_HH *p_src_data = (tBTA_HH *)p_src;
353 switch (msg->act)
354 {
355 case BTA_HH_GET_RPT_EVT: {
356 BT_HDR *src_hdr = p_src_data->hs_data.rsp_data.p_rpt_data;
357 if (src_hdr) {
358 p_dst_data->hs_data.rsp_data.p_rpt_data = osi_malloc(sizeof(BT_HDR) + src_hdr->offset + src_hdr->len);
359 if (p_dst_data->hs_data.rsp_data.p_rpt_data == NULL) {
360 BTC_TRACE_ERROR("%s malloc p_rpt_data failed!", __func__);
361 p_dst_data->hs_data.status = ESP_HIDH_ERR_NO_RES;
362 break;
363 }
364 memcpy(p_dst_data->hs_data.rsp_data.p_rpt_data, src_hdr, sizeof(BT_HDR) + src_hdr->offset + src_hdr->len);
365 }
366 break;
367 }
368 default:
369 break;
370 }
371 }
372
bte_hh_evt(tBTA_HH_EVT event,tBTA_HH * p_data)373 static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH *p_data)
374 {
375 bt_status_t status;
376 int param_len = 0;
377
378 BTC_TRACE_API("%s event=%d", __func__, event);
379
380 switch (event) {
381 case BTA_HH_ENABLE_EVT:
382 param_len = sizeof(tBTA_HH_STATUS);
383 break;
384 case BTA_HH_DISABLE_EVT:
385 param_len = sizeof(tBTA_HH_STATUS);
386 break;
387 case BTA_HH_OPEN_EVT:
388 param_len = sizeof(tBTA_HH_CONN);
389 break;
390 case BTA_HH_CLOSE_EVT:
391 param_len = sizeof(tBTA_HH_CBDATA);
392 break;
393 case BTA_HH_GET_RPT_EVT:
394 param_len = sizeof(tBTA_HH_HSDATA);
395 break;
396 case BTA_HH_SET_RPT_EVT:
397 param_len = sizeof(tBTA_HH_CBDATA);
398 break;
399 case BTA_HH_GET_PROTO_EVT:
400 param_len = sizeof(tBTA_HH_HSDATA);
401 break;
402 case BTA_HH_SET_PROTO_EVT:
403 param_len = sizeof(tBTA_HH_CBDATA);
404 break;
405 case BTA_HH_GET_IDLE_EVT:
406 param_len = sizeof(tBTA_HH_HSDATA);
407 break;
408 case BTA_HH_SET_IDLE_EVT:
409 param_len = sizeof(tBTA_HH_CBDATA);
410 break;
411 case BTA_HH_GET_DSCP_EVT:
412 param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
413 break;
414 case BTA_HH_ADD_DEV_EVT:
415 param_len = sizeof(tBTA_HH_DEV_INFO);
416 break;
417 case BTA_HH_RMV_DEV_EVT:
418 param_len = sizeof(tBTA_HH_DEV_INFO);
419 break;
420 case BTA_HH_VC_UNPLUG_EVT:
421 param_len = sizeof(tBTA_HH_CBDATA);
422 break;
423 case BTA_HH_DATA_EVT:
424 param_len = sizeof(tBTA_HH_API_SENDDATA);
425 break;
426 case BTA_HH_API_ERR_EVT:
427 param_len = 0;
428 break;
429 }
430
431 btc_msg_t msg;
432 msg.sig = BTC_SIG_API_CB;
433 msg.pid = BTC_PID_HH;
434 msg.act = event;
435
436 status = btc_transfer_context(&msg, p_data, param_len, bte_hh_arg_deep_copy, btc_hh_cb_arg_deep_free);
437 assert(status == BT_STATUS_SUCCESS);
438 }
439
440 /*******************************************************************************
441 *
442 * Function btc_hh_init
443 *
444 * Description initializes the hh interface
445 *
446 * Returns void
447 *
448 ******************************************************************************/
btc_hh_init(void)449 static void btc_hh_init(void)
450 {
451 BTC_TRACE_API("%s", __func__);
452 esp_hidh_status_t ret = ESP_HIDH_OK;
453 do {
454 if (is_hidh_init()) {
455 BTC_TRACE_ERROR("%s HH has been initiated, shall uninit first!", __func__);
456 ret = ESP_HIDH_NEED_DEINIT;
457 break;
458 }
459
460 memset(&btc_hh_cb, 0, sizeof(btc_hh_cb));
461 for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) {
462 btc_hh_cb.devices[i].dev_status = ESP_HIDH_CONN_STATE_UNKNOWN;
463 }
464 BTA_HhEnable(BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT, bte_hh_evt);
465 } while (0);
466
467 if (ret != ESP_HIDH_OK) {
468 esp_hidh_cb_param_t param;
469 param.init.status = ret;
470 btc_hh_cb_to_app(ESP_HIDH_INIT_EVT, ¶m);
471 }
472 }
473
474 /*******************************************************************************
475 *
476 * Function btc_hh_deinit
477 *
478 * Description de-initializes the hh interface
479 *
480 * Returns void
481 *
482 ******************************************************************************/
btc_hh_deinit(void)483 static void btc_hh_deinit(void)
484 {
485 BTC_TRACE_API("%s", __func__);
486 esp_hidh_status_t ret = ESP_HIDH_OK;
487 do {
488 if (!is_hidh_init()) {
489 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
490 ret = ESP_HIDH_NEED_INIT;
491 break;
492 }
493
494 // close all connections
495 for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) {
496 if(btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_CONNECTED){
497 BTA_HhClose(btc_hh_cb.devices[i].dev_handle);
498 }
499 }
500 btc_hh_cb.service_dereg_active = TRUE;
501 btc_hh_cb.status = BTC_HH_DISABLING;
502 BTA_HhDisable();
503 } while (0);
504
505 if (ret != ESP_HIDH_OK) {
506 esp_hidh_cb_param_t param;
507 param.deinit.status = ret;
508 btc_hh_cb_to_app(ESP_HIDH_DEINIT_EVT, ¶m);
509 }
510 }
511
512 /*******************************************************************************
513 *
514 * Function btc_hh_connect
515 *
516 * Description connection initiated from the BTC thread context
517 *
518 * Returns void
519 *
520 ******************************************************************************/
btc_hh_connect(btc_hidh_args_t * arg)521 static void btc_hh_connect(btc_hidh_args_t *arg)
522 {
523 BTC_TRACE_API("%s", __func__);
524 esp_hidh_status_t ret = ESP_HIDH_OK;
525 btc_hh_added_device_t* added_dev = NULL;
526 btc_hh_device_t* dev = NULL;
527 esp_hidh_cb_param_t param;
528
529 do {
530 if (!is_hidh_init()) {
531 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
532 ret = ESP_HIDH_NEED_INIT;
533 break;
534 }
535
536 if (btc_hh_cb.status == BTC_HH_DEV_CONNECTING) {
537 BTC_TRACE_ERROR("%s HH is connecting, ignore!", __func__);
538 ret = ESP_HIDH_BUSY;
539 break;
540 }
541
542 dev = btc_hh_find_dev_by_bda(arg->connect.bd_addr);
543 if (!dev && btc_hh_cb.device_num >= BTC_HH_MAX_HID) {
544 BTC_TRACE_ERROR("%s exceeded the maximum supported HID device number %d!", __func__, BTC_HH_MAX_HID);
545 ret = ESP_HIDH_ERR_NO_RES;
546 break;
547 } else if (dev && dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED) {
548 BTC_TRACE_WARNING("%s Device[%s] already connected", __func__,
549 bdaddr_to_string((const bt_bdaddr_t *)arg->connect.bd_addr, bdstr, sizeof(bdstr)));
550 param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTED;
551 break;
552 }
553
554 for (int i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
555 if (memcmp(btc_hh_cb.added_devices[i].bd_addr, arg->connect.bd_addr, BD_ADDR_LEN) == 0) {
556 added_dev = &btc_hh_cb.added_devices[i];
557 BTC_TRACE_WARNING("%s Device[%s] already added, attr_mask = 0x%x", __func__,
558 bdaddr_to_string((const bt_bdaddr_t *)arg->connect.bd_addr, bdstr, sizeof(bdstr)),
559 added_dev->attr_mask);
560 }
561 }
562
563 if (added_dev != NULL) {
564 if (added_dev->dev_handle == BTA_HH_INVALID_HANDLE) {
565 // No space for more HID device now.
566 BTC_TRACE_ERROR("device added but addition failed");
567 memset(added_dev->bd_addr, 0, sizeof(added_dev->bd_addr));
568 ret = ESP_HIDH_ERR;
569 break;
570 }
571 }
572
573 /* Not checking the NORMALLY_Connectible flags from sdp record, and anyways
574 sending this request from host, for subsequent user initiated connection. If the remote is
575 not in pagescan mode, we will do 2 retries to connect before giving up */
576 btc_hh_cb.status = BTC_HH_DEV_CONNECTING;
577 memcpy(btc_hh_cb.pending_conn_address, arg->connect.bd_addr, BD_ADDR_LEN);
578 BTA_HhOpen(arg->connect.bd_addr, BTA_HH_PROTO_RPT_MODE, (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT));
579 param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTING;
580 ret = ESP_HIDH_OK;
581 } while (0);
582
583 if (ret != ESP_HIDH_OK) {
584 param.open.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
585 }
586 param.open.status = ret;
587 param.open.handle = BTA_HH_INVALID_HANDLE;
588 memcpy(param.open.bd_addr, arg->connect.bd_addr, BD_ADDR_LEN);
589 param.open.is_orig = true;
590 btc_hh_cb_to_app(ESP_HIDH_OPEN_EVT, ¶m);
591 }
592
593 /*******************************************************************************
594 *
595 * Function btc_hh_disconnect
596 *
597 * Description disconnection initiated from the BTC thread context
598 *
599 * Returns void
600 *
601 ******************************************************************************/
btc_hh_disconnect(btc_hidh_args_t * arg)602 static void btc_hh_disconnect(btc_hidh_args_t *arg)
603 {
604 BTC_TRACE_API("%s", __func__);
605 esp_hidh_status_t ret = ESP_HIDH_OK;
606 btc_hh_device_t *p_dev;
607 esp_hidh_cb_param_t param;
608
609 do {
610 if (!is_hidh_init()) {
611 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
612 ret = ESP_HIDH_NEED_INIT;
613 break;
614 }
615 p_dev = btc_hh_find_connected_dev_by_bda(arg->disconnect.bd_addr);
616 if (p_dev != NULL) {
617 BTA_HhClose(p_dev->dev_handle);
618 param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING;
619 param.close.handle = p_dev->dev_handle;
620 } else {
621 ret = ESP_HIDH_NO_CONNECTION;
622 BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
623 }
624
625 } while (0);
626
627 if (ret != ESP_HIDH_OK) {
628 param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
629 param.close.handle = BTA_HH_INVALID_HANDLE;
630 }
631 param.close.status = ret;
632 btc_hh_cb_to_app(ESP_HIDH_CLOSE_EVT, ¶m);
633 }
634
635 /*******************************************************************************
636 *
637 * Function btc_hh_virtual_unplug
638 *
639 * Description Virtual unplug initiated from the BTC thread context
640 * Special handling for HID mouse-
641 *
642 * Returns void
643 *
644 ******************************************************************************/
btc_hh_virtual_unplug(btc_hidh_args_t * arg)645 static void btc_hh_virtual_unplug(btc_hidh_args_t *arg)
646 {
647 BTC_TRACE_API("%s", __func__);
648 esp_hidh_status_t ret = ESP_HIDH_OK;
649 btc_hh_device_t *p_dev;
650 esp_hidh_cb_param_t param;
651
652 do {
653 if (!is_hidh_init()) {
654 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
655 ret = ESP_HIDH_NEED_INIT;
656 break;
657 }
658 p_dev = btc_hh_find_dev_by_bda(arg->unplug.bd_addr);
659 if ((p_dev != NULL) && (p_dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED) &&
660 (p_dev->attr_mask & HID_VIRTUAL_CABLE)) {
661 BTC_TRACE_DEBUG("%s: Sending BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG", __func__);
662 /* start the timer */
663 btc_hh_start_vup_timer(arg->unplug.bd_addr);
664 p_dev->local_vup = true;
665 BTA_HhSendCtrl(p_dev->dev_handle, BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG);
666
667 param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING;
668 param.unplug.handle = p_dev->dev_handle;
669 } else if ((p_dev != NULL) && (p_dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED)) {
670 BTC_TRACE_WARNING("%s: Virtual unplug not supported, disconnecting device", __func__);
671 /* start the timer */
672 btc_hh_start_vup_timer(arg->unplug.bd_addr);
673 p_dev->local_vup = true;
674 BTA_HhClose(p_dev->dev_handle);
675
676 param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING;
677 param.unplug.handle = p_dev->dev_handle;
678 } else {
679 BTC_TRACE_ERROR("%s: Error, device not opened, status = %d", __func__, btc_hh_cb.status);
680 ret = ESP_HIDH_NO_CONNECTION;
681 if (memcmp(btc_hh_cb.pending_conn_address, arg->unplug.bd_addr, BD_ADDR_LEN) == 0 &&
682 (btc_hh_cb.status == BTC_HH_DEV_CONNECTING)) {
683 btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED;
684 memset(btc_hh_cb.pending_conn_address, 0, BD_ADDR_LEN);
685 }
686 }
687 } while (0);
688
689 if (ret != ESP_HIDH_OK) {
690 param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
691 param.unplug.handle = BTA_HH_INVALID_HANDLE;
692 }
693 param.unplug.status = ret;
694 btc_hh_cb_to_app(ESP_HIDH_VC_UNPLUG_EVT, ¶m);
695 }
696
697 /*******************************************************************************
698 *
699 * Function btc_hh_set_info
700 *
701 * Description Set the HID device descriptor for the specified HID device.
702 *
703 * Returns void
704 *
705 ******************************************************************************/
btc_hh_set_info(btc_hidh_args_t * arg)706 static void btc_hh_set_info(btc_hidh_args_t *arg)
707 {
708 BTC_TRACE_API("%s", __func__);
709 esp_hidh_status_t ret = ESP_HIDH_OK;
710 esp_hidh_cb_param_t param;
711 tBTA_HH_DEV_DSCP_INFO dscp_info;
712
713 BTC_TRACE_DEBUG("%s: sub_class = 0x%02x, app_id = %d, vendor_id = 0x%04x, "
714 "product_id = 0x%04x, version= 0x%04x",
715 __func__, arg->set_info.hid_info->sub_class, arg->set_info.hid_info->app_id,
716 arg->set_info.hid_info->vendor_id, arg->set_info.hid_info->product_id,
717 arg->set_info.hid_info->version);
718 do {
719 if (!is_hidh_init()) {
720 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
721 ret = ESP_HIDH_NEED_INIT;
722 break;
723 }
724
725 memset(&dscp_info, 0, sizeof(dscp_info));
726 dscp_info.vendor_id = arg->set_info.hid_info->vendor_id;
727 dscp_info.product_id = arg->set_info.hid_info->product_id;
728 dscp_info.version = arg->set_info.hid_info->version;
729 dscp_info.ctry_code = arg->set_info.hid_info->ctry_code;
730
731 dscp_info.descriptor.dl_len = arg->set_info.hid_info->dl_len;
732 dscp_info.descriptor.dsc_list = (uint8_t *)osi_malloc(dscp_info.descriptor.dl_len);
733 if (dscp_info.descriptor.dsc_list == NULL) {
734 BTC_TRACE_ERROR("%s malloc dsc_list failed!", __func__);
735 ret = ESP_HIDH_ERR_NO_RES;
736 break;
737 }
738 memcpy(dscp_info.descriptor.dsc_list, arg->set_info.hid_info->dsc_list, dscp_info.descriptor.dl_len);
739
740 if (btc_hh_add_added_dev(arg->set_info.bd_addr, arg->set_info.hid_info->attr_mask)) {
741 btc_hh_cb.add_event = BTC_HH_SET_INFO_EVT;
742 BTA_HhAddDev(arg->set_info.bd_addr, arg->set_info.hid_info->attr_mask, arg->set_info.hid_info->sub_class,
743 arg->set_info.hid_info->app_id, dscp_info);
744 } else {
745 BTC_TRACE_ERROR("%s malloc dsc_list failed!", __func__);
746 ret = ESP_HIDH_ERR;
747 break;
748 }
749 } while(0);
750 utl_freebuf((void **)&dscp_info.descriptor.dsc_list);
751
752 if (ret != ESP_HIDH_OK) {
753 param.set_info.status = ret;
754 param.set_info.handle = BTA_HH_INVALID_HANDLE;
755 memcpy(param.set_info.bd_addr, arg->set_info.bd_addr, BD_ADDR_LEN);
756 btc_hh_cb_to_app(ESP_HIDH_SET_INFO_EVT, ¶m);
757 }
758 }
759
760 /*******************************************************************************
761 *
762 * Function btc_hh_get_protocol
763 *
764 * Description Get the HID proto mode.
765 *
766 * Returns void
767 *
768 ******************************************************************************/
btc_hh_get_protocol(btc_hidh_args_t * arg)769 static void btc_hh_get_protocol(btc_hidh_args_t *arg)
770 {
771 BTC_TRACE_API("%s", __func__);
772 esp_hidh_status_t ret = ESP_HIDH_OK;
773 esp_hidh_cb_param_t param;
774 btc_hh_device_t *p_dev;
775
776 do {
777 if (!is_hidh_init()) {
778 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
779 ret = ESP_HIDH_NEED_INIT;
780 break;
781 }
782 p_dev = btc_hh_find_connected_dev_by_bda(arg->get_protocol.bd_addr);
783 if (p_dev == NULL) {
784 ret = ESP_HIDH_NO_CONNECTION;
785 BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
786 break;
787 }
788 BTA_HhGetProtoMode(p_dev->dev_handle);
789 } while(0);
790
791 if (ret != ESP_HIDH_OK) {
792 param.get_proto.proto_mode = ESP_HIDH_UNSUPPORTED_MODE;
793 param.get_proto.handle = BTA_HH_INVALID_HANDLE;
794 param.get_proto.status = ret;
795 btc_hh_cb_to_app(ESP_HIDH_GET_PROTO_EVT, ¶m);
796 }
797 }
798
799 /*******************************************************************************
800 *
801 * Function btc_hh_set_protocol
802 *
803 * Description Set the HID proto mode.
804 *
805 * Returns void
806 *
807 ******************************************************************************/
btc_hh_set_protocol(btc_hidh_args_t * arg)808 static void btc_hh_set_protocol(btc_hidh_args_t *arg)
809 {
810 BTC_TRACE_API("%s", __func__);
811 esp_hidh_status_t ret = ESP_HIDH_OK;
812 esp_hidh_cb_param_t param;
813 btc_hh_device_t *p_dev;
814
815 do {
816 if (!is_hidh_init()) {
817 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
818 ret = ESP_HIDH_NEED_INIT;
819 break;
820 }
821 p_dev = btc_hh_find_connected_dev_by_bda(arg->set_protocol.bd_addr);
822 if (p_dev == NULL) {
823 ret = ESP_HIDH_NO_CONNECTION;
824 BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
825 break;
826 } else if (arg->set_protocol.protocol_mode != ESP_HIDH_REPORT_MODE && arg->set_protocol.protocol_mode != ESP_HIDH_BOOT_MODE) {
827 BTC_TRACE_ERROR("%s: Error, device proto_mode = %d.", __func__, arg->set_protocol.protocol_mode);
828 ret = ESP_HIDH_HS_INVALID_PARAM;
829 break;
830 } else {
831 BTA_HhSetProtoMode(p_dev->dev_handle, proto_mode_change_to_lower_layer(arg->set_protocol.protocol_mode));
832 }
833 } while (0);
834
835 if (ret != ESP_HIDH_OK) {
836 param.set_proto.handle = BTA_HH_INVALID_HANDLE;
837 param.set_proto.status = ret;
838 btc_hh_cb_to_app(ESP_HIDH_SET_PROTO_EVT, ¶m);
839 }
840 }
841
842 /*******************************************************************************
843 *
844 * Function btc_hh_get_report
845 *
846 * Description Send a GET_REPORT to HID device.
847 *
848 * Returns void
849 *
850 ******************************************************************************/
btc_hh_get_report(btc_hidh_args_t * arg)851 static void btc_hh_get_report(btc_hidh_args_t *arg)
852 {
853 BTC_TRACE_API("%s", __func__);
854 esp_hidh_status_t ret = ESP_HIDH_OK;
855 esp_hidh_cb_param_t param;
856 btc_hh_device_t *p_dev;
857
858 do {
859 if (!is_hidh_init()) {
860 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
861 ret = ESP_HIDH_NEED_INIT;
862 break;
863 }
864
865 p_dev = btc_hh_find_connected_dev_by_bda(arg->get_report.bd_addr);
866 if (p_dev == NULL) {
867 ret = ESP_HIDH_NO_CONNECTION;
868 BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
869 break;
870 } else if (((int)arg->get_report.report_type) <= BTA_HH_RPTT_RESRV ||
871 ((int)arg->get_report.report_type) > BTA_HH_RPTT_FEATURE) {
872 BTC_TRACE_ERROR("%s Error: report type=%d not supported!", __func__, arg->get_report.report_type);
873 ret = ESP_HIDH_HS_INVALID_PARAM;
874 break;
875 } else {
876 BTA_HhGetReport(p_dev->dev_handle, arg->get_report.report_type, arg->get_report.report_id,
877 arg->get_report.buffer_size);
878 }
879 } while (0);
880
881 if (ret != ESP_HIDH_OK) {
882 param.get_rpt.handle = BTA_HH_INVALID_HANDLE;
883 param.get_rpt.status = ret;
884 param.get_rpt.len = 0;
885 param.get_rpt.data = NULL;
886 btc_hh_cb_to_app(ESP_HIDH_GET_RPT_EVT, ¶m);
887 }
888 }
889
890 /*******************************************************************************
891 *
892 * Function create_pbuf
893 *
894 * Description Helper function to create p_buf for send_data or set_report
895 *
896 * Returns BT_HDR *
897 *
898 ******************************************************************************/
create_pbuf(uint16_t len,uint8_t * data)899 static BT_HDR *create_pbuf(uint16_t len, uint8_t *data)
900 {
901 uint8_t *pbuf_data;
902 BT_HDR *p_buf = (BT_HDR *)osi_malloc(len + BTA_HH_MIN_OFFSET + sizeof(BT_HDR));
903 if (p_buf == NULL) {
904 BTC_TRACE_ERROR("%s failed!", __func__);
905 return NULL;
906 }
907 p_buf->len = len;
908 p_buf->offset = BTA_HH_MIN_OFFSET;
909
910 pbuf_data = (uint8_t *)(p_buf + 1) + p_buf->offset;
911 memcpy(pbuf_data, data, len);
912
913 return p_buf;
914 }
915
916 /*******************************************************************************
917 *
918 * Function btc_hh_set_report
919 *
920 * Description Send a SET_REPORT to HID device.
921 *
922 * Returns void
923 *
924 ******************************************************************************/
btc_hh_set_report(btc_hidh_args_t * arg)925 static void btc_hh_set_report(btc_hidh_args_t *arg)
926 {
927 BTC_TRACE_API("%s", __func__);
928 esp_hidh_status_t ret = ESP_HIDH_OK;
929 esp_hidh_cb_param_t param;
930 btc_hh_device_t *p_dev;
931
932 do {
933 if (!is_hidh_init()) {
934 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
935 ret = ESP_HIDH_NEED_INIT;
936 break;
937 }
938
939 p_dev = btc_hh_find_connected_dev_by_bda(arg->set_report.bd_addr);
940 if (p_dev == NULL) {
941 ret = ESP_HIDH_NO_CONNECTION;
942 BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
943 break;
944 } else if (((int)arg->set_report.report_type) <= BTA_HH_RPTT_RESRV ||
945 ((int)arg->set_report.report_type) > BTA_HH_RPTT_FEATURE) {
946 BTC_TRACE_ERROR("%s Error: report type=%d not supported!", __func__, arg->set_report.report_type);
947 ret = ESP_HIDH_HS_INVALID_PARAM;
948 break;
949 } else if (arg->set_report.report == NULL || arg->set_report.len == 0) {
950 BTC_TRACE_ERROR("%s Error: report is empty!", __func__);
951 ret = ESP_HIDH_HS_INVALID_PARAM;
952 break;
953 } else {
954 BT_HDR* p_buf = create_pbuf(arg->set_report.len, arg->set_report.report);
955 if (p_buf == NULL) {
956 ret = ESP_HIDH_ERR_NO_RES;
957 break;
958 }
959 BTA_HhSetReport(p_dev->dev_handle, arg->set_report.report_type, p_buf);
960 }
961 } while(0);
962
963 if (ret != ESP_HIDH_OK) {
964 param.set_rpt.handle = BTA_HH_INVALID_HANDLE;
965 param.set_rpt.status = ret;
966 btc_hh_cb_to_app(ESP_HIDH_SET_RPT_EVT, ¶m);
967 }
968 }
969
970 /*******************************************************************************
971 *
972 * Function btc_hh_send_data
973 *
974 * Description Send a SEND_DATA to HID device.
975 *
976 * Returns void
977 *
978 ******************************************************************************/
btc_hh_send_data(btc_hidh_args_t * arg)979 static void btc_hh_send_data(btc_hidh_args_t *arg)
980 {
981 BTC_TRACE_API("%s", __func__);
982 esp_hidh_status_t ret = ESP_HIDH_OK;
983 esp_hidh_cb_param_t param;
984 btc_hh_device_t *p_dev;
985
986 do {
987 if (!is_hidh_init()) {
988 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
989 ret = ESP_HIDH_NEED_INIT;
990 break;
991 }
992
993 p_dev = btc_hh_find_connected_dev_by_bda(arg->send_data.bd_addr);
994 if (p_dev == NULL) {
995 ret = ESP_HIDH_NO_CONNECTION;
996 BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
997 break;
998 } else if (arg->send_data.data == NULL || arg->send_data.len == 0) {
999 BTC_TRACE_ERROR("%s Error: send data is empty!", __func__);
1000 ret = ESP_HIDH_HS_INVALID_PARAM;
1001 break;
1002 } else {
1003 BT_HDR *p_buf = create_pbuf(arg->send_data.len, arg->send_data.data);
1004 if (p_buf == NULL) {
1005 ret = ESP_HIDH_ERR_NO_RES;
1006 break;
1007 }
1008 p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
1009 BTA_HhSendData(p_dev->dev_handle, arg->send_data.bd_addr, p_buf);
1010 }
1011 } while(0);
1012
1013 if (ret != ESP_HIDH_OK) {
1014 param.send_data.handle = BTA_HH_INVALID_HANDLE;
1015 param.send_data.status = ret;
1016 param.send_data.reason = 0;
1017 btc_hh_cb_to_app(ESP_HIDH_DATA_EVT, ¶m);
1018 }
1019 }
1020
1021 /*******************************************************************************
1022 **
1023 ** Function btc_hh_get_idle_time
1024 **
1025 ** Description Get the HID idle time
1026 **
1027 ** Returns void
1028 **
1029 *******************************************************************************/
btc_hh_get_idle_time(btc_hidh_args_t * arg)1030 static void btc_hh_get_idle_time(btc_hidh_args_t *arg)
1031 {
1032 BTC_TRACE_API("%s", __func__);
1033 esp_hidh_status_t ret = ESP_HIDH_OK;
1034 esp_hidh_cb_param_t param;
1035 btc_hh_device_t *p_dev;
1036
1037 do {
1038 if (!is_hidh_init()) {
1039 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
1040 ret = ESP_HIDH_NEED_INIT;
1041 break;
1042 }
1043
1044 p_dev = btc_hh_find_connected_dev_by_bda(arg->get_idle.bd_addr);
1045 if (p_dev == NULL) {
1046 ret = ESP_HIDH_NO_CONNECTION;
1047 BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
1048 break;
1049 }
1050 BTA_HhGetIdle(p_dev->dev_handle);
1051 } while (0);
1052
1053 if (ret != ESP_HIDH_OK) {
1054 param.get_idle.handle = BTA_HH_INVALID_HANDLE;
1055 param.get_idle.status = ret;
1056 param.get_idle.idle_rate = 0;
1057 btc_hh_cb_to_app(ESP_HIDH_GET_IDLE_EVT, ¶m);
1058 }
1059 }
1060
1061 /*******************************************************************************
1062 **
1063 ** Function btc_hh_set_idle_time
1064 **
1065 ** Description Set the HID idle time
1066 **
1067 ** Returns void
1068 **
1069 *******************************************************************************/
btc_hh_set_idle_time(btc_hidh_args_t * arg)1070 static void btc_hh_set_idle_time(btc_hidh_args_t *arg)
1071 {
1072 BTC_TRACE_API("%s", __func__);
1073 esp_hidh_status_t ret = ESP_HIDH_OK;
1074 esp_hidh_cb_param_t param;
1075 btc_hh_device_t *p_dev;
1076
1077 do {
1078 if (!is_hidh_init()) {
1079 BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
1080 ret = ESP_HIDH_NEED_INIT;
1081 break;
1082 }
1083
1084 p_dev = btc_hh_find_connected_dev_by_bda(arg->set_idle.bd_addr);
1085 if (p_dev == NULL) {
1086 ret = ESP_HIDH_NO_CONNECTION;
1087 BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
1088 break;
1089 }
1090 BTA_HhSetIdle(p_dev->dev_handle, arg->set_idle.idle_time);
1091 } while (0);
1092
1093 if (ret != ESP_HIDH_OK) {
1094 param.set_idle.handle = BTA_HH_INVALID_HANDLE;
1095 param.set_idle.status = ret;
1096 btc_hh_cb_to_app(ESP_HIDH_SET_IDLE_EVT, ¶m);
1097 }
1098 }
1099
btc_hh_call_arg_deep_free(btc_msg_t * msg)1100 static void btc_hh_call_arg_deep_free(btc_msg_t *msg)
1101 {
1102 btc_hidh_args_t *arg = (btc_hidh_args_t *)msg->arg;
1103
1104 switch (msg->act) {
1105 case BTC_HH_SET_INFO_EVT:
1106 utl_freebuf((void **)&arg->set_info.hid_info);
1107 break;
1108 case BTC_HH_SET_REPORT_EVT:
1109 utl_freebuf((void **)&arg->set_report.report);
1110 break;
1111 case BTC_HH_SEND_DATA_EVT:
1112 utl_freebuf((void **)&arg->send_data.data);
1113 break;
1114 default:
1115 break;
1116 }
1117 }
1118
btc_hh_call_handler(btc_msg_t * msg)1119 void btc_hh_call_handler(btc_msg_t *msg)
1120 {
1121 btc_hidh_args_t *arg = (btc_hidh_args_t *)(msg->arg);
1122 switch (msg->act) {
1123 case BTC_HH_INIT_EVT:
1124 btc_hh_init();
1125 break;
1126 case BTC_HH_CONNECT_EVT:
1127 btc_hh_connect(arg);
1128 break;
1129 case BTC_HH_DISCONNECT_EVT:
1130 btc_hh_disconnect(arg);
1131 break;
1132 case BTC_HH_UNPLUG_EVT:
1133 btc_hh_virtual_unplug(arg);
1134 break;
1135 case BTC_HH_SET_INFO_EVT:
1136 btc_hh_set_info(arg);
1137 break;
1138 case BTC_HH_GET_PROTO_EVT:
1139 btc_hh_get_protocol(arg);
1140 break;
1141 case BTC_HH_SET_PROTO_EVT:
1142 btc_hh_set_protocol(arg);
1143 break;
1144 case BTC_HH_GET_IDLE_EVT:
1145 btc_hh_get_idle_time(arg);
1146 break;
1147 case BTC_HH_SET_IDLE_EVT:
1148 btc_hh_set_idle_time(arg);
1149 break;
1150 case BTC_HH_GET_REPORT_EVT:
1151 btc_hh_get_report(arg);
1152 break;
1153 case BTC_HH_SET_REPORT_EVT:
1154 btc_hh_set_report(arg);
1155 break;
1156 case BTC_HH_SEND_DATA_EVT:
1157 btc_hh_send_data(arg);
1158 break;
1159 case BTC_HH_DEINIT_EVT:
1160 btc_hh_deinit();
1161 break;
1162 default:
1163 BTC_TRACE_WARNING("unknown hidh action %d", msg->act);
1164 break;
1165 }
1166 btc_hh_call_arg_deep_free(msg);
1167 }
1168
btc_hh_cb_arg_deep_free(btc_msg_t * msg)1169 void btc_hh_cb_arg_deep_free(btc_msg_t *msg)
1170 {
1171 tBTA_HH *arg = (tBTA_HH *)msg->arg;
1172
1173 switch (msg->act) {
1174 case BTA_HH_GET_RPT_EVT:
1175 utl_freebuf((void **)&arg->hs_data.rsp_data.p_rpt_data);
1176 break;
1177 case BTA_HH_DATA_IND_EVT:
1178 utl_freebuf((void **)&arg->int_data.p_data);
1179 break;
1180 default:
1181 break;
1182 }
1183 }
1184
btc_hh_copy_hid_info(tBTA_HH_DEV_DSCP_INFO * dest,tBTA_HH_DEV_DSCP_INFO * src)1185 bool btc_hh_copy_hid_info(tBTA_HH_DEV_DSCP_INFO *dest, tBTA_HH_DEV_DSCP_INFO *src)
1186 {
1187 dest->descriptor.dl_len = 0;
1188 if (src->descriptor.dl_len > 0) {
1189 dest->descriptor.dsc_list = (uint8_t *)osi_malloc(src->descriptor.dl_len);
1190 }
1191 if (dest->descriptor.dsc_list) {
1192 memcpy(dest->descriptor.dsc_list, src->descriptor.dsc_list, src->descriptor.dl_len);
1193 dest->descriptor.dl_len = src->descriptor.dl_len;
1194 }
1195 dest->vendor_id = src->vendor_id;
1196 dest->product_id = src->product_id;
1197 dest->version = src->version;
1198 dest->ctry_code = src->ctry_code;
1199 dest->ssr_max_latency = src->ssr_max_latency;
1200 dest->ssr_min_tout = src->ssr_min_tout;
1201 return true;
1202 }
1203
btc_hh_cb_copy_hid_info(esp_hidh_cb_param_t * param,tBTA_HH_DEV_DSCP_INFO * src)1204 bool btc_hh_cb_copy_hid_info(esp_hidh_cb_param_t *param, tBTA_HH_DEV_DSCP_INFO *src)
1205 {
1206 param->dscp.dl_len = 0;
1207 if (src->descriptor.dl_len > 0) {
1208 param->dscp.dsc_list = (uint8_t *)osi_malloc(src->descriptor.dl_len);
1209 }
1210 if (param->dscp.dsc_list) {
1211 memcpy(param->dscp.dsc_list, src->descriptor.dsc_list, src->descriptor.dl_len);
1212 param->dscp.dl_len = src->descriptor.dl_len;
1213 }
1214 param->dscp.vendor_id = src->vendor_id;
1215 param->dscp.product_id = src->product_id;
1216 param->dscp.version = src->version;
1217 param->dscp.ctry_code = src->ctry_code;
1218 param->dscp.ssr_max_latency = src->ssr_max_latency;
1219 param->dscp.ssr_min_tout = src->ssr_min_tout;
1220 return true;
1221 }
1222
btc_hh_cb_handler(btc_msg_t * msg)1223 void btc_hh_cb_handler(btc_msg_t *msg)
1224 {
1225 esp_hidh_cb_param_t param = {0};
1226 tBTA_HH *p_data = (tBTA_HH *)msg->arg;
1227 btc_hh_device_t *p_dev = NULL;
1228 int len, i;
1229 BTC_TRACE_DEBUG("%s: event=%s dereg = %d", __func__, dump_hh_event(msg->act), btc_hh_cb.service_dereg_active);
1230 switch (msg->act) {
1231 case BTA_HH_ENABLE_EVT:
1232 if (p_data->status == BTA_HH_OK) {
1233 btc_hh_cb.status = BTC_HH_ENABLED;
1234 BTC_TRACE_DEBUG("Loading added devices");
1235 /* Add hid descriptors for already bonded hid devices*/
1236 // btc_storage_load_bonded_hid_info();
1237 } else {
1238 btc_hh_cb.status = BTC_HH_DISABLED;
1239 BTC_TRACE_ERROR("Error, HH enabling failed, status = %d", p_data->status);
1240 }
1241 param.init.status = p_data->status;
1242 btc_hh_cb_to_app(ESP_HIDH_INIT_EVT, ¶m);
1243 break;
1244 case BTA_HH_DISABLE_EVT:
1245 btc_hh_cb.status = BTC_HH_DISABLED;
1246 if (btc_hh_cb.service_dereg_active) {
1247 BTIF_TRACE_DEBUG("BTA_HH_DISABLE_EVT: enabling HID Device service");
1248 // btif_hd_service_registration();
1249 btc_hh_cb.service_dereg_active = FALSE;
1250 }
1251 if (p_data->status == BTA_HH_OK) {
1252 // Clear the control block
1253 for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) {
1254 if (btc_hh_cb.devices[i].vup_timer) {
1255 osi_alarm_free(btc_hh_cb.devices[i].vup_timer);
1256 }
1257 }
1258 memset(&btc_hh_cb, 0, sizeof(btc_hh_cb));
1259 for (i = 0; i < BTC_HH_MAX_HID; i++) {
1260 btc_hh_cb.devices[i].dev_status = ESP_HIDH_CONN_STATE_UNKNOWN;
1261 }
1262 } else {
1263 BTC_TRACE_ERROR("Error, HH disabling failed, status = %d", p_data->status);
1264 }
1265 param.deinit.status = p_data->status;
1266 btc_hh_cb_to_app(ESP_HIDH_DEINIT_EVT, ¶m);
1267 break;
1268 case BTA_HH_OPEN_EVT:
1269 BTC_TRACE_DEBUG("handle=%d, status =%d", p_data->conn.handle, p_data->conn.status);
1270 memset(btc_hh_cb.pending_conn_address, 0, BD_ADDR_LEN);
1271 if (p_data->conn.status == BTA_HH_OK) {
1272 p_dev = btc_hh_find_connected_dev_by_handle(p_data->conn.handle);
1273 if (p_dev == NULL) {
1274 BTC_TRACE_ERROR("Error, cannot find device with handle %d", p_data->conn.handle);
1275 btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED;
1276 // The connect request must come from device side and exceeded the
1277 // connected HID device number.
1278 BTA_HhClose(p_data->conn.handle);
1279
1280 param.open.status = ESP_HIDH_ERR;
1281 param.open.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
1282 } else {
1283 BTC_TRACE_DEBUG("Found device...Getting dscp info for handle "
1284 "... %d",
1285 p_data->conn.handle);
1286 memcpy(p_dev->bd_addr, p_data->conn.bda, BD_ADDR_LEN);
1287 btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_CONNECTED;
1288 // Send set_idle if the peer_device is a keyboard [boblane]
1289 // if (check_cod(&p_data->conn.bda, COD_HID_KEYBOARD) || check_cod(&p_data->conn.bda, COD_HID_COMBO))
1290 // BTA_HhSetIdle(p_data->conn.handle, 0);
1291 btc_hh_cb.p_curr_dev = btc_hh_find_connected_dev_by_handle(p_data->conn.handle);
1292 BTA_HhGetDscpInfo(p_data->conn.handle);
1293 p_dev->dev_status = ESP_HIDH_CONN_STATE_CONNECTED;
1294
1295 param.open.status = ESP_HIDH_OK;
1296 param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTED;
1297 }
1298 } else {
1299 p_dev = btc_hh_find_dev_by_bda(p_data->conn.bda);
1300 if (p_dev != NULL) {
1301 btc_hh_stop_vup_timer(p_dev->bd_addr);
1302 p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
1303 }
1304 btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED;
1305
1306 param.open.status = p_data->conn.status;
1307 param.open.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
1308 }
1309 param.open.handle = p_data->conn.handle;
1310 param.open.is_orig = p_data->conn.is_orig;
1311 memcpy(param.open.bd_addr, p_data->conn.bda, BD_ADDR_LEN);
1312 btc_hh_cb_to_app(ESP_HIDH_OPEN_EVT, ¶m);
1313 break;
1314 case BTA_HH_GET_DSCP_EVT:
1315 len = p_data->dscp_info.descriptor.dl_len;
1316 BTC_TRACE_DEBUG("len = %d", len);
1317 do {
1318 param.dscp.status = ESP_HIDH_OK;
1319 param.dscp.handle = BTA_HH_INVALID_HANDLE;
1320 param.dscp.added = false;
1321 p_dev = btc_hh_cb.p_curr_dev;
1322 if (p_dev == NULL) {
1323 BTC_TRACE_ERROR("No HID device is currently connected");
1324 param.dscp.status = ESP_HIDH_NO_CONNECTION;
1325 break;
1326 }
1327
1328 if (btc_hh_add_added_dev(p_dev->bd_addr, p_dev->attr_mask)) {
1329 tBTA_HH_DEV_DSCP_INFO dscp_info;
1330 bt_status_t ret;
1331 btc_hh_copy_hid_info(&dscp_info, &p_data->dscp_info);
1332 btc_hh_cb.add_event = BTC_HH_CONNECT_EVT;
1333 BTA_HhAddDev(p_dev->bd_addr, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id, dscp_info);
1334 // write hid info to nvs
1335 ret = btc_storage_add_hid_device_info((bt_bdaddr_t *)p_dev->bd_addr, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id,
1336 p_data->dscp_info.vendor_id, p_data->dscp_info.product_id,
1337 p_data->dscp_info.version, p_data->dscp_info.ctry_code,
1338 p_data->dscp_info.ssr_max_latency, p_data->dscp_info.ssr_min_tout,
1339 len, p_data->dscp_info.descriptor.dsc_list);
1340
1341 if (ret != BT_STATUS_SUCCESS) {
1342 BTC_TRACE_ERROR("write hid info to nvs failed!");
1343 }
1344 // Free buffer created for dscp_info;
1345 if (dscp_info.descriptor.dl_len > 0 && dscp_info.descriptor.dsc_list != NULL) {
1346 utl_freebuf((void **)&dscp_info.descriptor.dsc_list);
1347 dscp_info.descriptor.dl_len = 0;
1348 }
1349 } else {
1350 // Device already added.
1351 BTC_TRACE_WARNING("%s: Device already added ", __func__);
1352 param.dscp.added = true;
1353 }
1354 btc_hh_cb_copy_hid_info(¶m, &p_data->dscp_info);
1355 param.dscp.handle = p_dev->dev_handle;
1356 } while(0);
1357 btc_hh_cb_to_app(ESP_HIDH_GET_DSCP_EVT, ¶m);
1358 if (param.dscp.dl_len > 0 && param.dscp.dsc_list != NULL) {
1359 utl_freebuf((void **)¶m.dscp.dsc_list);
1360 param.dscp.dl_len = 0;
1361 }
1362 break;
1363 case BTA_HH_CLOSE_EVT:
1364 BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status,
1365 p_data->dev_status.handle);
1366 p_dev = btc_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
1367 if (p_dev != NULL) {
1368 BTC_TRACE_DEBUG("uhid local_vup=%d", p_dev->local_vup);
1369 btc_hh_stop_vup_timer(p_dev->bd_addr);
1370 /* If this is a locally initiated VUP, remove the bond as ACL got
1371 * disconnected while VUP being processed.
1372 */
1373 if (p_dev->local_vup) {
1374 p_dev->local_vup = false;
1375 BTA_DmRemoveDevice(p_dev->bd_addr, BT_TRANSPORT_BR_EDR);
1376 }
1377
1378 btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED;
1379 p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
1380 param.close.status = p_data->dev_status.status;
1381 } else {
1382 BTC_TRACE_ERROR("Error: cannot find device with handle %d", p_data->dev_status.handle);
1383 param.close.status = ESP_HIDH_NO_CONNECTION;
1384 }
1385 param.close.handle = p_data->dev_status.handle;
1386 param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
1387 btc_hh_cb_to_app(ESP_HIDH_CLOSE_EVT, ¶m);
1388 break;
1389 case BTA_HH_VC_UNPLUG_EVT:
1390 BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status,
1391 p_data->dev_status.handle);
1392 p_dev = btc_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
1393 btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED;
1394 if (p_dev != NULL) {
1395 /* Stop the VUP timer */
1396 btc_hh_stop_vup_timer(p_dev->bd_addr);
1397 p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
1398 BTC_TRACE_DEBUG("%s---Sending connection state change", __func__);
1399 param.close.status = ESP_HIDH_OK;
1400 param.close.handle = p_data->dev_status.handle;
1401 param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
1402 btc_hh_cb_to_app(ESP_HIDH_CLOSE_EVT, ¶m);
1403 BTC_TRACE_DEBUG("%s---Removing HID bond", __func__);
1404 /* If it is locally initiated VUP or remote device has its major COD as
1405 Peripheral removed the bond.*/
1406 // [boblane]
1407 if (p_dev->local_vup) {
1408 p_dev->local_vup = false;
1409 BTA_DmRemoveDevice(p_dev->bd_addr, BT_TRANSPORT_BR_EDR);
1410 } else {
1411 btc_hh_remove_device(p_dev->bd_addr);
1412 }
1413 param.unplug.status = p_data->dev_status.status;
1414 } else {
1415 BTC_TRACE_ERROR("Error: cannot find device with handle %d", p_data->dev_status.handle);
1416 param.unplug.status = ESP_HIDH_NO_CONNECTION;
1417 }
1418 param.unplug.handle = p_data->dev_status.handle;
1419 param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
1420 btc_hh_cb_to_app(ESP_HIDH_VC_UNPLUG_EVT, ¶m);
1421 break;
1422 case BTA_HH_DATA_EVT:
1423 BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->send_data.status,
1424 p_data->send_data.handle);
1425 param.send_data.handle = p_data->send_data.handle;
1426 param.send_data.status = p_data->send_data.status;
1427 param.send_data.reason = p_data->send_data.reason;
1428 btc_hh_cb_to_app(ESP_HIDH_DATA_EVT, ¶m);
1429 break;
1430 case BTA_HH_GET_PROTO_EVT:
1431 BTC_TRACE_DEBUG("status = %d, handle = %d, proto = [%d], %s", p_data->hs_data.status,
1432 p_data->hs_data.handle, p_data->hs_data.rsp_data.proto_mode,
1433 (p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)
1434 ? "Report Mode"
1435 : (p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_BOOT_MODE) ? "Boot Mode"
1436 : "Unsupported");
1437 param.get_proto.proto_mode = proto_mode_change_to_upper_layer(p_data->hs_data.rsp_data.proto_mode);
1438 param.get_proto.handle = p_data->hs_data.handle;
1439 param.get_proto.status = p_data->hs_data.status;
1440 btc_hh_cb_to_app(ESP_HIDH_GET_PROTO_EVT, ¶m);
1441 break;
1442 case BTA_HH_SET_PROTO_EVT:
1443 BTIF_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status,
1444 p_data->dev_status.handle);
1445 param.set_proto.handle = p_data->dev_status.handle;
1446 param.set_proto.status = p_data->dev_status.status;
1447 btc_hh_cb_to_app(ESP_HIDH_SET_PROTO_EVT, ¶m);
1448 break;
1449 case BTA_HH_GET_RPT_EVT: {
1450 BT_HDR *hdr = p_data->hs_data.rsp_data.p_rpt_data;
1451 uint8_t *data = NULL;
1452 uint16_t len = 0;
1453 BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->hs_data.status, p_data->hs_data.handle);
1454 /* p_rpt_data is NULL in HANDSHAKE response case */
1455 if (hdr) {
1456 data = (uint8_t *)(hdr + 1) + hdr->offset;
1457 len = hdr->len;
1458 }
1459 param.get_rpt.handle = p_data->hs_data.handle;
1460 param.get_rpt.status = p_data->hs_data.status;
1461 param.get_rpt.len = len;
1462 param.get_rpt.data = data;
1463 btc_hh_cb_to_app(ESP_HIDH_GET_RPT_EVT, ¶m);
1464 break;
1465 }
1466 case BTA_HH_SET_RPT_EVT:
1467 BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status,
1468 p_data->dev_status.handle);
1469 param.set_rpt.handle = p_data->dev_status.handle;
1470 param.set_rpt.status = p_data->dev_status.status;
1471 btc_hh_cb_to_app(ESP_HIDH_SET_RPT_EVT, ¶m);
1472 break;
1473 case BTA_HH_GET_IDLE_EVT:
1474 BTC_TRACE_DEBUG("handle = %d, status = %d, rate = %d", p_data->hs_data.handle, p_data->hs_data.status,
1475 p_data->hs_data.rsp_data.idle_rate);
1476 param.get_idle.handle = p_data->hs_data.handle;
1477 param.get_idle.status = p_data->hs_data.status;
1478 param.get_idle.idle_rate = p_data->hs_data.rsp_data.idle_rate;
1479 btc_hh_cb_to_app(ESP_HIDH_GET_IDLE_EVT, ¶m);
1480 break;
1481 case BTA_HH_SET_IDLE_EVT:
1482 BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status, p_data->dev_status.handle);
1483 param.set_idle.handle = p_data->dev_status.handle;
1484 param.set_idle.status = p_data->dev_status.status;
1485 btc_hh_cb_to_app(BTA_HH_SET_IDLE_EVT, ¶m);
1486 break;
1487 case BTA_HH_ADD_DEV_EVT:
1488 BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_info.status, p_data->dev_info.handle);
1489 for (uint8_t i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
1490 if (memcmp(btc_hh_cb.added_devices[i].bd_addr, p_data->dev_info.bda, BD_ADDR_LEN) == 0) {
1491 if (p_data->dev_info.status == BTA_HH_OK) {
1492 btc_hh_cb.added_devices[i].dev_handle = p_data->dev_info.handle;
1493 } else {
1494 memset(btc_hh_cb.added_devices[i].bd_addr, 0, BD_ADDR_LEN);
1495 btc_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
1496 }
1497 break;
1498 }
1499 }
1500 if (btc_hh_cb.add_event == BTC_HH_SET_INFO_EVT) {
1501 param.set_info.handle = p_data->dev_info.handle;
1502 param.set_info.status = p_data->dev_info.status;
1503 memcpy(param.set_info.bd_addr, p_data->dev_info.bda, BD_ADDR_LEN);
1504 btc_hh_cb_to_app(ESP_HIDH_SET_INFO_EVT, ¶m);
1505 } else {
1506 param.add_dev.handle = p_data->dev_info.handle;
1507 param.add_dev.status = p_data->dev_info.status;
1508 memcpy(param.add_dev.bd_addr, p_data->dev_info.bda, BD_ADDR_LEN);
1509 btc_hh_cb_to_app(ESP_HIDH_ADD_DEV_EVT, ¶m);
1510 }
1511 break;
1512 case BTA_HH_RMV_DEV_EVT:
1513 BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_info.status, p_data->dev_info.handle);
1514 param.rmv_dev.handle = p_data->dev_info.status;
1515 param.rmv_dev.status = p_data->dev_info.handle;
1516 memcpy(param.rmv_dev.bd_addr, p_data->dev_info.bda, BD_ADDR_LEN);
1517 btc_hh_cb_to_app(ESP_HIDH_RMV_DEV_EVT, ¶m);
1518 break;
1519 case BTA_HH_DATA_IND_EVT:
1520 BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->int_data.status, p_data->int_data.handle);
1521 if (p_data->int_data.status == BTA_HH_OK && p_data->int_data.p_data) {
1522 param.data_ind.len = p_data->int_data.p_data->len;
1523 param.data_ind.data = p_data->int_data.p_data->data + p_data->int_data.p_data->offset;
1524 }
1525 param.data_ind.handle = p_data->int_data.handle;
1526 param.data_ind.status = p_data->int_data.status;
1527 param.data_ind.proto_mode = proto_mode_change_to_upper_layer(p_data->int_data.proto_mode);
1528 btc_hh_cb_to_app(ESP_HIDH_DATA_IND_EVT, ¶m);
1529 break;
1530 case BTA_HH_API_ERR_EVT:
1531 break;
1532 default:
1533 BTC_TRACE_WARNING("%s: Unhandled event: %d", __func__, msg->act);
1534 break;
1535 }
1536 btc_hh_cb_arg_deep_free(msg);
1537 }
1538
btc_hh_arg_deep_copy(btc_msg_t * msg,void * p_dest,void * p_src)1539 void btc_hh_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
1540 {
1541 btc_hidh_args_t *dst = (btc_hidh_args_t *)p_dest;
1542 btc_hidh_args_t *src = (btc_hidh_args_t *)p_src;
1543
1544 switch (msg->act) {
1545 case BTC_HH_SET_INFO_EVT:
1546 dst->set_info.hid_info = (esp_hidh_hid_info_t *)osi_malloc(sizeof(esp_hidh_hid_info_t));
1547 if (dst->set_info.hid_info) {
1548 memcpy(dst->set_info.hid_info, src->set_info.hid_info, sizeof(esp_hidh_hid_info_t));
1549 } else {
1550 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
1551 }
1552 break;
1553 case BTC_HH_SET_REPORT_EVT:
1554 dst->set_report.report = (uint8_t *)osi_malloc(src->set_report.len);
1555 if (dst->set_report.report) {
1556 memcpy(dst->set_report.report, src->set_report.report, src->set_report.len);
1557 } else {
1558 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
1559 }
1560 break;
1561 case BTC_HH_SEND_DATA_EVT:
1562 dst->send_data.data = (uint8_t *)osi_malloc(src->send_data.len);
1563 if (dst->send_data.data) {
1564 memcpy(dst->send_data.data, src->send_data.data, src->send_data.len);
1565 } else {
1566 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
1567 }
1568 break;
1569 default:
1570 break;
1571 }
1572 }
1573
1574 #endif // HID_HOST_INCLUDED == TRUE
1575