1 // Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "bt_hidh.h"
16 #if CONFIG_BT_HID_HOST_ENABLED
17 #include "esp_hidh_private.h"
18 #include <string.h>
19 #include <stdbool.h>
20 
21 #include "freertos/FreeRTOS.h"
22 #include "freertos/task.h"
23 #include "freertos/semphr.h"
24 #include "osi/fixed_queue.h"
25 #include "string.h"
26 #include "esp_hidh_api.h"
27 
28 static const char *TAG = "BT_HIDH";
29 
30 // element of connection queue
31 typedef struct {
32     esp_hidh_dev_t* dev;
33 } conn_item_t;
34 
35 typedef struct {
36     fixed_queue_t *connection_queue; /* Queue of connection */
37     esp_event_loop_handle_t event_loop_handle;
38 } hidh_local_param_t;
39 
40 static hidh_local_param_t hidh_local_param;
41 #define TRANS_TO 1000000 // us
42 #define is_init() (hidh_local_param.event_loop_handle != NULL)
43 
44 #define get_protocol_mode(mode) (mode) ? "REPORT" : "BOOT"
45 static const char *s_esp_hh_evt_names[] = {"INIT", "DEINIT", "OPEN", "CLOSE", "GET_RPT", "SET_RPT", "GET_PROTO", "SET_PROTO", "GET_IDLE", "SET_IDLE", "GET_DSCP", "ADD_DEV", "RMV_DEV", "VC_UNPLUG", "DATA", "DATA_IND", "SET_INFO"};
46 static const char *s_esp_hh_status_names[] = {"OK",
47                                               "HS_HID_NOT_READY",
48                                               "HS_INVALID_RPT_ID",
49                                               "HS_TRANS_NOT_SPT",
50                                               "HS_INVALID_PARAM",
51                                               "HS_ERROR",
52                                               "ERR",
53                                               "ERR_SDP",
54                                               "ERR_PROTO",
55                                               "ERR_DB_FULL",
56                                               "ERR_TOD_UNSPT",
57                                               "ERR_NO_RES",
58                                               "ERR_AUTH_FAILED",
59                                               "ERR_HDL",
60                                               "ERR_SEC",
61                                               "BUSY",
62                                               "NO_DATA",
63                                               "NEED_INIT",
64                                               "NEED_DEINIT",
65                                               "NO_CONNECTION"};
66 
67 static esp_hidh_dev_t *hidh_dev_ctor(esp_bd_addr_t bda);
68 
get_trans_type_str(esp_hid_trans_type_t trans_type)69 static char *get_trans_type_str(esp_hid_trans_type_t trans_type)
70 {
71     switch (trans_type) {
72     case ESP_HID_TRANS_HANDSHAKE:
73         return "TRANS_HANDSHAKE";
74     case ESP_HID_TRANS_CONTROL:
75         return "TRANS_CONTROL";
76     case ESP_HID_TRANS_GET_REPORT:
77         return "TRANS_GET_REPORT";
78     case ESP_HID_TRANS_SET_REPORT:
79         return "TRANS_SET_REPORT";
80     case ESP_HID_TRANS_GET_PROTOCOL:
81         return "TRANS_GET_PROTOCOL";
82     case ESP_HID_TRANS_SET_PROTOCOL:
83         return "TRANS_SET_PROTOCOL";
84     case ESP_HID_TRANS_GET_IDLE:
85         return "TRANS_GET_IDLE";
86     case ESP_HID_TRANS_SET_IDLE:
87         return "TRANS_SET_IDLE";
88     case ESP_HID_TRANS_DATA:
89         return "TRANS_DATA";
90     case ESP_HID_TRANS_DATAC:
91         return "TRANS_DATAC";
92     case ESP_HID_TRANS_MAX:
93         return "TRANS_MAX";
94     default:
95         return "UNKOWN";
96     }
97 }
98 
bt_hidh_get_status(esp_hidh_status_t status)99 static esp_err_t bt_hidh_get_status(esp_hidh_status_t status)
100 {
101     esp_err_t ret = ESP_OK;
102     switch (status) {
103     case ESP_HIDH_OK:
104         ret = ESP_OK;
105         break;
106     case ESP_HIDH_ERR_NO_RES:
107         ret = ESP_ERR_NO_MEM;
108         break;
109     default:
110         ret = ESP_FAIL;
111         break;
112     }
113     return ret;
114 }
115 
utl_freebuf(void ** p)116 static void utl_freebuf(void **p)
117 {
118     if (*p != NULL) {
119         free(*p);
120         *p = NULL;
121     }
122 }
123 
transaction_timeout_handler(void * arg)124 static void transaction_timeout_handler(void *arg)
125 {
126     esp_hidh_dev_t *dev = (esp_hidh_dev_t *)arg;
127     if (dev != NULL && esp_hidh_dev_exists(dev)) {
128         ESP_LOGW(TAG, "transaction timeout!");
129         esp_hidh_dev_lock(dev);
130         dev->trans_type = ESP_HID_TRANS_MAX;
131         dev->report_id = 0;
132         dev->report_type = 0;
133         esp_hidh_dev_unlock(dev);
134     }
135 }
136 
set_trans(esp_hidh_dev_t * dev,esp_hid_trans_type_t trans_type)137 static inline void set_trans(esp_hidh_dev_t *dev, esp_hid_trans_type_t trans_type)
138 {
139     dev->trans_type = trans_type;
140     if (dev->trans_timer == NULL) {
141         esp_timer_create_args_t config = {
142             .callback = &transaction_timeout_handler,
143             .arg = (void *)dev,
144             .name = "hid_trans"
145         };
146         if (esp_timer_create(&config, &dev->trans_timer) != ESP_OK) {
147             ESP_LOGE(TAG, "create trans timer failed! trans:%s", get_trans_type_str(trans_type));
148             return;
149         }
150     }
151     if (!esp_timer_is_active(dev->trans_timer) && esp_timer_start_once(dev->trans_timer, TRANS_TO) != ESP_OK) {
152         ESP_LOGE(TAG, "set trans timer failed! trans:%s", get_trans_type_str(trans_type));
153     }
154 }
155 
reset_trans(esp_hidh_dev_t * dev)156 static inline void reset_trans(esp_hidh_dev_t *dev)
157 {
158     esp_hidh_dev_lock(dev);
159     dev->trans_type = ESP_HID_TRANS_MAX;
160     dev->report_id = 0;
161     dev->report_type = 0;
162     if (dev->trans_timer) {
163         esp_timer_stop(dev->trans_timer);
164     }
165     esp_hidh_dev_unlock(dev);
166 }
167 
is_trans_done(esp_hidh_dev_t * dev)168 static inline bool is_trans_done(esp_hidh_dev_t *dev)
169 {
170     bool ret = (dev->trans_type == ESP_HID_TRANS_MAX);
171     return ret;
172 }
173 
free_local_param(void)174 static void free_local_param(void)
175 {
176     if (hidh_local_param.event_loop_handle) {
177         esp_event_loop_delete(hidh_local_param.event_loop_handle);
178     }
179 
180     if (hidh_local_param.connection_queue) {
181         fixed_queue_free(hidh_local_param.connection_queue, free);
182     }
183 }
184 
open_failed_cb(esp_hidh_dev_t * dev,esp_hidh_status_t status,esp_hidh_event_data_t * p,size_t event_data_size)185 static void open_failed_cb(esp_hidh_dev_t *dev, esp_hidh_status_t status, esp_hidh_event_data_t *p,
186                            size_t event_data_size)
187 {
188     p->open.status = bt_hidh_get_status(status);
189     p->open.dev = dev;
190     if (dev != NULL) {
191         esp_hidh_dev_lock(dev);
192         if (dev->connected) {
193             esp_bt_hid_host_disconnect(dev->bda);
194         } else {
195             dev->in_use = false;
196         }
197         esp_hidh_dev_unlock(dev);
198     }
199     esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_OPEN_EVENT, p, event_data_size,
200                       portMAX_DELAY);
201 }
202 
esp_hh_cb(esp_hidh_cb_event_t event,esp_hidh_cb_param_t * param)203 static void esp_hh_cb(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param)
204 {
205     conn_item_t *conn_item = NULL;
206     esp_hidh_dev_t *dev = NULL;
207     esp_hidh_dev_report_t *report = NULL;
208     bool has_report_id = false;
209     size_t data_len = 0;
210     uint8_t *p_data = NULL;
211     esp_hidh_event_data_t p = {0};
212     esp_hidh_event_data_t *p_param = NULL;
213     size_t event_data_size = sizeof(esp_hidh_event_data_t);
214 
215     switch (event) {
216     case ESP_HIDH_INIT_EVT: {
217         p.start.status = bt_hidh_get_status(param->init.status);
218         esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_START_EVENT, &p,
219                           event_data_size, portMAX_DELAY);
220         if (param->init.status != ESP_HIDH_OK) {
221             ESP_LOGE(TAG, "ENABLE ERROR: %s", s_esp_hh_status_names[param->init.status]);
222             free_local_param();
223         }
224         break;
225     }
226     case ESP_HIDH_DEINIT_EVT: {
227         p.stop.status = bt_hidh_get_status(param->deinit.status);
228         esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_STOP_EVENT, &p,
229                           event_data_size, portMAX_DELAY);
230         if (param->deinit.status != ESP_HIDH_OK) {
231             ESP_LOGE(TAG, "DISABLE ERROR: %s", s_esp_hh_status_names[param->deinit.status]);
232         } else {
233             free_local_param();
234         }
235         break;
236     }
237     case ESP_HIDH_OPEN_EVT: {
238         if (param->open.conn_status == ESP_HIDH_CONN_STATE_CONNECTING) {
239             // ignore this conn_status
240             break;
241         }
242 
243         do {
244             dev = esp_hidh_dev_get_by_bda(param->open.bd_addr);
245             if (dev == NULL) {
246                 if (param->open.is_orig) {
247                     ESP_LOGE(TAG, "OPEN ERROR: Device Not Found");
248                     param->open.status = ESP_HIDH_NO_CONNECTION;
249                     break;
250                 } else {
251                     ESP_LOGD(TAG, "incoming device connect");
252                     if (param->open.status == ESP_HIDH_OK) {
253                         if ((dev = hidh_dev_ctor(param->open.bd_addr)) == NULL) {
254                             ESP_LOGE(TAG, "%s create device failed!", __func__);
255                             param->open.status = ESP_HIDH_ERR_NO_RES;
256                             break;
257                         }
258                         esp_hidh_dev_lock(dev);
259                         dev->opened = false; // not opened by ourself
260                         dev->is_orig = false;
261                         esp_hidh_dev_unlock(dev);
262                     }
263                 }
264             }
265 
266             if (param->open.status != ESP_HIDH_OK) {
267                 break;
268             }
269             esp_hidh_dev_lock(dev);
270             dev->connected = true;
271             dev->bt.handle = param->open.handle;
272             esp_hidh_dev_unlock(dev);
273             conn_item = malloc(sizeof(conn_item_t));
274             if (conn_item == NULL) {
275                 ESP_LOGE(TAG, "conn_item malloc failed!");
276                 param->open.status = ESP_HIDH_ERR_NO_RES;
277                 break;
278             }
279             conn_item->dev = dev;
280             bool ret = fixed_queue_enqueue(hidh_local_param.connection_queue, conn_item, FIXED_QUEUE_MAX_TIMEOUT);
281             assert(ret == true);
282         } while (0);
283 
284         if (param->open.status != ESP_HIDH_OK) {
285             ESP_LOGE(TAG, "OPEN ERROR: %s", s_esp_hh_status_names[param->open.status]);
286             open_failed_cb(dev, param->open.status, &p, event_data_size);
287         }
288 
289         if (dev != NULL) {
290             esp_hidh_dev_lock(dev);
291             dev->status = param->open.status;
292             esp_hidh_dev_unlock(dev);
293         }
294         break;
295     }
296     case ESP_HIDH_GET_DSCP_EVT: {
297         do {
298             ESP_LOGV(TAG, "DESCRIPTOR: PID: 0x%04x, VID: 0x%04x, VERSION: 0x%04x, REPORT_LEN: %u",
299                      param->dscp.product_id, param->dscp.vendor_id, param->dscp.version, param->dscp.dl_len);
300             if ((conn_item = (conn_item_t *)fixed_queue_dequeue(hidh_local_param.connection_queue,
301                                                                 FIXED_QUEUE_MAX_TIMEOUT)) == NULL) {
302                 ESP_LOGE(TAG, "No pending connect device!");
303                 param->dscp.status = ESP_HIDH_NO_CONNECTION;
304                 break;
305             }
306             dev = conn_item->dev;
307             utl_freebuf((void **)&conn_item);
308             // in case the dev has been freed
309             if (!esp_hidh_dev_exists(dev)) {
310                 ESP_LOGE(TAG, "Device Not Found");
311                 dev = NULL;
312                 param->dscp.status = ESP_HIDH_NO_CONNECTION;
313                 break;
314             }
315             // check if connected
316             esp_hidh_dev_lock(dev);
317             if (!dev->connected) {
318                 esp_hidh_dev_unlock(dev);
319                 ESP_LOGE(TAG, "Connection has been released!");
320                 param->dscp.status = ESP_HIDH_NO_CONNECTION;
321                 break;
322             }
323             // check if get descriptor failed
324             if (param->dscp.status != ESP_HIDH_OK) {
325                 esp_hidh_dev_unlock(dev);
326                 ESP_LOGE(TAG, "GET_DSCP ERROR: %s", s_esp_hh_status_names[param->dscp.status]);
327                 break;
328             }
329             dev->added = param->dscp.added;
330             dev->config.product_id = param->dscp.product_id;
331             dev->config.vendor_id = param->dscp.vendor_id;
332             dev->config.version = param->dscp.version;
333 
334             dev->config.report_maps_len = 1;
335             dev->config.report_maps =
336                 (esp_hid_raw_report_map_t *)malloc(dev->config.report_maps_len * sizeof(esp_hid_raw_report_map_t));
337             if (dev->config.report_maps == NULL) {
338                 esp_hidh_dev_unlock(dev);
339                 ESP_LOGE(TAG, "malloc report maps failed");
340                 param->dscp.status = ESP_HIDH_ERR_NO_RES;
341                 break;
342             }
343 
344             dev->config.report_maps[0].data = (uint8_t *)malloc(param->dscp.dl_len);
345             if (dev->config.report_maps[0].data == NULL) {
346                 ESP_LOGE(TAG, "Malloc Report Map Failed");
347                 param->dscp.status = ESP_HIDH_ERR_NO_RES;
348             } else {
349                 dev->config.report_maps[0].len = param->dscp.dl_len;
350                 memcpy((uint8_t *)dev->config.report_maps[0].data, param->dscp.dsc_list,
351                        dev->config.report_maps[0].len);
352                 // generate reports
353 
354                 if (dev->config.report_maps[0].len && dev->config.report_maps[0].data) {
355                     esp_hid_report_map_t *map;
356                     esp_hidh_dev_report_t *report;
357                     esp_hid_report_item_t *r;
358                     map = esp_hid_parse_report_map(dev->config.report_maps[0].data, dev->config.report_maps[0].len);
359                     if (map) {
360                         if (dev->usage == 0) {
361                             dev->usage = map->usage;
362                         }
363                         dev->reports = NULL;
364                         for (uint8_t i = 0; i < map->reports_len; i++) {
365                             r = &map->reports[i];
366                             report = (esp_hidh_dev_report_t *)malloc(sizeof(esp_hidh_dev_report_t));
367                             if (report == NULL) {
368                                 ESP_LOGE(TAG, "Malloc Report Failed");
369                                 param->dscp.status = ESP_HIDH_ERR_NO_RES;
370                                 break;
371                             }
372                             report->map_index = 0;
373                             report->protocol_mode = r->protocol_mode;
374                             report->report_type = r->report_type;
375                             report->report_id = r->report_id;
376                             report->value_len = r->value_len;
377                             report->usage = r->usage;
378                             report->next = dev->reports;
379                             dev->reports = report;
380                         }
381                         dev->reports_len = map->reports_len;
382                         free(map->reports);
383                         free(map);
384                         map = NULL;
385                     } else {
386                         ESP_LOGE(TAG, "Parse Report Map Failed");
387                         param->dscp.status = ESP_HIDH_ERR;
388                     }
389                 }
390             }
391             esp_hidh_dev_unlock(dev);
392         } while (0);
393 
394         if (param->dscp.status != ESP_HIDH_OK) {
395             open_failed_cb(dev, param->dscp.status, &p, event_data_size);
396         }
397 
398         if (dev != NULL) {
399             esp_hidh_dev_lock(dev);
400             dev->status = param->dscp.status;
401             // if has been added by lower layer, tell up layer
402             if (dev->status == ESP_HIDH_OK && dev->connected && dev->added) {
403                 p.open.status = bt_hidh_get_status(ESP_HIDH_OK);
404                 p.open.dev = dev;
405                 esp_hidh_dev_unlock(dev);
406                 esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_OPEN_EVENT, &p,
407                                   event_data_size, portMAX_DELAY);
408             } else {
409                 esp_hidh_dev_unlock(dev);
410             }
411         }
412         break;
413     }
414     case ESP_HIDH_ADD_DEV_EVT: {
415         ESP_LOGV(TAG, "ADD_DEV: BDA: " ESP_BD_ADDR_STR ", handle: %d, status: %s",
416                  ESP_BD_ADDR_HEX(param->add_dev.bd_addr), param->add_dev.handle,
417                  s_esp_hh_status_names[param->add_dev.status]);
418         do {
419             dev = esp_hidh_dev_get_by_handle(param->add_dev.handle);
420             if (dev == NULL) {
421                 ESP_LOGE(TAG, "Device Not Found");
422                 param->add_dev.status = ESP_HIDH_NO_CONNECTION;
423                 break;
424             }
425             esp_hidh_dev_lock(dev);
426             dev->added = param->add_dev.status == ESP_HIDH_OK ? true : false;
427             esp_hidh_dev_unlock(dev);
428         } while(0);
429 
430         if (param->add_dev.status != ESP_HIDH_OK) {
431             ESP_LOGE(TAG, "ADD_DEV ERROR: %s", s_esp_hh_status_names[param->add_dev.status]);
432             open_failed_cb(dev, param->add_dev.status, &p, event_data_size);
433         }
434         if (dev != NULL) {
435             esp_hidh_dev_lock(dev);
436             dev->status = param->add_dev.status;
437             if (dev->status == ESP_HIDH_OK && dev->connected && dev->added) {
438                 p.open.status = bt_hidh_get_status(ESP_HIDH_OK);
439                 p.open.dev = dev;
440                 esp_hidh_dev_unlock(dev);
441                 esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_OPEN_EVENT, &p,
442                                   event_data_size, portMAX_DELAY);
443             } else {
444                 esp_hidh_dev_unlock(dev);
445             }
446         }
447         break;
448     }
449     case ESP_HIDH_CLOSE_EVT: {
450         if (param->close.conn_status == ESP_HIDH_CONN_STATE_DISCONNECTING) {
451             // ignore this conn_status
452             break;
453         }
454         ESP_LOGV(TAG, "CLOSE: handle: %d, status: %s", param->close.handle, s_esp_hh_status_names[param->close.status]);
455         do {
456             dev = esp_hidh_dev_get_by_handle(param->close.handle);
457             if (dev == NULL) {
458                 ESP_LOGE(TAG, "Device Not Found");
459                 param->close.status = ESP_HIDH_NO_CONNECTION;
460                 break;
461             }
462             esp_hidh_dev_lock(dev);
463             dev->status = param->close.status;
464             if (dev->connected) {
465                 dev->connected = false;
466             }
467             // free the device in the wrapper event handler
468             dev->in_use = false;
469             esp_hidh_dev_unlock(dev);
470         } while(0);
471 
472         if (param->close.status != ESP_HIDH_OK) {
473             ESP_LOGE(TAG, "CLOSE ERROR: %s", s_esp_hh_status_names[param->close.status]);
474         }
475         p.close.dev = dev;
476         p.close.status = bt_hidh_get_status(param->close.status);
477         esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_CLOSE_EVENT, &p,
478                           event_data_size, portMAX_DELAY);
479 
480         break;
481     }
482     case ESP_HIDH_SET_RPT_EVT: {
483         if (param->set_rpt.status != ESP_HIDH_OK) {
484             ESP_LOGE(TAG, "SET_RPT ERROR: handle: %d, status: %s", param->set_rpt.handle,
485                      s_esp_hh_status_names[param->set_rpt.status]);
486         }
487         dev = esp_hidh_dev_get_by_handle(param->set_rpt.handle);
488         if (dev == NULL) {
489             ESP_LOGE(TAG, "SET_RPT ERROR: Device Not Found");
490             break;
491         }
492         esp_hidh_dev_lock(dev);
493         dev->status = param->set_rpt.status;
494         p.feature.dev = dev;
495         esp_hidh_dev_unlock(dev);
496         p.feature.status = bt_hidh_get_status(param->set_rpt.status);
497         p.feature.trans_type = ESP_HID_TRANS_SET_REPORT;
498         esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, &p,
499                           event_data_size, portMAX_DELAY);
500         reset_trans(dev);
501         break;
502     }
503     case ESP_HIDH_GET_RPT_EVT: {
504         if (param->get_rpt.status != ESP_HIDH_OK) {
505             ESP_LOGE(TAG, "GET_RPT ERROR: handle: %d, status: %s", param->get_rpt.handle,
506                      s_esp_hh_status_names[param->get_rpt.status]);
507         } else if (param->get_rpt.len > 0 && param->get_rpt.data) {
508             event_data_size += param->get_rpt.len;
509         }
510         dev = esp_hidh_dev_get_by_handle(param->get_rpt.handle);
511         if (dev == NULL) {
512             ESP_LOGE(TAG, "GET_RPT ERROR: Device Not Found");
513             break;
514         }
515         esp_hidh_dev_lock(dev);
516         dev->status = param->get_rpt.status;
517         if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) != NULL) {
518             memset(p_param, 0, event_data_size);
519             p_param->feature.dev = dev;
520             p_param->feature.status = bt_hidh_get_status(param->get_rpt.status);
521             p_param->feature.trans_type = ESP_HID_TRANS_GET_REPORT;
522             if (param->get_rpt.status == ESP_HIDH_OK && param->get_rpt.len > 0 && param->get_rpt.data) {
523                 if (dev->report_id) {
524                     data_len = param->get_rpt.len - 1;
525                     p_data = (uint8_t *)param->get_rpt.data + 1;
526                 } else {
527                     data_len = param->get_rpt.len;
528                     p_data = (uint8_t *)param->get_rpt.data;
529                 }
530                 memcpy(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t), p_data, data_len);
531                 p_param->feature.length = data_len;
532                 p_param->feature.data = p_data;
533                 p_param->feature.report_id = dev->report_id;
534                 esp_hidh_dev_unlock(dev);
535             }
536             esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param,
537                               event_data_size, portMAX_DELAY);
538         } else {
539             esp_hidh_dev_unlock(dev);
540             ESP_LOGE(TAG, "GET_RPT ERROR: malloc event data failed!");
541         }
542         reset_trans(dev);
543         break;
544     }
545     case ESP_HIDH_GET_IDLE_EVT:{
546         if (param->get_idle.status != ESP_HIDH_OK) {
547             ESP_LOGE(TAG, "GET_IDLE ERROR: handle: %d, status: %s", param->get_idle.handle,
548                      s_esp_hh_status_names[param->get_idle.status]);
549         } else {
550             event_data_size += 1;
551         }
552         dev = esp_hidh_dev_get_by_handle(param->get_idle.handle);
553         if (dev == NULL) {
554             ESP_LOGE(TAG, "GET_IDLE ERROR: Device Not Found");
555             break;
556         }
557         esp_hidh_dev_lock(dev);
558         dev->status = param->get_idle.status;
559         if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) != NULL) {
560             memset(p_param, 0, event_data_size);
561             p_param->feature.dev = dev;
562             p_param->feature.status = bt_hidh_get_status(param->get_idle.status);
563             p_param->feature.trans_type = ESP_HID_TRANS_GET_IDLE;
564             if (param->get_idle.status == ESP_HIDH_OK) {
565                 *(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t)) = param->get_idle.idle_rate;
566                 p_param->feature.length = 1;
567                 p_param->feature.data = ((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t);
568             }
569             esp_hidh_dev_unlock(dev);
570             esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param,
571                               event_data_size, portMAX_DELAY);
572         } else {
573             esp_hidh_dev_unlock(dev);
574             ESP_LOGE(TAG, "GET_IDLE ERROR: malloc event data failed!");
575         }
576         reset_trans(dev);
577         break;
578     }
579     case ESP_HIDH_SET_IDLE_EVT: {
580         if (param->set_idle.status != ESP_HIDH_OK) {
581             ESP_LOGE(TAG, "SET_IDLE ERROR: handle: %d, status: %s", param->set_idle.handle,
582                      s_esp_hh_status_names[param->set_idle.status]);
583         }
584         dev = esp_hidh_dev_get_by_handle(param->set_idle.handle);
585         if (dev == NULL) {
586             ESP_LOGE(TAG, "SET_IDLE ERROR: Device Not Found");
587             break;
588         }
589         esp_hidh_dev_lock(dev);
590         dev->status = param->set_idle.status;
591         p.feature.dev = dev;
592         esp_hidh_dev_unlock(dev);
593         p.feature.status = bt_hidh_get_status(param->set_idle.status);
594         p.feature.trans_type = ESP_HID_TRANS_SET_IDLE;
595         esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, &p,
596                           event_data_size, portMAX_DELAY);
597         reset_trans(dev);
598         break;
599     }
600     case ESP_HIDH_GET_PROTO_EVT: {
601         if (param->get_proto.status != ESP_HIDH_OK) {
602             ESP_LOGE(TAG, "GET_PROTO ERROR: handle: %d, status: %s", param->get_proto.handle,
603                      s_esp_hh_status_names[param->get_proto.status]);
604         } else {
605             event_data_size += 1;
606         }
607         dev = esp_hidh_dev_get_by_handle(param->get_proto.handle);
608         if (dev == NULL) {
609             ESP_LOGE(TAG, "GET_PROTO ERROR: Device Not Found");
610             break;
611         }
612         esp_hidh_dev_lock(dev);
613         dev->status = param->get_proto.status;
614         if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) != NULL) {
615             memset(p_param, 0, event_data_size);
616             p_param->feature.dev = dev;
617             p_param->feature.status = bt_hidh_get_status(param->get_proto.status);
618             p_param->feature.trans_type = ESP_HID_TRANS_GET_PROTOCOL;
619             if (param->get_proto.status == ESP_HIDH_OK) {
620                 dev->protocol_mode = param->get_proto.proto_mode; // update the device protocol mode
621                 *(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t)) = param->get_proto.proto_mode;
622                 p_param->feature.length = 1;
623                 p_param->feature.data = ((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t);
624             }
625             esp_hidh_dev_unlock(dev);
626             esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param,
627                               event_data_size, portMAX_DELAY);
628         } else {
629             esp_hidh_dev_unlock(dev);
630             ESP_LOGE(TAG, "GET_PROTO ERROR: malloc event data failed!");
631         }
632         reset_trans(dev);
633         break;
634     }
635     case ESP_HIDH_SET_PROTO_EVT: {
636         if (param->set_proto.status != ESP_HIDH_OK) {
637             ESP_LOGE(TAG, "SET_PROTO ERROR: handle: %d, status: %s", param->set_proto.handle,
638                      s_esp_hh_status_names[param->set_proto.status]);
639         }
640         dev = esp_hidh_dev_get_by_handle(param->set_proto.handle);
641         if (dev == NULL) {
642             ESP_LOGE(TAG, "Device Not Found");
643             break;
644         }
645         esp_hidh_dev_lock(dev);
646         dev->status = param->set_proto.status;
647         p.feature.dev = dev;
648         esp_hidh_dev_unlock(dev);
649         p.feature.status = bt_hidh_get_status(param->set_proto.status);
650         p.feature.trans_type = ESP_HID_TRANS_SET_PROTOCOL;
651         esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, &p,
652                           event_data_size, portMAX_DELAY);
653         reset_trans(dev);
654         break;
655     }
656     case ESP_HIDH_DATA_IND_EVT: {
657         esp_hid_usage_t _usage;
658         if (param->data_ind.status != ESP_HIDH_OK) {
659             ESP_LOGE(TAG, "DATA_IND ERROR: handle: %d, status: %s", param->data_ind.handle,
660                      s_esp_hh_status_names[param->data_ind.status]);
661         }
662         dev = esp_hidh_dev_get_by_handle(param->data_ind.handle);
663         if (dev == NULL) {
664             ESP_LOGE(TAG, "Device Not Found: handle %u", param->data_ind.handle);
665             break;
666         }
667 
668         if (param->data_ind.len > 0 && param->data_ind.data != NULL) {
669             esp_hidh_dev_lock(dev);
670             event_data_size += param->data_ind.len;
671             if (param->data_ind.proto_mode == ESP_HID_PROTOCOL_MODE_BOOT) {
672                 /**
673                  * first data shall have report_id, according to HID_SPEC_V10
674                  * | Device   | Report ID | Report Size |
675                  * --------------------------------------
676                  * | Keyboard | 1         | 9 Bytes     |
677                  * | Mouse    | 2         | 4 Bytes     |
678                  * | Reserved | 0, 3-255  | N/A         |
679                  */
680                 if (param->data_ind.len == 9 && *(param->data_ind.data) == 1) {
681                     has_report_id = true;
682                     _usage = ESP_HID_USAGE_KEYBOARD;
683                 } else if (param->data_ind.len == 4 && *(param->data_ind.data) == 2) {
684                     has_report_id = true;
685                     _usage = ESP_HID_USAGE_MOUSE;
686                 } else {
687                     esp_hidh_dev_unlock(dev);
688                     ESP_LOGE(TAG, "Invalid Boot Report format, rpt_len:%d, rpt_id:%d!", param->data_ind.len,
689                              *(param->data_ind.data));
690                     break;
691                 }
692             } else {
693                 report = esp_hidh_dev_get_input_report_by_proto_and_data(
694                     dev, ESP_HID_PROTOCOL_MODE_REPORT, param->data_ind.len, param->data_ind.data, &has_report_id);
695                 if (report == NULL) {
696                     esp_hidh_dev_unlock(dev);
697                     ESP_LOGE(TAG, "Not find report handle: %d mode: %s", param->data_ind.handle,
698                              param->data_ind.proto_mode == ESP_HID_PROTOCOL_MODE_REPORT ? "REPORT" : "BOOT");
699                     break;
700                 }
701                 _usage = report->usage;
702             }
703 
704             if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) == NULL) {
705                 esp_hidh_dev_unlock(dev);
706                 ESP_LOGE(TAG, "DATA_IND ERROR: malloc event data failed!");
707                 break;
708             }
709             memset(p_param, 0, event_data_size);
710             p_param->input.dev = dev;
711             p_param->input.usage = _usage;
712             if (has_report_id) {
713                 data_len = param->data_ind.len - 1;
714                 p_data = (uint8_t *)param->data_ind.data + 1;
715                 p_param->input.report_id = *(uint8_t *)param->data_ind.data;
716             } else {
717                 data_len = param->data_ind.len;
718                 p_data = (uint8_t *)param->data_ind.data;
719                 p_param->input.report_id = report->report_id;
720             }
721             memcpy(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t), p_data, data_len);
722             p_param->input.length = data_len;
723             p_param->input.data = p_data;
724             esp_hidh_dev_unlock(dev);
725             esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, p_param,
726                               event_data_size, portMAX_DELAY);
727         }
728         break;
729     }
730     case ESP_HIDH_DATA_EVT:
731         break;
732     default:
733         ESP_LOGV(TAG, "BTA_HH EVENT: %s", s_esp_hh_evt_names[event]);
734         break;
735     }
736 
737     if (p_param) {
738         free(p_param);
739         p_param = NULL;
740     }
741 }
742 
743 /*
744  * Public Functions
745  * */
746 
esp_bt_hidh_dev_close(esp_hidh_dev_t * dev)747 static esp_err_t esp_bt_hidh_dev_close(esp_hidh_dev_t *dev)
748 {
749     esp_err_t ret = ESP_OK;
750     do {
751         if (dev == NULL) {
752             ret = ESP_ERR_INVALID_ARG;
753             break;
754         }
755         if (!dev->connected) {
756             ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle);
757             ret = ESP_ERR_INVALID_STATE;
758             break;
759         }
760         ret = esp_bt_hid_host_disconnect(dev->bda);
761     } while (0);
762     return ret;
763 }
764 
esp_bt_hidh_dev_report_write(esp_hidh_dev_t * dev,size_t map_index,size_t report_id,int report_type,uint8_t * data,size_t len)765 static esp_err_t esp_bt_hidh_dev_report_write(esp_hidh_dev_t *dev, size_t map_index, size_t report_id,
766                                               int report_type, uint8_t *data, size_t len)
767 {
768     esp_err_t ret = ESP_OK;
769     uint8_t *p_data = NULL;
770     do {
771         esp_hidh_dev_report_t *report =
772             esp_hidh_dev_get_report_by_id_type_proto(dev, map_index, report_id, report_type, dev->protocol_mode);
773         if (!report) {
774             ESP_LOGE(TAG, "mode:%s report:%s id:%d not found", get_protocol_mode(dev->protocol_mode),
775                      esp_hid_report_type_str(report_type), report_id);
776             ret = ESP_FAIL;
777             break;
778         }
779         if (len > report->value_len) {
780             ESP_LOGE(TAG, "%s report %d takes maximum %d bytes. you have provided %d",
781                      esp_hid_report_type_str(report_type), report_id, report->value_len, len);
782             ret = ESP_FAIL;
783             break;
784         }
785 
786         if (report_type != ESP_HID_REPORT_TYPE_OUTPUT) {
787             ESP_LOGE(TAG,
788                      "Only OUTPUT type data can be send on interrupt channel.\n" \
789                      "You have provided %s, try Set_Report!",
790                      esp_hid_report_type_str(report_type));
791             ret = ESP_FAIL;
792             break;
793         }
794 
795         if (report_id) {
796             if ((p_data = malloc(len + 1)) == NULL) {
797                 ESP_LOGE(TAG, "%s malloc failed!", __func__);
798                 ret = ESP_FAIL;
799                 break;
800             }
801             *p_data = report_id;
802             memcpy(p_data + 1, data, len);
803             data = p_data;
804             len = len + 1;
805         }
806         ret = esp_bt_hid_host_send_data(dev->bda, data, len);
807     } while (0);
808     return ret;
809 }
810 
esp_bt_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 len)811 static esp_err_t esp_bt_hidh_dev_set_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id,
812                                             int report_type, uint8_t *data, size_t len)
813 {
814     esp_err_t ret = ESP_OK;
815     uint8_t *p_data = NULL;
816     esp_hidh_dev_report_t *report = NULL;
817     do {
818         if (!is_trans_done(dev)) {
819             ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type));
820             ret = ESP_FAIL;
821             break;
822         }
823         report = esp_hidh_dev_get_report_by_id_type_proto(dev, map_index, report_id, report_type, dev->protocol_mode);
824         if (!report) {
825             ESP_LOGE(TAG, "mode:%s report:%s id:%d not found", get_protocol_mode(dev->protocol_mode),
826                      esp_hid_report_type_str(report_type), report_id);
827             ret = ESP_FAIL;
828             break;
829         }
830         if (len > report->value_len) {
831             ESP_LOGE(TAG, "%s report %d takes maximum %d bytes. you have provided %d",
832                      esp_hid_report_type_str(report_type), report_id, report->value_len, len);
833             ret = ESP_FAIL;
834             break;
835         }
836 
837         if (report_id) {
838             if ((p_data = malloc(len + 1)) == NULL) {
839                 ESP_LOGE(TAG, "%s malloc failed!", __func__);
840                 ret = ESP_FAIL;
841                 break;
842             }
843             *p_data = report_id;
844             memcpy(p_data + 1, data, len);
845             data = p_data;
846             len = len + 1;
847         }
848         ret = esp_bt_hid_host_set_report(dev->bda, report_type, data, len);
849         if (ret == ESP_OK) {
850             set_trans(dev, ESP_HID_TRANS_SET_REPORT);
851         }
852     } while (0);
853     return ret;
854 }
855 
esp_bt_hidh_dev_report_read(esp_hidh_dev_t * dev,size_t map_index,size_t report_id,int report_type,size_t max_length,uint8_t * value,size_t * value_len)856 static esp_err_t esp_bt_hidh_dev_report_read(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type,
857                                              size_t max_length, uint8_t *value, size_t *value_len)
858 {
859     esp_err_t ret = ESP_OK;
860     esp_hidh_dev_report_t *report = NULL;
861     do {
862         if (!is_trans_done(dev)) {
863             ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type));
864             ret = ESP_FAIL;
865             break;
866         }
867         report = esp_hidh_dev_get_report_by_id_type_proto(dev, map_index, report_id, report_type, dev->protocol_mode);
868         if (!report) {
869             ESP_LOGE(TAG, "mode:%s report:%s id:%d not found", get_protocol_mode(dev->protocol_mode),
870                      esp_hid_report_type_str(report_type), report_id);
871             ret = ESP_FAIL;
872             break;
873         }
874         ret = esp_bt_hid_host_get_report(dev->bda, report_type, report_id, max_length);
875         if (ret == ESP_OK) {
876             dev->trans_type = ESP_HID_TRANS_GET_REPORT;
877             dev->report_id = report_id;
878             dev->report_type = report_type;
879         }
880     } while (0);
881     return ret;
882 }
883 
esp_bt_hidh_dev_get_idle(esp_hidh_dev_t * dev)884 static esp_err_t esp_bt_hidh_dev_get_idle(esp_hidh_dev_t *dev)
885 {
886     esp_err_t ret = ESP_OK;
887     do {
888         if (!is_trans_done(dev)) {
889             ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type));
890             ret = ESP_FAIL;
891             break;
892         }
893         if (!dev->connected) {
894             ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle);
895             ret = ESP_ERR_INVALID_STATE;
896             break;
897         }
898         ret = esp_bt_hid_host_get_idle(dev->bda);
899         if (ret == ESP_OK) {
900             set_trans(dev, ESP_HID_TRANS_GET_IDLE);
901         }
902     } while(0);
903 
904     return ret;
905 }
906 
esp_bt_hidh_dev_set_idle(esp_hidh_dev_t * dev,uint8_t idle_time)907 static esp_err_t esp_bt_hidh_dev_set_idle(esp_hidh_dev_t *dev, uint8_t idle_time)
908 {
909     esp_err_t ret = ESP_OK;
910     do {
911         if (!is_trans_done(dev)) {
912             ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type));
913             ret = ESP_FAIL;
914             break;
915         }
916         if (!dev->connected) {
917             ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle);
918             ret = ESP_ERR_INVALID_STATE;
919             break;
920         }
921         ret = esp_bt_hid_host_set_idle(dev->bda, idle_time);
922         if (ret == ESP_OK) {
923             set_trans(dev, ESP_HID_TRANS_SET_IDLE);
924         }
925     } while(0);
926 
927     return ret;
928 }
929 
esp_bt_hidh_dev_get_protocol(esp_hidh_dev_t * dev)930 static esp_err_t esp_bt_hidh_dev_get_protocol(esp_hidh_dev_t *dev)
931 {
932     esp_err_t ret = ESP_OK;
933     do {
934         if (!is_trans_done(dev)) {
935             ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type));
936             ret = ESP_FAIL;
937             break;
938         }
939         if (!dev->connected) {
940             ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle);
941             ret = ESP_ERR_INVALID_STATE;
942             break;
943         }
944         ret = esp_bt_hid_host_get_protocol(dev->bda);
945         if (ret == ESP_OK) {
946             set_trans(dev, ESP_HID_TRANS_GET_PROTOCOL);
947         }
948     } while(0);
949 
950     return ret;
951 }
952 
esp_bt_hidh_dev_set_protocol(esp_hidh_dev_t * dev,uint8_t protocol_mode)953 static esp_err_t esp_bt_hidh_dev_set_protocol(esp_hidh_dev_t *dev, uint8_t protocol_mode)
954 {
955     esp_err_t ret = ESP_OK;
956 
957     do {
958         if (!is_trans_done(dev)) {
959             ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type));
960             ret = ESP_FAIL;
961             break;
962         }
963         if (!dev->connected) {
964             ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle);
965             ret = ESP_ERR_INVALID_STATE;
966             break;
967         }
968         ret = esp_bt_hid_host_set_protocol(dev->bda, protocol_mode);
969         if (ret == ESP_OK) {
970             set_trans(dev, ESP_HID_TRANS_SET_PROTOCOL);
971         }
972     } while(0);
973 
974     return ret;
975 }
976 
esp_bt_hidh_dev_dump(esp_hidh_dev_t * dev,FILE * fp)977 static void esp_bt_hidh_dev_dump(esp_hidh_dev_t *dev, FILE *fp)
978 {
979     fprintf(fp, "BDA:" ESP_BD_ADDR_STR ", Status: %s, Connected: %s, Handle: %d, Usage: %s\n", ESP_BD_ADDR_HEX(dev->bda), s_esp_hh_status_names[dev->status], dev->connected ? "YES" : "NO", dev->bt.handle, esp_hid_usage_str(dev->usage));
980     fprintf(fp, "Name: %s, Manufacturer: %s, Serial Number: %s\n", dev->config.device_name ? dev->config.device_name : "", dev->config.manufacturer_name ? dev->config.manufacturer_name : "", dev->config.serial_number ? dev->config.serial_number : "");
981     fprintf(fp, "PID: 0x%04x, VID: 0x%04x, VERSION: 0x%04x\n", dev->config.product_id, dev->config.vendor_id, dev->config.version);
982     fprintf(fp, "Report Map Length: %d\n", dev->config.report_maps[0].len);
983     esp_hidh_dev_report_t *report = dev->reports;
984     while (report) {
985         fprintf(fp, "  %8s %7s %6s, ID: %3u, Length: %3u\n",
986                esp_hid_usage_str(report->usage), esp_hid_report_type_str(report->report_type), get_protocol_mode(report->protocol_mode),
987                report->report_id, report->value_len);
988         report = report->next;
989     }
990 }
991 
esp_bt_hidh_init(const esp_hidh_config_t * config)992 esp_err_t esp_bt_hidh_init(const esp_hidh_config_t *config)
993 {
994     esp_err_t ret = ESP_OK;
995     if (config == NULL) {
996         ESP_LOGE(TAG, "Config is NULL");
997         return ESP_ERR_INVALID_ARG;
998     }
999     esp_event_loop_args_t event_task_args = {
1000         .queue_size = 5,
1001         .task_name = "esp_bt_hidh_events",
1002         .task_priority = uxTaskPriorityGet(NULL),
1003         .task_stack_size = config->event_stack_size > 0 ? config->event_stack_size : 4096,
1004         .task_core_id = tskNO_AFFINITY
1005     };
1006 
1007     do {
1008         if ((hidh_local_param.connection_queue = fixed_queue_new(QUEUE_SIZE_MAX)) == NULL) {
1009             ESP_LOGE(TAG, "connection_queue create failed!");
1010             ret = ESP_FAIL;
1011             break;
1012         }
1013         ret = esp_event_loop_create(&event_task_args, &hidh_local_param.event_loop_handle);
1014         if (ret != ESP_OK) {
1015             ESP_LOGE(TAG, "esp_event_loop_create failed!");
1016             ret = ESP_FAIL;
1017             break;
1018         }
1019         ret = esp_event_handler_register_with(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID,
1020                                               esp_hidh_process_event_data_handler, NULL);
1021         ret |= esp_event_handler_register_with(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID,
1022                                                config->callback, config->callback_arg);
1023         if (ret != ESP_OK) {
1024             ESP_LOGE(TAG, "event_loop register failed!");
1025             ret = ESP_FAIL;
1026             break;
1027         }
1028         ret = esp_bt_hid_host_register_callback(esp_hh_cb);
1029         ret |= esp_bt_hid_host_init();
1030     } while (0);
1031 
1032     if (ret != ESP_OK) {
1033         free_local_param();
1034     }
1035     return ret;
1036 }
1037 
esp_bt_hidh_deinit(void)1038 esp_err_t esp_bt_hidh_deinit(void)
1039 {
1040     esp_err_t ret = esp_bt_hid_host_deinit();
1041     return ret;
1042 }
1043 
hidh_dev_ctor(esp_bd_addr_t bda)1044 static esp_hidh_dev_t *hidh_dev_ctor(esp_bd_addr_t bda)
1045 {
1046     esp_hidh_dev_t *dev = NULL;
1047     dev = esp_hidh_dev_malloc();
1048     if (dev == NULL) {
1049         return NULL;
1050     }
1051     dev->in_use = true;
1052     dev->transport = ESP_HID_TRANSPORT_BT;
1053     dev->trans_type = ESP_HID_TRANS_MAX;
1054     dev->trans_timer = NULL;
1055     dev->protocol_mode = ESP_HID_PROTOCOL_MODE_REPORT; // device default protocol mode
1056     dev->connected = false;
1057     dev->opened = true;
1058     dev->added = false;
1059     dev->is_orig = true;
1060     dev->reports = NULL;
1061     dev->reports_len = 0;
1062     dev->tmp = NULL;
1063     dev->tmp_len = 0;
1064     memcpy(dev->bda, bda, sizeof(esp_bd_addr_t));
1065     dev->bt.handle = 0xff;
1066 
1067     dev->close = esp_bt_hidh_dev_close;
1068     dev->report_write = esp_bt_hidh_dev_report_write;
1069     dev->report_read = esp_bt_hidh_dev_report_read;
1070     dev->set_report = esp_bt_hidh_dev_set_report;
1071     dev->get_idle = esp_bt_hidh_dev_get_idle;
1072     dev->set_idle = esp_bt_hidh_dev_set_idle;
1073     dev->get_protocol = esp_bt_hidh_dev_get_protocol;
1074     dev->set_protocol = esp_bt_hidh_dev_set_protocol;
1075     dev->dump = esp_bt_hidh_dev_dump;
1076 
1077     return dev;
1078 }
1079 
esp_bt_hidh_dev_open(esp_bd_addr_t bda)1080 esp_hidh_dev_t *esp_bt_hidh_dev_open(esp_bd_addr_t bda)
1081 {
1082     esp_hidh_dev_t *dev = esp_hidh_dev_get_by_bda(bda);
1083     if (dev == NULL) {
1084         if ((dev = hidh_dev_ctor(bda)) == NULL) {
1085             ESP_LOGE(TAG, "%s create device failed!", __func__);
1086             return NULL;
1087         }
1088     } else {
1089         ESP_LOGW(TAG, "device has opened, connected: %d", dev->connected);
1090     }
1091 
1092     if (!dev->connected) {
1093         esp_bt_hid_host_connect(dev->bda);
1094     }
1095     return dev;
1096 }
1097 
1098 #endif /* CONFIG_BT_HID_HOST_ENABLED */
1099