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 #include "bt_hidd.h"
15 
16 #if CONFIG_BT_HID_DEVICE_ENABLED
17 #include "esp_bt.h"
18 #include "esp_bt_defs.h"
19 #include "esp_bt_main.h"
20 #include "esp_hidd.h"
21 #include "esp_hidd_api.h"
22 #include "esp_hidd_private.h"
23 #include "esp_log.h"
24 #include "osi/mutex.h"
25 #include "string.h"
26 
27 /* Values for service_type */
28 #define NO_TRAFFIC      0
29 #define BEST_EFFORT     1
30 #define GUARANTEED      2
31 
32 static const char *TAG = "BT_HIDD";
33 
34 typedef struct {
35     esp_hid_raw_report_map_t    reports_map;
36     uint8_t                     reports_len;
37     hidd_report_item_t          *reports;
38 } hidd_dev_map_t;
39 
40 typedef struct {
41     esp_hidd_dev_t             *dev;
42     esp_event_loop_handle_t     event_loop_handle;
43     esp_hid_device_config_t     config;
44     uint16_t                    appearance;
45     bool                        registered;
46     bool                        connected;
47     esp_bd_addr_t               remote_bda;
48     uint8_t                     bat_level;  // 0 - 100 - battery percentage
49     uint8_t                     control;    // 0x00 suspend, 0x01 suspend off
50     uint8_t                     protocol_mode;   // 0x00 boot, 0x01 report
51     hidd_dev_map_t             *devices;
52     uint8_t                     devices_len;
53 } esp_bt_hidd_dev_t;
54 
55 typedef struct
56 {
57     osi_mutex_t mutex;
58     esp_bt_hidd_dev_t *dev;
59     esp_hidd_app_param_t app_param;
60     esp_hidd_qos_param_t in_qos;
61     esp_hidd_qos_param_t out_qos;
62 } hidd_param_t;
63 
64 static hidd_param_t s_hidd_param = {0};
65 #define is_init() (s_hidd_param.dev != NULL)
66 #define UNUSED(x) (void)(x)
67 
bt_hidd_get_status(esp_hidd_status_t status)68 static esp_err_t bt_hidd_get_status(esp_hidd_status_t status)
69 {
70     esp_err_t ret = ESP_OK;
71     switch (status) {
72     case ESP_HIDD_SUCCESS:
73         ret = ESP_OK;
74         break;
75     case ESP_HIDD_NO_RES:
76         ret = ESP_ERR_NO_MEM;
77         break;
78     default:
79         ret = ESP_FAIL;
80         break;
81     }
82     return ret;
83 }
84 
bt_hidd_init_config(esp_bt_hidd_dev_t * dev,const esp_hid_device_config_t * config)85 static esp_err_t bt_hidd_init_config(esp_bt_hidd_dev_t *dev, const esp_hid_device_config_t *config)
86 {
87     if (config->report_maps == NULL || config->report_maps_len == 0 || config->report_maps_len > 1) {
88         return ESP_ERR_INVALID_ARG;
89     }
90     memset((uint8_t *)(&dev->config), 0, sizeof(esp_hid_device_config_t));
91     dev->config.vendor_id = config->vendor_id;
92     dev->config.product_id = config->product_id;
93     dev->config.version = config->version;
94     if (config->device_name != NULL) {
95         dev->config.device_name = strdup(config->device_name);
96     }
97     if (config->manufacturer_name != NULL) {
98         dev->config.manufacturer_name = strdup(config->manufacturer_name);
99     }
100     if (config->serial_number != NULL) {
101         dev->config.serial_number = strdup(config->serial_number);
102     }
103     dev->appearance = ESP_HID_APPEARANCE_GENERIC;
104 
105     if (config->report_maps_len) {
106         dev->devices = (hidd_dev_map_t *)malloc(config->report_maps_len * sizeof(hidd_dev_map_t));
107         if (dev->devices == NULL) {
108             ESP_LOGE(TAG, "devices malloc(%d) failed", config->report_maps_len);
109             return ESP_ERR_NO_MEM;
110         }
111         memset(dev->devices, 0, config->report_maps_len * sizeof(hidd_dev_map_t));
112         dev->devices_len = config->report_maps_len;
113         for (uint8_t d = 0; d < dev->devices_len; d++) {
114 
115             //raw report map
116             uint8_t *map = (uint8_t *)malloc(config->report_maps[d].len);
117             if (map == NULL) {
118                 ESP_LOGE(TAG, "report map malloc(%d) failed", config->report_maps[d].len);
119                 return ESP_ERR_NO_MEM;
120             }
121             memcpy(map, config->report_maps[d].data, config->report_maps[d].len);
122 
123             dev->devices[d].reports_map.data = (const uint8_t *)map;
124             dev->devices[d].reports_map.len = config->report_maps[d].len;
125 
126             esp_hid_report_map_t *rmap = esp_hid_parse_report_map(config->report_maps[d].data, config->report_maps[d].len);
127             if (rmap == NULL) {
128                 ESP_LOGE(TAG, "hid_parse_report_map[%d](%d) failed", d, config->report_maps[d].len);
129                 return ESP_FAIL;
130             }
131             dev->appearance = rmap->appearance;
132             dev->devices[d].reports_len = rmap->reports_len;
133             dev->devices[d].reports = (hidd_report_item_t *)malloc(rmap->reports_len * sizeof(hidd_report_item_t));
134             if (dev->devices[d].reports == NULL) {
135                 ESP_LOGE(TAG, "reports malloc(%d) failed", rmap->reports_len * sizeof(hidd_report_item_t));
136                 free(rmap);
137                 return ESP_ERR_NO_MEM;
138             }
139             for (uint8_t r = 0; r < rmap->reports_len; r++) {
140                 dev->devices[d].reports[r].map_index = d;
141                 dev->devices[d].reports[r].report_id = rmap->reports[r].report_id;
142                 dev->devices[d].reports[r].protocol_mode = rmap->reports[r].protocol_mode;
143                 dev->devices[d].reports[r].report_type = rmap->reports[r].report_type;
144                 dev->devices[d].reports[r].usage = rmap->reports[r].usage;
145                 dev->devices[d].reports[r].value_len = rmap->reports[r].value_len;
146             }
147             free(rmap->reports);
148             free(rmap);
149         }
150     }
151 
152     return ESP_OK;
153 }
154 
get_report_by_idx_id_type(esp_bt_hidd_dev_t * dev,size_t index,uint8_t id,uint8_t type)155 static hidd_report_item_t *get_report_by_idx_id_type(esp_bt_hidd_dev_t *dev, size_t index, uint8_t id, uint8_t type)
156 {
157     hidd_report_item_t *rpt = NULL;
158     if (index >= dev->devices_len) {
159         ESP_LOGE(TAG, "index out of range[0-%d]", dev->devices_len - 1);
160         return NULL;
161     }
162     for (uint8_t i = 0; i < dev->devices[index].reports_len; i++) {
163         rpt = &dev->devices[index].reports[i];
164         if (rpt->report_id == id && rpt->report_type == type && rpt->protocol_mode == dev->protocol_mode) {
165             return rpt;
166         }
167     }
168     return NULL;
169 }
170 
get_report_by_id_and_type(esp_bt_hidd_dev_t * dev,uint8_t id,uint8_t type,uint8_t * index)171 static hidd_report_item_t *get_report_by_id_and_type(esp_bt_hidd_dev_t *dev, uint8_t id, uint8_t type, uint8_t *index)
172 {
173     hidd_report_item_t *rpt = NULL;
174     for (uint8_t idx = 0; idx < dev->devices_len; idx++) {
175         for (uint8_t i = 0; i < dev->devices[idx].reports_len; i++) {
176             rpt = &dev->devices[idx].reports[i];
177             if (rpt->report_id == id && rpt->report_type == type && rpt->protocol_mode == dev->protocol_mode) {
178                 if (index) {
179                     *index = idx;
180                 }
181                 return rpt;
182             }
183         }
184     }
185     return NULL;
186 }
187 
bt_hid_free_config(esp_bt_hidd_dev_t * dev)188 static esp_err_t bt_hid_free_config(esp_bt_hidd_dev_t *dev)
189 {
190     for (uint8_t d = 0; d < dev->devices_len; d++) {
191         free((void *)dev->devices[d].reports);
192         free((void *)dev->devices[d].reports_map.data);
193     }
194 
195     free((void *)dev->devices);
196     free((void *)dev->config.device_name);
197     free((void *)dev->config.manufacturer_name);
198     free((void *)dev->config.serial_number);
199     if (dev->event_loop_handle != NULL) {
200         esp_event_loop_delete(dev->event_loop_handle);
201         dev->event_loop_handle = NULL;
202     }
203     return ESP_OK;
204 }
205 
bt_hidd_dev_free(void)206 static void bt_hidd_dev_free(void)
207 {
208     if (s_hidd_param.dev) {
209         osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
210         bt_hid_free_config(s_hidd_param.dev);
211         free(s_hidd_param.dev);
212         s_hidd_param.dev = NULL;
213         osi_mutex_unlock(&s_hidd_param.mutex);
214         osi_mutex_free(&s_hidd_param.mutex);
215     }
216 }
217 
build_default_in_qos(esp_hidd_qos_param_t * in_qos,uint32_t value_len)218 static void build_default_in_qos(esp_hidd_qos_param_t *in_qos, uint32_t value_len)
219 {
220 
221     if (value_len > 0) {
222         in_qos->service_type = GUARANTEED;
223         in_qos->token_rate = value_len * 100;
224         in_qos->token_bucket_size = value_len;
225         in_qos->peak_bandwidth = value_len * 100;
226         in_qos->access_latency = 10;
227         in_qos->delay_variation = 10;
228     } else {
229         memset(in_qos, 0, sizeof(esp_hidd_qos_param_t));
230     }
231 }
232 
build_default_out_qos(esp_hidd_qos_param_t * out_qos,uint32_t value_len)233 static void build_default_out_qos(esp_hidd_qos_param_t *out_qos, uint32_t value_len)
234 {
235     if (value_len > 0) {
236         out_qos->service_type = GUARANTEED;
237         out_qos->token_rate = value_len * 100;
238         out_qos->token_bucket_size = value_len;
239         out_qos->peak_bandwidth = value_len * 100;
240         out_qos->access_latency = 10;
241         out_qos->delay_variation = 10;
242     } else {
243         memset(out_qos, 0, sizeof(esp_hidd_qos_param_t));
244     }
245 }
246 
get_subclass_by_appearance(uint16_t appearance)247 static uint8_t get_subclass_by_appearance(uint16_t appearance)
248 {
249     uint8_t ret = ESP_HID_CLASS_UNKNOWN;
250     switch (appearance) {
251     case ESP_HID_APPEARANCE_KEYBOARD:
252         ret = ESP_HID_CLASS_KBD;
253         break;
254     case ESP_HID_APPEARANCE_MOUSE:
255         ret = ESP_HID_CLASS_MIC;
256         break;
257     case ESP_HID_APPEARANCE_JOYSTICK:
258         ret = ESP_HID_CLASS_JOS;
259         break;
260     case ESP_HID_APPEARANCE_GAMEPAD:
261         ret = ESP_HID_CLASS_GPD;
262         break;
263     default:
264         ret = ESP_HID_CLASS_UNKNOWN;
265         break;
266     }
267     return ret;
268 }
269 
get_value_len_by_type_protocol(esp_bt_hidd_dev_t * dev,uint8_t report_type,uint8_t protocol_mode)270 static uint32_t get_value_len_by_type_protocol(esp_bt_hidd_dev_t *dev, uint8_t report_type, uint8_t protocol_mode)
271 {
272     uint32_t value_len = 0;
273     hidd_report_item_t *rpt = NULL;
274     for (uint8_t d = 0; d < dev->devices_len; d++) {
275         for (uint8_t i = 0; i < dev->devices[d].reports_len; i++) {
276             rpt = &dev->devices[d].reports[i];
277             if (rpt->report_type == report_type && rpt->protocol_mode == dev->protocol_mode) {
278                 value_len += rpt->value_len;
279             }
280         }
281     }
282     return value_len;
283 }
284 
bt_hidd_init_app(void)285 static void bt_hidd_init_app(void)
286 {
287     esp_hid_device_config_t *p_config = &s_hidd_param.dev->config;
288     s_hidd_param.app_param.name = p_config->device_name;
289     s_hidd_param.app_param.description = p_config->device_name;
290     s_hidd_param.app_param.provider = p_config->manufacturer_name;
291     s_hidd_param.app_param.subclass = get_subclass_by_appearance(s_hidd_param.dev->appearance);
292     s_hidd_param.app_param.desc_list = (uint8_t *)s_hidd_param.dev->devices[0].reports_map.data;
293     s_hidd_param.app_param.desc_list_len = s_hidd_param.dev->devices[0].reports_map.len;
294 }
295 
bt_hidd_init_qos(void)296 static void bt_hidd_init_qos(void)
297 {
298     uint32_t value_len = 0;
299     value_len =
300         get_value_len_by_type_protocol(s_hidd_param.dev, ESP_HID_REPORT_TYPE_INPUT, s_hidd_param.dev->protocol_mode);
301     build_default_in_qos(&s_hidd_param.in_qos, value_len);
302 
303     value_len =
304         get_value_len_by_type_protocol(s_hidd_param.dev, ESP_HID_REPORT_TYPE_INPUT, s_hidd_param.dev->protocol_mode);
305     build_default_out_qos(&s_hidd_param.out_qos, value_len);
306 }
307 
esp_bt_hidd_dev_connected(void * devp)308 static bool esp_bt_hidd_dev_connected(void *devp)
309 {
310     esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
311     bool ret = true;
312     osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
313     do {
314         if (!is_init()) {
315             ESP_LOGE(TAG, "HID device profile is uninit");
316             ret = false;
317             break;
318         }
319 
320         if (s_hidd_param.dev != dev) {
321             ESP_LOGE(TAG, "Wrong HID device provided");
322             ret = false;
323             break;
324         }
325     } while(0);
326     if (ret) {
327         ret = dev->connected;
328     }
329     osi_mutex_unlock(&s_hidd_param.mutex);
330     return ret;
331 }
332 
esp_bt_hidd_dev_deinit(void * devp)333 static esp_err_t esp_bt_hidd_dev_deinit(void *devp)
334 {
335     esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
336     esp_err_t ret = ESP_OK;
337     osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
338     do {
339         if (!is_init()) {
340             osi_mutex_unlock(&s_hidd_param.mutex);
341             ESP_LOGE(TAG, "HID device profile already uninitialized");
342             return ESP_OK;
343         }
344 
345         if (s_hidd_param.dev != dev) {
346             ESP_LOGE(TAG, "Wrong HID device provided");
347             ret = ESP_FAIL;
348         }
349     } while(0);
350     osi_mutex_unlock(&s_hidd_param.mutex);
351 
352     if (ret == ESP_OK) {
353         ret = esp_bt_hid_device_deinit();
354     }
355     return ret;
356 }
357 
esp_bt_hidd_dev_disconnect(void * devp)358 static esp_err_t esp_bt_hidd_dev_disconnect(void *devp)
359 {
360     esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
361     esp_err_t ret = ESP_OK;
362     osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
363     do {
364         if (!is_init()) {
365             ESP_LOGE(TAG, "HID device is uninit");
366             ret = ESP_FAIL;
367             break;
368         }
369 
370         if (s_hidd_param.dev != dev) {
371             ESP_LOGE(TAG, "Wrong HID device provided");
372             ret = ESP_FAIL;
373             break;
374         }
375 
376         if (!dev->connected) {
377             osi_mutex_unlock(&s_hidd_param.mutex);
378             ESP_LOGW(TAG, "already disconnected");
379             return ESP_OK;
380         }
381     } while(0);
382     osi_mutex_unlock(&s_hidd_param.mutex);
383 
384     if (ret == ESP_OK) {
385         ret = esp_bt_hid_device_disconnect();
386     }
387     return ret;
388 }
389 
esp_bt_hidd_dev_battery_set(void * devp,uint8_t level)390 static esp_err_t esp_bt_hidd_dev_battery_set(void *devp, uint8_t level)
391 {
392     UNUSED(devp);
393     UNUSED(level);
394     ESP_LOGW(TAG, "Not implement yet!");
395     return ESP_OK;
396 }
397 
esp_bt_hidd_dev_input_set(void * devp,size_t index,size_t id,uint8_t * data,size_t length)398 static esp_err_t esp_bt_hidd_dev_input_set(void *devp, size_t index, size_t id, uint8_t *data, size_t length)
399 {
400     hidd_report_item_t *p_rpt;
401     esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
402     esp_err_t ret = ESP_OK;
403     osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
404     do {
405         if (!is_init()) {
406             ESP_LOGE(TAG, "HID device is uninit");
407             ret = ESP_FAIL;
408             break;
409         }
410 
411         if (s_hidd_param.dev != dev) {
412             ESP_LOGE(TAG, "Wrong HID device provided");
413             ret = ESP_FAIL;
414             break;
415         }
416 
417         if (!dev->connected) {
418             ESP_LOGE(TAG, "HID device not connected!");
419             ret = ESP_FAIL;
420             break;
421         }
422 
423         p_rpt = get_report_by_idx_id_type(dev, index, id, ESP_HID_REPORT_TYPE_INPUT);
424         if (p_rpt == NULL) {
425             ESP_LOGE(TAG, "HID device not connected!");
426             ret = ESP_FAIL;
427             break;
428         }
429 
430         if (length > p_rpt->value_len) {
431             ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len);
432             ret = ESP_FAIL;
433             break;
434         }
435     } while(0);
436     osi_mutex_unlock(&s_hidd_param.mutex);
437 
438     if (ret == ESP_OK) {
439         ret = esp_bt_hid_device_send_report(ESP_HIDD_REPORT_TYPE_INTRDATA, id, length, data);
440     }
441     return ret;
442 }
443 
esp_bt_hidd_dev_feature_set(void * devp,size_t index,size_t id,uint8_t * data,size_t length)444 static esp_err_t esp_bt_hidd_dev_feature_set(void *devp, size_t index, size_t id, uint8_t *data, size_t length)
445 {
446     hidd_report_item_t *p_rpt;
447     esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
448     esp_err_t ret = ESP_OK;
449     osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
450     do {
451         if (!is_init()) {
452             ESP_LOGE(TAG, "HID device is uninit");
453             ret = ESP_FAIL;
454             break;
455         }
456 
457         if (s_hidd_param.dev != dev) {
458             ESP_LOGE(TAG, "Wrong HID device provided");
459             ret = ESP_FAIL;
460             break;
461         }
462 
463         if (!dev->connected) {
464             ESP_LOGE(TAG, "HID device not connected!");
465             ret = ESP_FAIL;
466             break;
467         }
468 
469         p_rpt = get_report_by_idx_id_type(dev, index, id, ESP_HID_REPORT_TYPE_FEATURE);
470         if (p_rpt == NULL) {
471             ESP_LOGE(TAG, "HID device not connected!");
472             ret = ESP_FAIL;
473             break;
474         }
475 
476         if (length > p_rpt->value_len) {
477             ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len);
478             ret = ESP_FAIL;
479             break;
480         }
481     } while(0);
482     osi_mutex_unlock(&s_hidd_param.mutex);
483 
484     if (ret == ESP_OK) {
485         ret = esp_bt_hid_device_send_report(ESP_HID_REPORT_TYPE_FEATURE, id, length, data);
486     }
487     return ret;
488 }
489 
esp_bt_hidd_dev_event_handler_register(void * devp,esp_event_handler_t callback,esp_hidd_event_t event)490 static esp_err_t esp_bt_hidd_dev_event_handler_register(void *devp, esp_event_handler_t callback, esp_hidd_event_t event)
491 {
492     esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
493     esp_err_t ret = ESP_OK;
494     osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
495     do {
496         if (!is_init()) {
497             ESP_LOGE(TAG, "HID device is uninit");
498             ret = ESP_FAIL;
499             break;
500         }
501 
502         if (s_hidd_param.dev != dev) {
503             ESP_LOGE(TAG, "Wrong HID device provided");
504             ret = ESP_FAIL;
505             break;
506         }
507 
508         ret = esp_event_handler_register_with(dev->event_loop_handle, ESP_HIDD_EVENTS, event, callback, dev->dev);
509     } while (0);
510     osi_mutex_unlock(&s_hidd_param.mutex);
511     return ret;
512 }
513 
esp_bt_hidd_dev_event_handler_unregister(void * devp,esp_event_handler_t callback,esp_hidd_event_t event)514 static esp_err_t esp_bt_hidd_dev_event_handler_unregister(void *devp, esp_event_handler_t callback, esp_hidd_event_t event)
515 {
516     esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
517     esp_err_t ret = ESP_OK;
518     osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
519     do {
520         if (!is_init()) {
521             ESP_LOGE(TAG, "HID device is uninit");
522             ret = ESP_FAIL;
523             break;
524         }
525 
526         if (s_hidd_param.dev != dev) {
527             ESP_LOGE(TAG, "Wrong HID device provided");
528             ret = ESP_FAIL;
529             break;
530         }
531         ret = esp_event_handler_unregister_with(dev->event_loop_handle, ESP_HIDD_EVENTS, event, callback);
532     } while (0);
533     osi_mutex_unlock(&s_hidd_param.mutex);
534     return ret;
535 }
536 
bt_hidd_cb(esp_hidd_cb_event_t event,esp_hidd_cb_param_t * param)537 void bt_hidd_cb(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
538 {
539     esp_hidd_event_data_t cb_param = {0};
540     esp_hidd_event_data_t *p_cb_param = NULL;
541     size_t event_data_size = 0;
542     uint8_t map_index = 0;
543     hidd_report_item_t *p_rpt = NULL;
544 
545     if (!is_init()) {
546         ESP_LOGE(TAG, "HID device is uninit, event(%d)", event);
547         return;
548     }
549 
550     switch (event) {
551     case ESP_HIDD_INIT_EVT: {
552         if (param->init.status == ESP_HIDD_SUCCESS) {
553             ESP_LOGD(TAG, "Setting hid parameters in_qos:%d, out_qos:%d", s_hidd_param.in_qos.token_bucket_size,
554                      s_hidd_param.out_qos.token_bucket_size);
555             esp_bt_hid_device_register_app(&s_hidd_param.app_param, &s_hidd_param.in_qos, &s_hidd_param.out_qos);
556         } else {
557             ESP_LOGE(TAG, "Init hidd failed (%d)!", param->init.status);
558             cb_param.start.status = bt_hidd_get_status(param->init.status);
559             esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_START_EVENT, &cb_param,
560                               sizeof(esp_hidd_event_data_t), portMAX_DELAY);
561 
562             bt_hidd_dev_free();
563         }
564         break;
565     }
566     case ESP_HIDD_DEINIT_EVT: {
567         cb_param.stop.status = bt_hidd_get_status(param->deinit.status);
568         esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_STOP_EVENT, &cb_param,
569                           sizeof(esp_hidd_event_data_t), portMAX_DELAY);
570         if (param->deinit.status == ESP_HIDD_SUCCESS) {
571             bt_hidd_dev_free();
572         } else {
573             ESP_LOGE(TAG, "Deinit hidd failed (%d)!", param->deinit.status);
574         }
575         break;
576     }
577     case ESP_HIDD_REGISTER_APP_EVT: {
578         if (param->register_app.status == ESP_HIDD_SUCCESS) {
579             ESP_LOGD(TAG, "Setting hid parameters success!");
580             if (param->register_app.in_use && param->register_app.bd_addr != NULL) {
581                 ESP_LOGI(TAG, "Start virtual cable plug!");
582                 esp_bt_hid_device_connect(param->register_app.bd_addr);
583             }
584 
585             osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
586             s_hidd_param.dev->registered = true;
587             osi_mutex_unlock(&s_hidd_param.mutex);
588 
589             cb_param.start.status = bt_hidd_get_status(param->init.status);
590             esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_START_EVENT, &cb_param,
591                               sizeof(esp_hidd_event_data_t), portMAX_DELAY);
592         } else {
593             ESP_LOGE(TAG, "Setting hid parameters failed (%d), now deint!", param->register_app.status);
594             esp_bt_hid_device_deinit();
595         }
596         break;
597     }
598     case ESP_HIDD_UNREGISTER_APP_EVT: {
599         break;
600     }
601     case ESP_HIDD_OPEN_EVT: {
602         if (param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTING) {
603             break;
604         }
605         if (param->open.status == ESP_HIDD_SUCCESS && param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTED) {
606             ESP_LOGI(TAG, "Connected to %02x:%02x:%02x:%02x:%02x:%02x", param->open.bd_addr[0], param->open.bd_addr[1],
607                      param->open.bd_addr[2], param->open.bd_addr[3], param->open.bd_addr[4], param->open.bd_addr[5]);
608             osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
609             s_hidd_param.dev->connected = true;
610             memcpy(s_hidd_param.dev->remote_bda, param->open.bd_addr, ESP_BD_ADDR_LEN);
611             osi_mutex_unlock(&s_hidd_param.mutex);
612         } else {
613             ESP_LOGE(TAG, "Connect failed (%d)!", param->open.status);
614         }
615         cb_param.connect.status = bt_hidd_get_status(param->open.status);
616         cb_param.connect.dev = s_hidd_param.dev->dev;
617         esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_CONNECT_EVENT, &cb_param,
618                           sizeof(esp_hidd_event_data_t), portMAX_DELAY);
619         break;
620     }
621     case ESP_HIDD_CLOSE_EVT: {
622         if (param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTING) {
623             break;
624         }
625         if (param->close.status == ESP_HIDD_SUCCESS && param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTED) {
626             osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
627             s_hidd_param.dev->connected = false;
628             memset(s_hidd_param.dev->remote_bda, 0, ESP_BD_ADDR_LEN);
629             osi_mutex_unlock(&s_hidd_param.mutex);
630         } else {
631             ESP_LOGE(TAG, "Disconnect failed (%d)!", param->close.status);
632         }
633         cb_param.disconnect.status = bt_hidd_get_status(param->close.status);
634         cb_param.disconnect.dev = s_hidd_param.dev->dev;
635         cb_param.disconnect.reason = param->close.status;
636         esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_DISCONNECT_EVENT, &cb_param,
637                           sizeof(esp_hidd_event_data_t), portMAX_DELAY);
638         break;
639     }
640     case ESP_HIDD_SEND_REPORT_EVT:
641         break;
642     case ESP_HIDD_REPORT_ERR_EVT:
643         break;
644     case ESP_HIDD_GET_REPORT_EVT: {
645         uint8_t *data_ptr = NULL;
646         p_rpt = get_report_by_id_and_type((esp_bt_hidd_dev_t *)s_hidd_param.dev->dev, param->get_report.report_id,
647                                           param->get_report.report_type, &map_index);
648         if (p_rpt == NULL) {
649             ESP_LOGE(TAG, "Can not find report!");
650             esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID);
651             break;
652         }
653         if (param->get_report.buffer_size > p_rpt->value_len) {
654             ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len);
655             esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM);
656             break;
657         }
658 
659         event_data_size = sizeof(esp_hidd_event_data_t);
660         if (param->get_report.buffer_size) {
661             event_data_size += 2;
662         }
663 
664         if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) {
665             ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
666             break;
667         }
668         memset(p_cb_param, 0, event_data_size);
669         p_cb_param->feature.dev = s_hidd_param.dev->dev;
670         p_cb_param->feature.trans_type = ESP_HID_TRANS_GET_REPORT;
671         p_cb_param->feature.report_type = param->get_report.report_type;
672         p_cb_param->feature.report_id = p_rpt->report_id;
673         p_cb_param->feature.usage = p_rpt->usage;
674         p_cb_param->feature.length = param->get_report.buffer_size ? 2 : 0;
675         p_cb_param->feature.data = ((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t);
676         p_cb_param->feature.map_index = map_index;
677         if (param->get_report.buffer_size) {
678             data_ptr = ((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t);
679             *data_ptr++ = (uint8_t)param->get_report.buffer_size;
680             *data_ptr++ = (uint8_t)(param->get_report.buffer_size >> 8);
681         }
682         esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, p_cb_param,
683                           event_data_size, portMAX_DELAY);
684         break;
685     }
686     case ESP_HIDD_SET_REPORT_EVT: {
687         p_rpt = get_report_by_id_and_type((esp_bt_hidd_dev_t *)s_hidd_param.dev->dev, param->set_report.report_id,
688                                           param->set_report.report_type, &map_index);
689         if (p_rpt == NULL) {
690             ESP_LOGE(TAG, "Can not find report!");
691             esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID);
692             break;
693         }
694         if (param->set_report.len > p_rpt->value_len) {
695             ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len);
696             esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM);
697             break;
698         }
699 
700         event_data_size = sizeof(esp_hidd_event_data_t);
701         if (param->set_report.len && param->set_report.data) {
702             event_data_size += param->set_report.len;
703         }
704 
705         if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) {
706             ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
707             break;
708         }
709         memset(p_cb_param, 0, event_data_size);
710         p_cb_param->feature.dev = s_hidd_param.dev->dev;
711         p_cb_param->feature.trans_type = ESP_HID_TRANS_SET_REPORT;
712         p_cb_param->feature.report_type = param->set_report.report_type;
713         p_cb_param->feature.report_id = p_rpt->report_id;
714         p_cb_param->feature.usage = p_rpt->usage;
715         p_cb_param->feature.length = param->set_report.len;
716         p_cb_param->feature.data = param->set_report.data;
717         p_cb_param->feature.map_index = map_index;
718         if (param->set_report.len && param->set_report.data) {
719             memcpy(((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t), param->set_report.data,
720                    param->set_report.len);
721         }
722         esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, p_cb_param,
723                           event_data_size, portMAX_DELAY);
724         break;
725     }
726     case ESP_HIDD_SET_PROTOCOL_EVT: {
727         if (param->set_protocol.protocol_mode != ESP_HIDD_UNSUPPORTED_MODE) {
728             if (s_hidd_param.dev->protocol_mode == param->set_protocol.protocol_mode) {
729                 break;
730             }
731             osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
732             s_hidd_param.dev->protocol_mode = param->set_protocol.protocol_mode;
733             osi_mutex_unlock(&s_hidd_param.mutex);
734             cb_param.protocol_mode.dev = s_hidd_param.dev->dev;
735             cb_param.protocol_mode.protocol_mode = s_hidd_param.dev->protocol_mode;
736             cb_param.protocol_mode.map_index = 0;
737             esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_PROTOCOL_MODE_EVENT,
738                               &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
739         } else {
740             ESP_LOGE(TAG, "Unsupported protocol mode!");
741             break;
742         }
743         break;
744     }
745     case ESP_HIDD_INTR_DATA_EVT: {
746         p_rpt = get_report_by_id_and_type((esp_bt_hidd_dev_t *)s_hidd_param.dev->dev, param->intr_data.report_id,
747                                           ESP_HID_REPORT_TYPE_OUTPUT, &map_index);
748         if (p_rpt == NULL) {
749             ESP_LOGE(TAG, "Can not find report!");
750             break;
751         }
752 
753         event_data_size = sizeof(esp_hidd_event_data_t);
754         if (param->intr_data.len && param->intr_data.data) {
755             event_data_size += param->intr_data.len;
756         }
757 
758         if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) {
759             ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
760             break;
761         }
762         memset(p_cb_param, 0, event_data_size);
763         p_cb_param->output.dev = s_hidd_param.dev->dev;
764         p_cb_param->output.report_id = p_rpt->report_id;
765         p_cb_param->output.usage = p_rpt->usage;
766         p_cb_param->output.length = param->intr_data.len;
767         p_cb_param->output.data = param->intr_data.data;
768         p_cb_param->output.map_index = map_index;
769         if (param->intr_data.len && param->intr_data.data) {
770             memcpy(((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t), param->intr_data.data,
771                    param->intr_data.len);
772         }
773         esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, p_cb_param,
774                           event_data_size, portMAX_DELAY);
775         break;
776     }
777     default:
778         break;
779     }
780 
781     if (p_cb_param) {
782         free(p_cb_param);
783         p_cb_param = NULL;
784     }
785 }
786 
esp_bt_hidd_dev_init(esp_hidd_dev_t * dev_p,const esp_hid_device_config_t * config,esp_event_handler_t callback)787 esp_err_t esp_bt_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_config_t *config, esp_event_handler_t callback)
788 {
789     esp_err_t ret = ESP_OK;
790     if (dev_p == NULL || config == NULL) {
791         return ESP_ERR_INVALID_ARG;
792     }
793 
794     if (is_init()) {
795         ESP_LOGE(TAG, "HID device profile already initialized");
796         return ESP_FAIL;
797     }
798 
799     osi_mutex_new(&s_hidd_param.mutex);
800     if (s_hidd_param.mutex == NULL) {
801         ESP_LOGE(TAG, "HID device mutex could not be allocated");
802         return ESP_ERR_NO_MEM;
803     }
804 
805     s_hidd_param.dev = (esp_bt_hidd_dev_t *)calloc(1, sizeof(esp_bt_hidd_dev_t));
806     if (s_hidd_param.dev == NULL) {
807         ESP_LOGE(TAG, "HID device could not be allocated");
808         return ESP_ERR_NO_MEM;
809     }
810 
811     //[1] Reset the hid device target environment
812     s_hidd_param.dev->connected = false;
813     s_hidd_param.dev->registered = false;
814     s_hidd_param.dev->bat_level = 100;
815     s_hidd_param.dev->control = ESP_HID_CONTROL_EXIT_SUSPEND;
816     s_hidd_param.dev->protocol_mode = ESP_HID_PROTOCOL_MODE_REPORT;
817     s_hidd_param.dev->event_loop_handle = NULL;
818     s_hidd_param.dev->dev = dev_p;
819 
820     esp_event_loop_args_t event_task_args = {
821         .queue_size = 5,
822         .task_name = "bt_hidd_events",
823         .task_priority = uxTaskPriorityGet(NULL),
824         .task_stack_size = 2048,
825         .task_core_id = tskNO_AFFINITY
826     };
827     ret = esp_event_loop_create(&event_task_args, &s_hidd_param.dev->event_loop_handle);
828     if (ret != ESP_OK) {
829         ESP_LOGE(TAG, "HID device event loop could not be created");
830         bt_hidd_dev_free();
831         return ret;
832     }
833 
834     //[2] parse hid descriptor
835     ret = bt_hidd_init_config(s_hidd_param.dev, config);
836     if (ret != ESP_OK) {
837         bt_hidd_dev_free();
838         return ret;
839     }
840 
841     //[3] configure hidd app param and qos param
842     bt_hidd_init_app();
843     bt_hidd_init_qos();
844 
845     //[4] implement the interface
846     dev_p->dev = s_hidd_param.dev;
847     dev_p->connected = esp_bt_hidd_dev_connected;
848     dev_p->disconnect = esp_bt_hidd_dev_disconnect;
849     dev_p->deinit = esp_bt_hidd_dev_deinit;
850     dev_p->battery_set = esp_bt_hidd_dev_battery_set;
851     dev_p->input_set = esp_bt_hidd_dev_input_set;
852     dev_p->feature_set = esp_bt_hidd_dev_feature_set;
853     dev_p->event_handler_register = esp_bt_hidd_dev_event_handler_register;
854     dev_p->event_handler_unregister = esp_bt_hidd_dev_event_handler_unregister;
855 
856     ret = esp_bt_hidd_dev_event_handler_register(s_hidd_param.dev, esp_hidd_process_event_data_handler, ESP_EVENT_ANY_ID);
857     if (ret != ESP_OK) {
858         bt_hidd_dev_free();
859         return ret;
860     }
861 
862     if (callback != NULL) {
863         ret = esp_bt_hidd_dev_event_handler_register(s_hidd_param.dev, callback, ESP_EVENT_ANY_ID);
864         if (ret != ESP_OK) {
865             bt_hidd_dev_free();
866             return ret;
867         }
868     }
869 
870     ret = esp_bt_hid_device_register_callback(bt_hidd_cb);
871     ret |= esp_bt_hid_device_init();
872     if (ret != ESP_OK) {
873         bt_hidd_dev_free();
874         return ret;
875     }
876 
877     return ret;
878 }
879 #endif /* CONFIG_BT_HID_DEVICE_ENABLED */
880