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