1 /*
2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "sys/queue.h"
8 #include "esp_hidh_private.h"
9 #include "bt_hidh.h"
10 #include "ble_hidh.h"
11 #include <string.h>
12 #include <stdbool.h>
13 #include "esp_event_base.h"
14
15 ESP_EVENT_DEFINE_BASE(ESP_HIDH_EVENTS);
16 #define ESP_HIDH_DELAY_FREE_TO 100000 // us
17
18 static const char *TAG = "ESP_HIDH";
19
20 static esp_hidh_dev_head_t s_esp_hidh_devices;
21 static esp_timer_handle_t s_esp_hidh_timer;
22 static xSemaphoreHandle s_esp_hidh_devices_semaphore = NULL;
23
24 static void esp_hidh_dev_delay_free(void *arg);
25
lock_devices(void)26 static inline void lock_devices(void)
27 {
28 if (s_esp_hidh_devices_semaphore != NULL) {
29 xSemaphoreTake(s_esp_hidh_devices_semaphore, portMAX_DELAY);
30 }
31 }
32
unlock_devices(void)33 static inline void unlock_devices(void)
34 {
35 if (s_esp_hidh_devices_semaphore != NULL) {
36 xSemaphoreGive(s_esp_hidh_devices_semaphore);
37 }
38 }
39
40
41 /*
42 * Public Functions
43 * */
44
esp_hidh_dev_exists(esp_hidh_dev_t * dev)45 bool esp_hidh_dev_exists(esp_hidh_dev_t *dev)
46 {
47 if (dev == NULL) {
48 return false;
49 }
50 esp_hidh_dev_t * d = NULL;
51 lock_devices();
52 TAILQ_FOREACH(d, &s_esp_hidh_devices, devices) {
53 if (d == dev) {
54 unlock_devices();
55 return true;
56 }
57 }
58 unlock_devices();
59 return false;
60 }
61
esp_hidh_init(const esp_hidh_config_t * config)62 esp_err_t esp_hidh_init(const esp_hidh_config_t *config)
63 {
64 esp_err_t err = ESP_FAIL;
65 if (config == NULL) {
66 ESP_LOGE(TAG, "Config is NULL");
67 return err;
68 }
69
70 if (s_esp_hidh_devices_semaphore != NULL) {
71 ESP_LOGE(TAG, "Already initialized");
72 return err;
73 }
74
75 TAILQ_INIT(&s_esp_hidh_devices);
76
77 esp_timer_create_args_t timer_config = {
78 .callback = &esp_hidh_dev_delay_free,
79 .arg = NULL,
80 .name = "hidh_timer"
81 };
82
83 if ((err = esp_timer_create(&timer_config, &s_esp_hidh_timer)) != ESP_OK) {
84 ESP_LOGE(TAG, "%s create timer failed!", __func__);
85 return err;
86 }
87
88 s_esp_hidh_devices_semaphore = xSemaphoreCreateMutex();
89 if (s_esp_hidh_devices_semaphore == NULL) {
90 ESP_LOGE(TAG, "xSemaphoreCreateMutex failed!");
91 return err;
92 }
93 // unlock_devices();
94 err = ESP_OK;
95
96 #if CONFIG_BT_HID_HOST_ENABLED
97 if (err == ESP_OK) {
98 err = esp_bt_hidh_init(config);
99 }
100 #endif /* CONFIG_BT_HID_HOST_ENABLED */
101
102 #if CONFIG_GATTC_ENABLE
103 if (err == ESP_OK) {
104 err = esp_ble_hidh_init(config);
105 }
106 #endif /* CONFIG_GATTC_ENABLE */
107
108 if (err != ESP_OK) {
109 vSemaphoreDelete(s_esp_hidh_devices_semaphore);
110 s_esp_hidh_devices_semaphore = NULL;
111 esp_timer_delete(s_esp_hidh_timer);
112 s_esp_hidh_timer = NULL;
113 }
114
115 return err;
116 }
117
esp_hidh_deinit(void)118 esp_err_t esp_hidh_deinit(void)
119 {
120 esp_err_t err = ESP_FAIL;
121 if (s_esp_hidh_devices_semaphore == NULL) {
122 ESP_LOGE(TAG, "Already uninitialized");
123 return err;
124 }
125
126 if (esp_timer_is_active(s_esp_hidh_timer)) {
127 ESP_LOGE(TAG, "Busy, try again later!");
128 return ESP_ERR_NOT_FINISHED;
129 }
130
131 if (!TAILQ_EMPTY(&s_esp_hidh_devices)) {
132 ESP_LOGE(TAG, "Please disconnect all devices first!");
133 return err;
134 }
135
136 err = ESP_OK;
137
138 #if CONFIG_BT_HID_HOST_ENABLED
139 if (err == ESP_OK) {
140 err = esp_bt_hidh_deinit();
141 }
142 #endif /* CONFIG_BT_HID_HOST_ENABLED */
143
144 #if CONFIG_GATTC_ENABLE
145 if (err == ESP_OK) {
146 err = esp_ble_hidh_deinit();
147 }
148 #endif /* CONFIG_GATTC_ENABLE */
149
150 if (err == ESP_OK) {
151 TAILQ_INIT(&s_esp_hidh_devices);
152 vSemaphoreDelete(s_esp_hidh_devices_semaphore);
153 s_esp_hidh_devices_semaphore = NULL;
154 esp_timer_delete(s_esp_hidh_timer);
155 s_esp_hidh_timer = NULL;
156 }
157 return err;
158 }
159
160 #if CONFIG_BLUEDROID_ENABLED
esp_hidh_dev_open(esp_bd_addr_t bda,esp_hid_transport_t transport,uint8_t remote_addr_type)161 esp_hidh_dev_t *esp_hidh_dev_open(esp_bd_addr_t bda, esp_hid_transport_t transport, uint8_t remote_addr_type)
162 {
163 if (esp_hidh_dev_get_by_bda(bda) != NULL) {
164 ESP_LOGE(TAG, "Already Connected");
165 return NULL;
166 }
167 esp_hidh_dev_t *dev = NULL;
168 #if CONFIG_GATTC_ENABLE
169 if (transport == ESP_HID_TRANSPORT_BLE) {
170 dev = esp_ble_hidh_dev_open(bda, (esp_ble_addr_type_t)remote_addr_type);
171 }
172 #endif /* CONFIG_GATTC_ENABLE */
173 #if CONFIG_BT_HID_HOST_ENABLED
174 if (transport == ESP_HID_TRANSPORT_BT) {
175 dev = esp_bt_hidh_dev_open(bda);
176 }
177 #endif /* CONFIG_BT_HID_HOST_ENABLED */
178 return dev;
179 }
180 #endif /* CONFIG_BLUEDROID_ENABLED */
181
esp_hidh_dev_close(esp_hidh_dev_t * dev)182 esp_err_t esp_hidh_dev_close(esp_hidh_dev_t *dev)
183 {
184 esp_err_t ret = ESP_OK;
185 if (esp_hidh_dev_exists(dev)) {
186 esp_hidh_dev_lock(dev);
187 ret = dev->close(dev);
188 esp_hidh_dev_unlock(dev);
189 } else {
190 ret = ESP_FAIL;
191 }
192 return ret;
193 }
194
esp_hidh_dev_dump(esp_hidh_dev_t * dev,FILE * fp)195 void esp_hidh_dev_dump(esp_hidh_dev_t *dev, FILE *fp)
196 {
197 if (esp_hidh_dev_exists(dev)) {
198 esp_hidh_dev_lock(dev);
199 dev->dump(dev, fp);
200 esp_hidh_dev_unlock(dev);
201 }
202 }
203
esp_hidh_dev_output_set(esp_hidh_dev_t * dev,size_t map_index,size_t report_id,uint8_t * value,size_t value_len)204 esp_err_t esp_hidh_dev_output_set(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, uint8_t *value, size_t value_len)
205 {
206 esp_err_t ret = ESP_OK;
207 if (esp_hidh_dev_exists(dev)) {
208 esp_hidh_dev_lock(dev);
209 ret = dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_OUTPUT, value, value_len);
210 esp_hidh_dev_unlock(dev);
211 } else {
212 ret = ESP_FAIL;
213 }
214 return ret;
215 }
216
esp_hidh_dev_feature_set(esp_hidh_dev_t * dev,size_t map_index,size_t report_id,uint8_t * value,size_t value_len)217 esp_err_t esp_hidh_dev_feature_set(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, uint8_t *value, size_t value_len)
218 {
219 esp_err_t ret = ESP_OK;
220 if (esp_hidh_dev_exists(dev)) {
221 esp_hidh_dev_lock(dev);
222 ret = dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, value, value_len);
223 esp_hidh_dev_unlock(dev);
224 } else {
225 ret = ESP_FAIL;
226 }
227 return ret;
228 }
229
esp_hidh_dev_feature_get(esp_hidh_dev_t * dev,size_t map_index,size_t report_id,size_t max_length,uint8_t * value,size_t * value_len)230 esp_err_t esp_hidh_dev_feature_get(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, size_t max_length, uint8_t *value, size_t *value_len)
231 {
232 esp_err_t ret = ESP_OK;
233 if (esp_hidh_dev_exists(dev)) {
234 esp_hidh_dev_lock(dev);
235 ret = dev->report_read(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, max_length, value, value_len);
236 esp_hidh_dev_unlock(dev);
237 } else {
238 ret = ESP_FAIL;
239 }
240 return ret;
241 }
242
esp_hidh_dev_set_report(esp_hidh_dev_t * dev,size_t map_index,size_t report_id,int report_type,uint8_t * data,size_t length)243 esp_err_t esp_hidh_dev_set_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t *data, size_t length)
244 {
245 esp_err_t ret = ESP_OK;
246 if (esp_hidh_dev_exists(dev)) {
247 esp_hidh_dev_lock(dev);
248 if (dev->set_report) {
249 ret = dev->set_report(dev, map_index, report_id, report_type, data, length);
250 } else {
251 ret = ESP_ERR_NOT_SUPPORTED;
252 }
253 esp_hidh_dev_unlock(dev);
254 } else {
255 ret = ESP_FAIL;
256 }
257 return ret;
258 }
259
esp_hidh_dev_get_report(esp_hidh_dev_t * dev,size_t map_index,size_t report_id,int report_type,size_t max_len)260 esp_err_t esp_hidh_dev_get_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type,
261 size_t max_len)
262 {
263 esp_err_t ret = ESP_OK;
264 if (esp_hidh_dev_exists(dev)) {
265 esp_hidh_dev_lock(dev);
266 ret = dev->report_read(dev, map_index, report_id, report_type, max_len, NULL, NULL);
267 esp_hidh_dev_unlock(dev);
268 } else {
269 ret = ESP_FAIL;
270 }
271 return ret;
272 }
273
esp_hidh_dev_get_idle(esp_hidh_dev_t * dev)274 esp_err_t esp_hidh_dev_get_idle(esp_hidh_dev_t *dev)
275 {
276 esp_err_t ret = ESP_OK;
277 if (esp_hidh_dev_exists(dev)) {
278 esp_hidh_dev_lock(dev);
279 if (dev->get_idle) {
280 ret = dev->get_idle(dev);
281 } else {
282 ret = ESP_ERR_NOT_SUPPORTED;
283 }
284 esp_hidh_dev_unlock(dev);
285 } else {
286 ret = ESP_FAIL;
287 }
288 return ret;
289 }
290
esp_hidh_dev_set_idle(esp_hidh_dev_t * dev,uint8_t idle_time)291 esp_err_t esp_hidh_dev_set_idle(esp_hidh_dev_t *dev, uint8_t idle_time)
292 {
293 esp_err_t ret = ESP_OK;
294 if (esp_hidh_dev_exists(dev)) {
295 esp_hidh_dev_lock(dev);
296 if (dev->set_idle) {
297 ret = dev->set_idle(dev, idle_time);
298 } else {
299 ret = ESP_ERR_NOT_SUPPORTED;
300 }
301 esp_hidh_dev_unlock(dev);
302 } else {
303 ret = ESP_FAIL;
304 }
305 return ret;
306 }
307
esp_hidh_dev_get_protocol(esp_hidh_dev_t * dev)308 esp_err_t esp_hidh_dev_get_protocol(esp_hidh_dev_t *dev)
309 {
310 esp_err_t ret = ESP_OK;
311 if (esp_hidh_dev_exists(dev)) {
312 esp_hidh_dev_lock(dev);
313 if (dev->get_protocol) {
314 ret = dev->get_protocol(dev);
315 } else {
316 ret = ESP_ERR_NOT_SUPPORTED;
317 }
318 esp_hidh_dev_unlock(dev);
319 } else {
320 ret = ESP_FAIL;
321 }
322 return ret;
323 }
324
esp_hidh_dev_set_protocol(esp_hidh_dev_t * dev,uint8_t protocol_mode)325 esp_err_t esp_hidh_dev_set_protocol(esp_hidh_dev_t *dev, uint8_t protocol_mode)
326 {
327 esp_err_t ret = ESP_OK;
328 if (esp_hidh_dev_exists(dev)) {
329 esp_hidh_dev_lock(dev);
330 if (dev->set_protocol) {
331 ret = dev->set_protocol(dev, protocol_mode);
332 } else {
333 ret = ESP_ERR_NOT_SUPPORTED;
334 }
335 esp_hidh_dev_unlock(dev);
336 } else {
337 ret = ESP_FAIL;
338 }
339 return ret;
340 }
341
esp_hidh_dev_bda_get(esp_hidh_dev_t * dev)342 const uint8_t *esp_hidh_dev_bda_get(esp_hidh_dev_t *dev)
343 {
344 uint8_t *ret = NULL;
345 #if CONFIG_BLUEDROID_ENABLED
346 if (esp_hidh_dev_exists(dev)) {
347 esp_hidh_dev_lock(dev);
348 ret = dev->bda;
349 esp_hidh_dev_unlock(dev);
350 }
351 #endif /* CONFIG_BLUEDROID_ENABLED */
352 return ret;
353 }
354
esp_hidh_dev_transport_get(esp_hidh_dev_t * dev)355 esp_hid_transport_t esp_hidh_dev_transport_get(esp_hidh_dev_t *dev)
356 {
357 esp_hid_transport_t ret = ESP_HID_TRANSPORT_MAX;
358 if (esp_hidh_dev_exists(dev)) {
359 esp_hidh_dev_lock(dev);
360 ret = dev->transport;
361 esp_hidh_dev_unlock(dev);
362 }
363 return ret;
364 }
365
esp_hidh_dev_config_get(esp_hidh_dev_t * dev)366 const esp_hid_device_config_t *esp_hidh_dev_config_get(esp_hidh_dev_t *dev)
367 {
368 esp_hid_device_config_t *ret = NULL;
369 if (esp_hidh_dev_exists(dev)) {
370 esp_hidh_dev_lock(dev);
371 ret = &dev->config;
372 esp_hidh_dev_unlock(dev);
373 }
374 return ret;
375 }
376
esp_hidh_dev_name_get(esp_hidh_dev_t * dev)377 const char *esp_hidh_dev_name_get(esp_hidh_dev_t *dev)
378 {
379 const char * ret = NULL;
380 if (esp_hidh_dev_exists(dev)) {
381 esp_hidh_dev_lock(dev);
382 ret = dev->config.device_name ? dev->config.device_name : "";
383 esp_hidh_dev_unlock(dev);
384 }
385 return ret;
386 }
387
esp_hidh_dev_manufacturer_get(esp_hidh_dev_t * dev)388 const char *esp_hidh_dev_manufacturer_get(esp_hidh_dev_t *dev)
389 {
390 const char *ret = NULL;
391 if (esp_hidh_dev_exists(dev)) {
392 esp_hidh_dev_lock(dev);
393 ret = dev->config.manufacturer_name ? dev->config.manufacturer_name : "";
394 esp_hidh_dev_unlock(dev);
395 }
396 return ret;
397 }
398
esp_hidh_dev_serial_get(esp_hidh_dev_t * dev)399 const char *esp_hidh_dev_serial_get(esp_hidh_dev_t *dev)
400 {
401 const char *ret = NULL;
402 if (esp_hidh_dev_exists(dev)) {
403 esp_hidh_dev_lock(dev);
404 ret = dev->config.serial_number ? dev->config.serial_number : "";
405 esp_hidh_dev_unlock(dev);
406 }
407 return ret;
408 }
409
esp_hidh_dev_vendor_id_get(esp_hidh_dev_t * dev)410 uint16_t esp_hidh_dev_vendor_id_get(esp_hidh_dev_t *dev)
411 {
412 uint16_t ret = 0;
413 if (esp_hidh_dev_exists(dev)) {
414 esp_hidh_dev_lock(dev);
415 ret = dev->config.vendor_id;
416 esp_hidh_dev_unlock(dev);
417 }
418 return ret;
419 }
420
esp_hidh_dev_product_id_get(esp_hidh_dev_t * dev)421 uint16_t esp_hidh_dev_product_id_get(esp_hidh_dev_t *dev)
422 {
423 uint16_t ret = 0;
424 if (esp_hidh_dev_exists(dev)) {
425 esp_hidh_dev_lock(dev);
426 ret = dev->config.product_id;
427 esp_hidh_dev_unlock(dev);
428 }
429 return ret;
430 }
431
esp_hidh_dev_version_get(esp_hidh_dev_t * dev)432 uint16_t esp_hidh_dev_version_get(esp_hidh_dev_t *dev)
433 {
434 uint16_t ret = 0;
435 if (!esp_hidh_dev_exists(dev)) {
436 esp_hidh_dev_lock(dev);
437 ret = dev->config.version;
438 esp_hidh_dev_unlock(dev);
439 }
440 return ret;
441 }
442
esp_hidh_dev_usage_get(esp_hidh_dev_t * dev)443 esp_hid_usage_t esp_hidh_dev_usage_get(esp_hidh_dev_t *dev)
444 {
445 esp_hid_usage_t ret = ESP_HID_USAGE_GENERIC;
446 if (esp_hidh_dev_exists(dev)) {
447 esp_hidh_dev_lock(dev);
448 ret = dev->usage;
449 esp_hidh_dev_unlock(dev);
450 }
451 return ret;
452 }
453
esp_hidh_dev_reports_get(esp_hidh_dev_t * dev,size_t * num_reports,esp_hid_report_item_t ** reports)454 esp_err_t esp_hidh_dev_reports_get(esp_hidh_dev_t *dev, size_t *num_reports, esp_hid_report_item_t **reports)
455 {
456 esp_err_t ret = 0;
457 esp_hid_report_item_t *r = NULL;
458
459 if (!esp_hidh_dev_exists(dev)) {
460 return ESP_FAIL;
461 }
462
463 esp_hidh_dev_lock(dev);
464 do {
465 r = (esp_hid_report_item_t *)malloc(sizeof(esp_hid_report_item_t) * dev->reports_len);
466 if (r == NULL) {
467 ret = ESP_FAIL;
468 break;
469 }
470
471 esp_hidh_dev_report_t *dr = dev->reports;
472 for (uint8_t i = 0; i < dev->reports_len; i++) {
473 if (dr == NULL) {
474 // error
475 free(r);
476 ret = ESP_FAIL;
477 goto error_;
478 }
479 r[i].map_index = dr->map_index;
480 r[i].protocol_mode = dr->protocol_mode;
481 r[i].usage = dr->usage;
482 r[i].report_id = dr->report_id;
483 r[i].report_type = dr->report_type;
484 r[i].value_len = dr->value_len;
485
486 dr = dr->next;
487 }
488 *reports = r;
489 *num_reports = dev->reports_len;
490 } while (0);
491 error_:;
492 esp_hidh_dev_unlock(dev);
493
494 return ret;
495 }
496
esp_hidh_dev_report_maps_get(esp_hidh_dev_t * dev,size_t * num_maps,esp_hid_raw_report_map_t ** maps)497 esp_err_t esp_hidh_dev_report_maps_get(esp_hidh_dev_t *dev, size_t *num_maps, esp_hid_raw_report_map_t **maps)
498 {
499 if (!esp_hidh_dev_exists(dev)) {
500 return ESP_FAIL;
501 }
502 esp_hidh_dev_lock(dev);
503 *num_maps = dev->config.report_maps_len;
504 *maps = dev->config.report_maps;
505 esp_hidh_dev_unlock(dev);
506 return ESP_OK;
507 }
508
509
510 /*
511 * Private Functions
512 * */
513
514 /**
515 * `lock_devices()` only protect the devices list, this mutex protect the single deivce instance.
516 */
esp_hidh_dev_lock(esp_hidh_dev_t * dev)517 inline void esp_hidh_dev_lock(esp_hidh_dev_t *dev)
518 {
519 if (dev && dev->mutex != NULL) {
520 xSemaphoreTake(dev->mutex, portMAX_DELAY);
521 }
522 }
523
esp_hidh_dev_unlock(esp_hidh_dev_t * dev)524 inline void esp_hidh_dev_unlock(esp_hidh_dev_t *dev)
525 {
526 if (dev && dev->mutex != NULL) {
527 xSemaphoreGive(dev->mutex);
528 }
529 }
530
esp_hidh_dev_wait(esp_hidh_dev_t * dev)531 inline void esp_hidh_dev_wait(esp_hidh_dev_t *dev)
532 {
533 if (dev && dev->semaphore != NULL) {
534 xSemaphoreTake(dev->semaphore, portMAX_DELAY);
535 }
536 }
537
esp_hidh_dev_send(esp_hidh_dev_t * dev)538 inline void esp_hidh_dev_send(esp_hidh_dev_t *dev)
539 {
540 if (dev && dev->semaphore != NULL) {
541 xSemaphoreGive(dev->semaphore);
542 }
543 }
544
esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t * dev,uint16_t handle)545 esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, uint16_t handle)
546 {
547 esp_hidh_dev_report_t *r = dev->reports;
548 while (r) {
549 if (r->handle == handle) {
550 return r;
551 }
552 r = r->next;
553 }
554 return NULL;
555 }
556
esp_hidh_dev_get_report_by_id_type_proto(esp_hidh_dev_t * dev,size_t map_index,size_t report_id,int report_type,uint8_t protocol_mode)557 esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_type_proto(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t protocol_mode)
558 {
559 esp_hidh_dev_report_t *r = dev->reports;
560 while (r) {
561 if (r->map_index == map_index && r->report_type == report_type && r->report_id == report_id &&
562 r->protocol_mode == protocol_mode) {
563 return r;
564 }
565 r = r->next;
566 }
567 return NULL;
568 }
569
esp_hidh_dev_get_report_by_id_and_type(esp_hidh_dev_t * dev,size_t map_index,size_t report_id,int report_type)570 esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_and_type(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type)
571 {
572 esp_hidh_dev_report_t *r = dev->reports;
573 while (r) {
574 if (r->map_index == map_index && r->report_id == report_id && r->report_type == report_type && r->protocol_mode == ESP_HID_PROTOCOL_MODE_REPORT) {
575 return r;
576 }
577 r = r->next;
578 }
579 return NULL;
580 }
581
esp_hidh_dev_get_input_report_by_id_and_proto(esp_hidh_dev_t * dev,size_t report_id,int protocol_mode)582 esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_id_and_proto(esp_hidh_dev_t *dev, size_t report_id, int protocol_mode)
583 {
584 esp_hidh_dev_report_t *r = dev->reports;
585 while (r) {
586 if (r->report_id == report_id && (r->report_type & ESP_HID_REPORT_TYPE_INPUT) && r->protocol_mode == protocol_mode) {
587 return r;
588 }
589 r = r->next;
590 }
591 return NULL;
592 }
593
esp_hidh_dev_get_input_report_by_len_and_proto(esp_hidh_dev_t * dev,size_t len,int protocol_mode)594 esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_len_and_proto(esp_hidh_dev_t *dev, size_t len, int protocol_mode)
595 {
596 esp_hidh_dev_report_t *r = dev->reports;
597 while (r) {
598 if (r->value_len == len && (r->report_type & ESP_HID_REPORT_TYPE_INPUT) && r->protocol_mode == protocol_mode) {
599 return r;
600 }
601 r = r->next;
602 }
603 return NULL;
604 }
605
606 /**
607 * If no Report ID item tags are present in the Report descriptor, it
608 * can be assumed that only one Input, Output, and Feature report structure exists
609 * and together they represent all of the device’s data.
610 */
esp_hidh_dev_get_input_report_by_proto_and_data(esp_hidh_dev_t * dev,int protocol_mode,size_t len,const uint8_t * data,bool * has_report_id)611 esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_proto_and_data(esp_hidh_dev_t *dev, int protocol_mode,
612 size_t len, const uint8_t *data, bool *has_report_id)
613 {
614 esp_hidh_dev_report_t *r = dev->reports;
615 *has_report_id = false;
616 // first, assume data not include report id
617 while (r) {
618 if (r->value_len == len && r->report_id == 0 && (r->report_type & ESP_HID_REPORT_TYPE_INPUT) &&
619 r->protocol_mode == protocol_mode) {
620 *has_report_id = false;
621 break;
622 }
623 r = r->next;
624 }
625 // indicate data include report id
626 if (r == NULL) {
627 if (*data == 0) {
628 ESP_LOGE(TAG, "data not include report id!");
629 *has_report_id = false;
630 return NULL;
631 }
632 r = dev->reports;
633 while (r) {
634 if (r->value_len == len - 1 && r->report_id == *data && (r->report_type & ESP_HID_REPORT_TYPE_INPUT) &&
635 r->protocol_mode == protocol_mode) {
636 *has_report_id = true;
637 break;
638 }
639 r = r->next;
640 }
641 }
642 return r;
643 }
644
esp_hidh_dev_resources_free(esp_hidh_dev_t * dev)645 static void esp_hidh_dev_resources_free(esp_hidh_dev_t *dev)
646 {
647 esp_hidh_dev_lock(dev);
648 if (dev->semaphore) {
649 vSemaphoreDelete(dev->semaphore);
650 }
651 if (dev->trans_timer) {
652 esp_timer_stop(dev->trans_timer);
653 esp_timer_delete(dev->trans_timer);
654 dev->trans_timer = NULL;
655 }
656 free((void *)dev->config.device_name);
657 free((void *)dev->config.manufacturer_name);
658 free((void *)dev->config.serial_number);
659 for (uint8_t d = 0; d < dev->config.report_maps_len; d++) {
660 free((void *)dev->config.report_maps[d].data);
661 }
662 free((void *)dev->config.report_maps);
663 esp_hidh_dev_report_t *r;
664 while (dev->reports) {
665 r = dev->reports;
666 dev->reports = dev->reports->next;
667 free(r);
668 }
669 esp_hidh_dev_unlock(dev);
670 if (dev->mutex) {
671 vSemaphoreDelete(dev->mutex);
672 }
673 free(dev);
674 }
675
esp_hidh_dev_malloc()676 esp_hidh_dev_t *esp_hidh_dev_malloc()
677 {
678 esp_hidh_dev_t *dev = (esp_hidh_dev_t *)calloc(1, sizeof(esp_hidh_dev_t));
679 if (dev == NULL) {
680 ESP_LOGE(TAG, "malloc esp_hidh_dev_t failed");
681 return NULL;
682 }
683
684 dev->semaphore = xSemaphoreCreateBinary();
685 if (dev->semaphore == NULL) {
686 ESP_LOGE(TAG, "malloc semaphore failed");
687 esp_hidh_dev_resources_free(dev);
688 return NULL;
689 }
690
691 dev->mutex = xSemaphoreCreateMutex();
692 if (dev->mutex == NULL) {
693 ESP_LOGE(TAG, "malloc mutex failed");
694 esp_hidh_dev_resources_free(dev);
695 return NULL;
696 }
697
698 lock_devices();
699 TAILQ_INSERT_TAIL(&s_esp_hidh_devices, dev, devices);
700 unlock_devices();
701
702 return dev;
703 }
704
705 /**
706 * The `dev` is allocated by the internal function, and it should also be freed by the internal function. So, when the
707 * user call this function, it will do nothing.
708 */
esp_hidh_dev_free(esp_hidh_dev_t * dev)709 esp_err_t esp_hidh_dev_free(esp_hidh_dev_t *dev)
710 {
711 return ESP_OK;
712 }
713
esp_hidh_dev_free_inner(esp_hidh_dev_t * dev)714 esp_err_t esp_hidh_dev_free_inner(esp_hidh_dev_t *dev)
715 {
716 esp_err_t ret = ESP_FAIL;
717
718 if (dev == NULL) {
719 return ret;
720 }
721
722 esp_hidh_dev_t *d = NULL;
723 esp_hidh_dev_t *next = NULL;
724 lock_devices();
725 TAILQ_FOREACH_SAFE(d, &s_esp_hidh_devices, devices, next) {
726 if (d == dev) {
727 TAILQ_REMOVE(&s_esp_hidh_devices, d, devices);
728 esp_hidh_dev_resources_free(d);
729 ret = ESP_OK;
730 break;
731 }
732 }
733 unlock_devices();
734 if (ret != ESP_OK) {
735 ESP_LOGW(TAG, "device not found");
736 } else {
737 ESP_LOGD(TAG, "device removed");
738 }
739 return ret;
740 }
741
esp_hidh_dev_delay_free(void * arg)742 static void esp_hidh_dev_delay_free(void *arg)
743 {
744 esp_hidh_dev_t *d = NULL;
745 esp_hidh_dev_t *next = NULL;
746 lock_devices();
747 TAILQ_FOREACH_SAFE(d, &s_esp_hidh_devices, devices, next) {
748 if (!d->in_use) {
749 TAILQ_REMOVE(&s_esp_hidh_devices, d, devices);
750 esp_hidh_dev_resources_free(d);
751 }
752 }
753 unlock_devices();
754 }
755
756 #if CONFIG_BLUEDROID_ENABLED
esp_hidh_dev_get_by_bda(esp_bd_addr_t bda)757 esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda)
758 {
759 esp_hidh_dev_t * d = NULL;
760 lock_devices();
761 TAILQ_FOREACH(d, &s_esp_hidh_devices, devices) {
762 if (memcmp(bda, d->bda, sizeof(esp_bd_addr_t)) == 0) {
763 unlock_devices();
764 return d;
765 }
766 }
767 unlock_devices();
768 return NULL;
769 }
770
esp_hidh_dev_get_by_handle(uint8_t handle)771 esp_hidh_dev_t *esp_hidh_dev_get_by_handle(uint8_t handle)
772 {
773 #if CONFIG_BT_HID_HOST_ENABLED
774 esp_hidh_dev_t * d = NULL;
775 lock_devices();
776 TAILQ_FOREACH(d, &s_esp_hidh_devices, devices) {
777 if (d->transport == ESP_HID_TRANSPORT_BT && d->bt.handle == handle) {
778 unlock_devices();
779 return d;
780 }
781 }
782 unlock_devices();
783 #endif /* CONFIG_BT_HID_HOST_ENABLED */
784 return NULL;
785 }
786
esp_hidh_dev_get_by_conn_id(uint16_t conn_id)787 esp_hidh_dev_t *esp_hidh_dev_get_by_conn_id(uint16_t conn_id)
788 {
789 #if CONFIG_GATTC_ENABLE
790 esp_hidh_dev_t * d = NULL;
791 lock_devices();
792 TAILQ_FOREACH(d, &s_esp_hidh_devices, devices) {
793 if (d->transport == ESP_HID_TRANSPORT_BLE && d->ble.conn_id == conn_id) {
794 unlock_devices();
795 return d;
796 }
797 }
798 unlock_devices();
799 #endif /* CONFIG_GATTC_ENABLE */
800 return NULL;
801 }
802
803 /**
804 * The deep copy data append the end of the esp_hidh_event_data_t, move the data pointer to the correct address. This is
805 * a workaround way, it's better to use flexiable array in the interface.
806 */
esp_hidh_process_event_data_handler(void * event_handler_arg,esp_event_base_t event_base,int32_t event_id,void * event_data)807 void esp_hidh_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
808 void *event_data)
809 {
810 esp_hidh_event_t event = (esp_hidh_event_t)event_id;
811 esp_hidh_event_data_t *param = (esp_hidh_event_data_t *)event_data;
812
813 switch (event) {
814 case ESP_HIDH_INPUT_EVENT:
815 if (param->input.length && param->input.data) {
816 param->input.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t);
817 }
818 break;
819 case ESP_HIDH_FEATURE_EVENT:
820 if (param->feature.length && param->feature.data) {
821 param->feature.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t);
822 }
823 break;
824 case ESP_HIDH_OPEN_EVENT:
825 if (param->open.status != ESP_OK) {
826 if (s_esp_hidh_timer && !esp_timer_is_active(s_esp_hidh_timer) &&
827 esp_timer_start_once(s_esp_hidh_timer, ESP_HIDH_DELAY_FREE_TO) != ESP_OK) {
828 ESP_LOGE(TAG, "%s set hidh timer failed!", __func__);
829 }
830 }
831 break;
832 case ESP_HIDH_CLOSE_EVENT:
833 if (s_esp_hidh_timer && !esp_timer_is_active(s_esp_hidh_timer) &&
834 esp_timer_start_once(s_esp_hidh_timer, ESP_HIDH_DELAY_FREE_TO) != ESP_OK) {
835 ESP_LOGE(TAG, "%s set hidh timer failed!", __func__);
836 }
837 break;
838 default:
839 break;
840 }
841 }
842 #endif /* CONFIG_BLUEDROID_ENABLED */
843