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