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