1 /*
2 * Human Interface Device (HID) USB class core
3 *
4 * Copyright (c) 2018 Intel Corporation
5 * Copyright (c) 2018 Nordic Semiconductor ASA
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #define LOG_LEVEL CONFIG_USB_HID_LOG_LEVEL
11 #include <logging/log.h>
12 LOG_MODULE_REGISTER(usb_hid);
13
14 #include <sys/byteorder.h>
15 #include <usb_device.h>
16
17 #include <usb_descriptor.h>
18 #include <class/usb_hid.h>
19
20 #include <stdlib.h>
21
22 #define HID_INT_IN_EP_IDX 0
23 #define HID_INT_OUT_EP_IDX 1
24
25 struct usb_hid_class_subdescriptor {
26 uint8_t bDescriptorType;
27 uint16_t wDescriptorLength;
28 } __packed;
29
30 struct usb_hid_descriptor {
31 uint8_t bLength;
32 uint8_t bDescriptorType;
33 uint16_t bcdHID;
34 uint8_t bCountryCode;
35 uint8_t bNumDescriptors;
36
37 /*
38 * Specification says at least one Class Descriptor needs to
39 * be present (Report Descriptor).
40 */
41 struct usb_hid_class_subdescriptor subdesc[1];
42 } __packed;
43
44 struct usb_hid_config {
45 struct usb_if_descriptor if0;
46 struct usb_hid_descriptor if0_hid;
47 struct usb_ep_descriptor if0_int_in_ep;
48 #ifdef CONFIG_ENABLE_HID_INT_OUT_EP
49 struct usb_ep_descriptor if0_int_out_ep;
50 #endif
51 } __packed;
52
53 #if defined(CONFIG_USB_HID_BOOT_PROTOCOL)
54 #define INITIALIZER_IF \
55 { \
56 .bLength = sizeof(struct usb_if_descriptor), \
57 .bDescriptorType = USB_DESC_INTERFACE, \
58 .bInterfaceNumber = 0, \
59 .bAlternateSetting = 0, \
60 .bNumEndpoints = 1, \
61 .bInterfaceClass = USB_BCC_HID, \
62 .bInterfaceSubClass = 1, \
63 .bInterfaceProtocol = CONFIG_USB_HID_PROTOCOL_CODE, \
64 .iInterface = 0, \
65 }
66 #else
67 #define INITIALIZER_IF \
68 { \
69 .bLength = sizeof(struct usb_if_descriptor), \
70 .bDescriptorType = USB_DESC_INTERFACE, \
71 .bInterfaceNumber = 0, \
72 .bAlternateSetting = 0, \
73 .bNumEndpoints = 1, \
74 .bInterfaceClass = USB_BCC_HID, \
75 .bInterfaceSubClass = 0, \
76 .bInterfaceProtocol = 0, \
77 .iInterface = 0, \
78 }
79 #endif
80
81 /* Descriptor length needs to be set after initialization */
82 #define INITIALIZER_IF_HID \
83 { \
84 .bLength = sizeof(struct usb_hid_descriptor), \
85 .bDescriptorType = USB_DESC_HID, \
86 .bcdHID = sys_cpu_to_le16(USB_SRN_1_1), \
87 .bCountryCode = 0, \
88 .bNumDescriptors = 1, \
89 .subdesc[0] = { \
90 .bDescriptorType = USB_DESC_HID_REPORT, \
91 .wDescriptorLength = 0, \
92 }, \
93 }
94
95 #define INITIALIZER_IF_EP(addr, attr, mps) \
96 { \
97 .bLength = sizeof(struct usb_ep_descriptor), \
98 .bDescriptorType = USB_DESC_ENDPOINT, \
99 .bEndpointAddress = addr, \
100 .bmAttributes = attr, \
101 .wMaxPacketSize = sys_cpu_to_le16(mps), \
102 .bInterval = CONFIG_USB_HID_POLL_INTERVAL_MS, \
103 }
104
105 #ifdef CONFIG_ENABLE_HID_INT_OUT_EP
106 #define DEFINE_HID_DESCR(x, _) \
107 USBD_CLASS_DESCR_DEFINE(primary, x) \
108 struct usb_hid_config hid_cfg_##x = { \
109 /* Interface descriptor */ \
110 .if0 = INITIALIZER_IF, \
111 .if0_hid = INITIALIZER_IF_HID, \
112 .if0_int_in_ep = \
113 INITIALIZER_IF_EP(AUTO_EP_IN, \
114 USB_DC_EP_INTERRUPT, \
115 CONFIG_HID_INTERRUPT_EP_MPS), \
116 .if0_int_out_ep = \
117 INITIALIZER_IF_EP(AUTO_EP_OUT, \
118 USB_DC_EP_INTERRUPT, \
119 CONFIG_HID_INTERRUPT_EP_MPS), \
120 };
121 #else
122 #define DEFINE_HID_DESCR(x, _) \
123 USBD_CLASS_DESCR_DEFINE(primary, x) \
124 struct usb_hid_config hid_cfg_##x = { \
125 /* Interface descriptor */ \
126 .if0 = INITIALIZER_IF, \
127 .if0_hid = INITIALIZER_IF_HID, \
128 .if0_int_in_ep = \
129 INITIALIZER_IF_EP(AUTO_EP_IN, \
130 USB_DC_EP_INTERRUPT, \
131 CONFIG_HID_INTERRUPT_EP_MPS), \
132 };
133 #endif
134
135 struct hid_device_info {
136 const uint8_t *report_desc;
137 size_t report_size;
138 const struct hid_ops *ops;
139 #ifdef CONFIG_USB_DEVICE_SOF
140 uint32_t sof_cnt[CONFIG_USB_HID_REPORTS];
141 bool idle_on;
142 uint8_t idle_rate[CONFIG_USB_HID_REPORTS];
143 #endif
144 #ifdef CONFIG_USB_HID_BOOT_PROTOCOL
145 uint8_t protocol;
146 #endif
147 bool configured;
148 bool suspended;
149 struct usb_dev_data common;
150 };
151
152 static sys_slist_t usb_hid_devlist;
153
hid_on_get_idle(struct hid_device_info * dev_data,struct usb_setup_packet * setup,int32_t * len,uint8_t ** data)154 static int hid_on_get_idle(struct hid_device_info *dev_data,
155 struct usb_setup_packet *setup, int32_t *len,
156 uint8_t **data)
157 {
158 #ifdef CONFIG_USB_DEVICE_SOF
159 uint8_t report_id = (uint8_t)setup->wValue;
160
161 if (report_id > CONFIG_USB_HID_REPORTS) {
162 LOG_ERR("Report id out of limit: %d", report_id);
163 return -ENOTSUP;
164 }
165
166 LOG_DBG("Get Idle callback, report_id: %d", report_id);
167
168 if (report_id == 0U) {
169 /*
170 * Common value, stored on Set Idle request with Report ID 0,
171 * can be outdated because the duration can also
172 * be set individually for each Report ID.
173 */
174 *data = &dev_data->idle_rate[0];
175 *len = sizeof(dev_data->idle_rate[0]);
176 } else {
177 *data = &dev_data->idle_rate[report_id - 1];
178 *len = sizeof(dev_data->idle_rate[report_id - 1]);
179 }
180
181 return 0;
182 #else
183 return -ENOTSUP;
184 #endif
185 }
186
hid_on_get_report(struct hid_device_info * dev_data,struct usb_setup_packet * setup,int32_t * len,uint8_t ** data)187 static int hid_on_get_report(struct hid_device_info *dev_data,
188 struct usb_setup_packet *setup, int32_t *len,
189 uint8_t **data)
190 {
191 LOG_DBG("Get Report callback");
192
193 /* TODO: Do something. */
194
195 return -ENOTSUP;
196 }
197
hid_on_get_protocol(struct hid_device_info * dev_data,struct usb_setup_packet * setup,int32_t * len,uint8_t ** data)198 static int hid_on_get_protocol(struct hid_device_info *dev_data,
199 struct usb_setup_packet *setup, int32_t *len,
200 uint8_t **data)
201 {
202 #ifdef CONFIG_USB_HID_BOOT_PROTOCOL
203 uint32_t size = sizeof(dev_data->protocol);
204
205 if (setup->wValue) {
206 LOG_ERR("wValue should be 0");
207 return -ENOTSUP;
208 }
209
210 LOG_DBG("Get Protocol: %d", dev_data->protocol);
211
212 *data = &dev_data->protocol;
213 *len = size;
214 return 0;
215 #else
216 return -ENOTSUP;
217 #endif
218 }
219
hid_on_set_idle(struct hid_device_info * dev_data,struct usb_setup_packet * setup,int32_t * len,uint8_t ** data)220 static int hid_on_set_idle(struct hid_device_info *dev_data,
221 struct usb_setup_packet *setup, int32_t *len,
222 uint8_t **data)
223 {
224 #ifdef CONFIG_USB_DEVICE_SOF
225 uint8_t rate = (uint8_t)(setup->wValue >> 8);
226 uint8_t report_id = (uint8_t)setup->wValue;
227
228 if (report_id > CONFIG_USB_HID_REPORTS) {
229 LOG_ERR("Report id out of limit: %d", report_id);
230 return -ENOTSUP;
231 }
232
233 LOG_DBG("Set Idle callback, rate: %d, report_id: %d", rate, report_id);
234
235 if (report_id == 0U) {
236 for (uint16_t i = 0; i < CONFIG_USB_HID_REPORTS; i++) {
237 dev_data->idle_rate[i] = rate;
238 dev_data->sof_cnt[i] = 0U;
239 }
240 } else {
241 dev_data->idle_rate[report_id - 1] = rate;
242 dev_data->sof_cnt[report_id - 1] = 0U;
243 }
244
245 dev_data->idle_on = (bool)setup->wValue;
246
247 return 0;
248 #else
249 return -ENOTSUP;
250 #endif
251 }
252
hid_on_set_report(struct hid_device_info * dev_data,struct usb_setup_packet * setup,int32_t * len,uint8_t ** data)253 static int hid_on_set_report(struct hid_device_info *dev_data,
254 struct usb_setup_packet *setup, int32_t *len,
255 uint8_t **data)
256 {
257 LOG_DBG("Set Report callback");
258
259 /* TODO: Do something. */
260
261 return -ENOTSUP;
262 }
263
hid_on_set_protocol(const struct device * dev,struct hid_device_info * dev_data,struct usb_setup_packet * setup)264 static int hid_on_set_protocol(const struct device *dev,
265 struct hid_device_info *dev_data,
266 struct usb_setup_packet *setup)
267 {
268 #ifdef CONFIG_USB_HID_BOOT_PROTOCOL
269 uint16_t protocol = setup->wValue;
270
271 if (protocol > HID_PROTOCOL_REPORT) {
272 LOG_ERR("Unsupported protocol: %u", protocol);
273 return -ENOTSUP;
274 }
275
276 LOG_DBG("Set Protocol: %u", protocol);
277
278 if (dev_data->protocol != protocol) {
279 dev_data->protocol = protocol;
280
281 if (dev_data->ops && dev_data->ops->protocol_change) {
282 dev_data->ops->protocol_change(dev, protocol);
283 }
284 }
285
286 return 0;
287 #else
288 return -ENOTSUP;
289 #endif
290 }
291
usb_set_hid_report_size(const struct usb_cfg_data * cfg,uint16_t size)292 static void usb_set_hid_report_size(const struct usb_cfg_data *cfg, uint16_t size)
293 {
294 struct usb_if_descriptor *if_desc = (void *)cfg->interface_descriptor;
295 struct usb_hid_config *desc =
296 CONTAINER_OF(if_desc, struct usb_hid_config, if0);
297
298 LOG_DBG("if_desc %p desc %p size %u", if_desc, desc, size);
299
300 sys_put_le16(size,
301 (uint8_t *)&(desc->if0_hid.subdesc[0].wDescriptorLength));
302 }
303
304 #ifdef CONFIG_USB_DEVICE_SOF
hid_clear_idle_ctx(struct hid_device_info * dev_data)305 void hid_clear_idle_ctx(struct hid_device_info *dev_data)
306 {
307 dev_data->idle_on = false;
308 for (uint16_t i = 0; i < CONFIG_USB_HID_REPORTS; i++) {
309 dev_data->sof_cnt[i] = 0U;
310 dev_data->idle_rate[i] = 0U;
311 }
312 }
313
hid_sof_handler(struct hid_device_info * dev_data)314 void hid_sof_handler(struct hid_device_info *dev_data)
315 {
316 const struct device *dev = dev_data->common.dev;
317 bool reported = false;
318
319 if (dev_data->ops == NULL || dev_data->ops->on_idle == NULL) {
320 return;
321 }
322
323 for (uint16_t i = 0; i < CONFIG_USB_HID_REPORTS; i++) {
324 if (dev_data->idle_rate[i]) {
325 dev_data->sof_cnt[i]++;
326 } else {
327 continue;
328 }
329
330 uint32_t diff = abs(dev_data->idle_rate[i] * 4U -
331 dev_data->sof_cnt[i]);
332
333 if (diff < 2 && reported == false) {
334 dev_data->sof_cnt[i] = 0U;
335 /*
336 * We can submit only one report at a time
337 * because we have only one endpoint and
338 * there is no queue for the packets/reports.
339 */
340 reported = true;
341 dev_data->ops->on_idle(dev, i + 1);
342 } else if (diff == 0 && reported == true) {
343 /* Delay it once until it has spread. */
344 dev_data->sof_cnt[i]--;
345 }
346 }
347 }
348 #endif
349
hid_do_status_cb(struct hid_device_info * dev_data,enum usb_dc_status_code status,const uint8_t * param)350 static void hid_do_status_cb(struct hid_device_info *dev_data,
351 enum usb_dc_status_code status,
352 const uint8_t *param)
353 {
354 switch (status) {
355 case USB_DC_ERROR:
356 LOG_INF("Device error");
357 break;
358 case USB_DC_RESET:
359 LOG_INF("Device reset detected");
360 dev_data->configured = false;
361 dev_data->suspended = false;
362 #ifdef CONFIG_USB_HID_BOOT_PROTOCOL
363 dev_data->protocol = HID_PROTOCOL_REPORT;
364 #endif
365 #ifdef CONFIG_USB_DEVICE_SOF
366 hid_clear_idle_ctx(dev_data);
367 #endif
368 break;
369 case USB_DC_CONNECTED:
370 LOG_INF("Device connected");
371 break;
372 case USB_DC_CONFIGURED:
373 LOG_INF("Device configured");
374 dev_data->configured = true;
375 break;
376 case USB_DC_DISCONNECTED:
377 LOG_INF("Device disconnected");
378 dev_data->configured = false;
379 dev_data->suspended = false;
380 break;
381 case USB_DC_SUSPEND:
382 LOG_INF("Device suspended");
383 dev_data->suspended = true;
384 break;
385 case USB_DC_RESUME:
386 LOG_INF("Device resumed");
387 if (dev_data->suspended) {
388 LOG_INF("from suspend");
389 dev_data->suspended = false;
390 } else {
391 LOG_DBG("Spurious resume event");
392 }
393 break;
394 case USB_DC_SOF:
395 #ifdef CONFIG_USB_DEVICE_SOF
396 if (dev_data->idle_on) {
397 hid_sof_handler(dev_data);
398 }
399 #endif
400 break;
401 case USB_DC_UNKNOWN:
402 default:
403 LOG_INF("Unknown event");
404 break;
405 }
406
407 }
408
hid_status_cb(struct usb_cfg_data * cfg,enum usb_dc_status_code status,const uint8_t * param)409 static void hid_status_cb(struct usb_cfg_data *cfg,
410 enum usb_dc_status_code status,
411 const uint8_t *param)
412 {
413 struct hid_device_info *dev_data;
414 struct usb_dev_data *common;
415
416 LOG_DBG("cfg %p status %d", cfg, status);
417
418 common = usb_get_dev_data_by_cfg(&usb_hid_devlist, cfg);
419 if (common == NULL) {
420 LOG_WRN("Device data not found for cfg %p", cfg);
421 return;
422 }
423
424 dev_data = CONTAINER_OF(common, struct hid_device_info, common);
425
426 hid_do_status_cb(dev_data, status, param);
427 }
428
hid_class_handle_req(struct usb_setup_packet * setup,int32_t * len,uint8_t ** data)429 static int hid_class_handle_req(struct usb_setup_packet *setup,
430 int32_t *len, uint8_t **data)
431 {
432 struct hid_device_info *dev_data;
433 struct usb_dev_data *common;
434 const struct device *dev;
435
436 LOG_DBG("Class request:"
437 "bRequest 0x%02x, bmRequestType 0x%02x len %d",
438 setup->bRequest, setup->bmRequestType, *len);
439
440 common = usb_get_dev_data_by_iface(&usb_hid_devlist,
441 (uint8_t)setup->wIndex);
442 if (common == NULL) {
443 LOG_WRN("Device data not found for interface %u",
444 setup->wIndex);
445 return -ENODEV;
446 }
447
448 dev_data = CONTAINER_OF(common, struct hid_device_info, common);
449 dev = common->dev;
450
451 if (usb_reqtype_is_to_host(setup)) {
452 switch (setup->bRequest) {
453 case USB_HID_GET_IDLE:
454 return hid_on_get_idle(dev_data, setup, len, data);
455 case USB_HID_GET_REPORT:
456 if (dev_data->ops && dev_data->ops->get_report) {
457 return dev_data->ops->get_report(dev, setup,
458 len, data);
459 } else {
460 return hid_on_get_report(dev_data, setup, len,
461 data);
462 }
463 break;
464 case USB_HID_GET_PROTOCOL:
465 return hid_on_get_protocol(dev_data, setup, len, data);
466 default:
467 LOG_ERR("Unhandled request 0x%02x", setup->bRequest);
468 break;
469 }
470 } else {
471 switch (setup->bRequest) {
472 case USB_HID_SET_IDLE:
473 return hid_on_set_idle(dev_data, setup, len, data);
474 case USB_HID_SET_REPORT:
475 if (dev_data->ops && dev_data->ops->set_report) {
476 return dev_data->ops->set_report(dev, setup,
477 len, data);
478 } else {
479 return hid_on_set_report(dev_data, setup, len,
480 data);
481 }
482 break;
483 case USB_HID_SET_PROTOCOL:
484 return hid_on_set_protocol(dev, dev_data, setup);
485 default:
486 LOG_ERR("Unhandled request 0x%02x", setup->bRequest);
487 break;
488 }
489 }
490
491 return -ENOTSUP;
492 }
493
hid_custom_handle_req(struct usb_setup_packet * setup,int32_t * len,uint8_t ** data)494 static int hid_custom_handle_req(struct usb_setup_packet *setup,
495 int32_t *len, uint8_t **data)
496 {
497 LOG_DBG("Standard request:"
498 "bRequest 0x%02x, bmRequestType 0x%02x, len %d",
499 setup->bRequest, setup->bmRequestType, setup->wLength);
500
501 if (usb_reqtype_is_to_host(setup) &&
502 setup->RequestType.recipient == USB_REQTYPE_RECIPIENT_INTERFACE &&
503 setup->bRequest == USB_SREQ_GET_DESCRIPTOR) {
504 uint8_t value = (uint8_t)(setup->wValue >> 8);
505 uint8_t iface_num = (uint8_t)setup->wIndex;
506 struct hid_device_info *dev_data;
507 struct usb_dev_data *common;
508 const struct usb_cfg_data *cfg;
509 const struct usb_hid_config *hid_desc;
510
511 common = usb_get_dev_data_by_iface(&usb_hid_devlist, iface_num);
512 if (common == NULL) {
513 LOG_WRN("Device data not found for interface %u",
514 iface_num);
515 return -EINVAL;
516 }
517
518 dev_data = CONTAINER_OF(common, struct hid_device_info, common);
519
520 switch (value) {
521 case USB_DESC_HID:
522 cfg = common->dev->config;
523 hid_desc = cfg->interface_descriptor;
524
525 LOG_DBG("Return HID Descriptor");
526
527 *len = MIN(setup->wLength, hid_desc->if0_hid.bLength);
528 *data = (uint8_t *)&hid_desc->if0_hid;
529 break;
530 case USB_DESC_HID_REPORT:
531 LOG_DBG("Return Report Descriptor");
532
533 *len = MIN(setup->wLength, dev_data->report_size);
534 *data = (uint8_t *)dev_data->report_desc;
535 break;
536 default:
537 return -ENOTSUP;
538 }
539
540 return 0;
541 }
542
543 return -EINVAL;
544 }
545
hid_int_in(uint8_t ep,enum usb_dc_ep_cb_status_code ep_status)546 static void hid_int_in(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status)
547 {
548 struct hid_device_info *dev_data;
549 struct usb_dev_data *common;
550
551 common = usb_get_dev_data_by_ep(&usb_hid_devlist, ep);
552 if (common == NULL) {
553 LOG_WRN("Device data not found for endpoint %u", ep);
554 return;
555 }
556
557 dev_data = CONTAINER_OF(common, struct hid_device_info, common);
558
559 if (ep_status != USB_DC_EP_DATA_IN || dev_data->ops == NULL ||
560 dev_data->ops->int_in_ready == NULL) {
561 return;
562 }
563
564 dev_data->ops->int_in_ready(common->dev);
565 }
566
567 #ifdef CONFIG_ENABLE_HID_INT_OUT_EP
hid_int_out(uint8_t ep,enum usb_dc_ep_cb_status_code ep_status)568 static void hid_int_out(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status)
569 {
570 struct hid_device_info *dev_data;
571 struct usb_dev_data *common;
572
573 common = usb_get_dev_data_by_ep(&usb_hid_devlist, ep);
574 if (common == NULL) {
575 LOG_WRN("Device data not found for endpoint %u", ep);
576 return;
577 }
578
579 dev_data = CONTAINER_OF(common, struct hid_device_info, common);
580
581 if (ep_status != USB_DC_EP_DATA_OUT || dev_data->ops == NULL ||
582 dev_data->ops->int_out_ready == NULL) {
583 return;
584 }
585
586 dev_data->ops->int_out_ready(common->dev);
587 }
588 #endif
589
590 #define INITIALIZER_EP_DATA(cb, addr) \
591 { \
592 .ep_cb = cb, \
593 .ep_addr = addr, \
594 }
595
596 /* Describe Endpoints configuration */
597 #ifdef CONFIG_ENABLE_HID_INT_OUT_EP
598 #define DEFINE_HID_EP(x, _) \
599 static struct usb_ep_cfg_data hid_ep_data_##x[] = { \
600 INITIALIZER_EP_DATA(hid_int_in, AUTO_EP_IN), \
601 INITIALIZER_EP_DATA(hid_int_out, AUTO_EP_OUT), \
602 };
603 #else
604 #define DEFINE_HID_EP(x, _) \
605 static struct usb_ep_cfg_data hid_ep_data_##x[] = { \
606 INITIALIZER_EP_DATA(hid_int_in, AUTO_EP_IN), \
607 };
608 #endif
609
hid_interface_config(struct usb_desc_header * head,uint8_t bInterfaceNumber)610 static void hid_interface_config(struct usb_desc_header *head,
611 uint8_t bInterfaceNumber)
612 {
613 struct usb_if_descriptor *if_desc = (struct usb_if_descriptor *)head;
614 struct usb_hid_config *desc =
615 CONTAINER_OF(if_desc, struct usb_hid_config, if0);
616
617 LOG_DBG("");
618
619 desc->if0.bInterfaceNumber = bInterfaceNumber;
620 #ifdef CONFIG_ENABLE_HID_INT_OUT_EP
621 desc->if0.bNumEndpoints = 2;
622 #endif
623 }
624
625 #define DEFINE_HID_CFG_DATA(x, _) \
626 USBD_CFG_DATA_DEFINE(primary, hid) \
627 struct usb_cfg_data hid_config_##x = { \
628 .usb_device_description = NULL, \
629 .interface_config = hid_interface_config, \
630 .interface_descriptor = &hid_cfg_##x.if0, \
631 .cb_usb_status = hid_status_cb, \
632 .interface = { \
633 .class_handler = hid_class_handle_req, \
634 .custom_handler = hid_custom_handle_req, \
635 }, \
636 .num_endpoints = ARRAY_SIZE(hid_ep_data_##x), \
637 .endpoint = hid_ep_data_##x, \
638 };
639
usb_hid_set_proto_code(const struct device * dev,uint8_t proto_code)640 int usb_hid_set_proto_code(const struct device *dev, uint8_t proto_code)
641 {
642 const struct usb_cfg_data *cfg = dev->config;
643 struct usb_if_descriptor *if_desc = cfg->interface_descriptor;
644
645 if (IS_ENABLED(CONFIG_USB_HID_BOOT_PROTOCOL)) {
646 if_desc->bInterfaceProtocol = proto_code;
647 return 0;
648 }
649
650 return -ENOTSUP;
651 }
652
usb_hid_init(const struct device * dev)653 int usb_hid_init(const struct device *dev)
654 {
655 struct usb_cfg_data *cfg = (void *)dev->config;
656 struct hid_device_info *dev_data = dev->data;
657
658 LOG_DBG("Initializing HID Device: dev %p", dev);
659
660 /*
661 * Modify Report Descriptor Size
662 */
663 usb_set_hid_report_size(cfg, dev_data->report_size);
664
665 return 0;
666 }
667
usb_hid_register_device(const struct device * dev,const uint8_t * desc,size_t size,const struct hid_ops * ops)668 void usb_hid_register_device(const struct device *dev, const uint8_t *desc,
669 size_t size, const struct hid_ops *ops)
670 {
671 struct hid_device_info *dev_data = dev->data;
672
673 dev_data->report_desc = desc;
674 dev_data->report_size = size;
675
676 dev_data->ops = ops;
677 dev_data->common.dev = dev;
678
679 sys_slist_append(&usb_hid_devlist, &dev_data->common.node);
680
681 LOG_DBG("Added dev_data %p dev %p to devlist %p", dev_data, dev,
682 &usb_hid_devlist);
683 }
684
hid_int_ep_write(const struct device * dev,const uint8_t * data,uint32_t data_len,uint32_t * bytes_ret)685 int hid_int_ep_write(const struct device *dev, const uint8_t *data, uint32_t data_len,
686 uint32_t *bytes_ret)
687 {
688 const struct usb_cfg_data *cfg = dev->config;
689 struct hid_device_info *hid_dev_data = dev->data;
690
691 if (hid_dev_data->configured && !hid_dev_data->suspended) {
692 return usb_write(cfg->endpoint[HID_INT_IN_EP_IDX].ep_addr, data,
693 data_len, bytes_ret);
694 } else {
695 LOG_WRN("Device is not configured");
696 return -EAGAIN;
697 }
698
699 }
700
hid_int_ep_read(const struct device * dev,uint8_t * data,uint32_t max_data_len,uint32_t * ret_bytes)701 int hid_int_ep_read(const struct device *dev, uint8_t *data, uint32_t max_data_len,
702 uint32_t *ret_bytes)
703 {
704 #ifdef CONFIG_ENABLE_HID_INT_OUT_EP
705 const struct usb_cfg_data *cfg = dev->config;
706
707 return usb_read(cfg->endpoint[HID_INT_OUT_EP_IDX].ep_addr,
708 data, max_data_len, ret_bytes);
709 #else
710 return -ENOTSUP;
711 #endif
712 }
713
714 static const struct usb_hid_device_api {
715 void (*init)(void);
716 } hid_api;
717
usb_hid_device_init(const struct device * dev)718 static int usb_hid_device_init(const struct device *dev)
719 {
720 LOG_DBG("Init HID Device: dev %p (%s)", dev, dev->name);
721
722 return 0;
723 }
724
725 #define DEFINE_HID_DEV_DATA(x, _) \
726 struct hid_device_info usb_hid_dev_data_##x;
727
728 #define DEFINE_HID_DEVICE(x, _) \
729 DEVICE_DEFINE(usb_hid_device_##x, \
730 CONFIG_USB_HID_DEVICE_NAME "_" #x, \
731 &usb_hid_device_init, \
732 NULL, \
733 &usb_hid_dev_data_##x, \
734 &hid_config_##x, POST_KERNEL, \
735 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
736 &hid_api);
737
738 UTIL_LISTIFY(CONFIG_USB_HID_DEVICE_COUNT, DEFINE_HID_DESCR, _)
739 UTIL_LISTIFY(CONFIG_USB_HID_DEVICE_COUNT, DEFINE_HID_EP, _)
740 UTIL_LISTIFY(CONFIG_USB_HID_DEVICE_COUNT, DEFINE_HID_CFG_DATA, _)
741 UTIL_LISTIFY(CONFIG_USB_HID_DEVICE_COUNT, DEFINE_HID_DEV_DATA, _)
742 UTIL_LISTIFY(CONFIG_USB_HID_DEVICE_COUNT, DEFINE_HID_DEVICE, _)
743