1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT zephyr_hid_device
8
9 #include "usbd_hid_internal.h"
10
11 #include <stdlib.h>
12 #include <assert.h>
13 #include <zephyr/device.h>
14 #include <zephyr/devicetree.h>
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/usb/usbd.h>
17 #include <zephyr/usb/class/usbd_hid.h>
18 #include <zephyr/drivers/usb/udc.h>
19
20 #include <zephyr/logging/log.h>
21 LOG_MODULE_REGISTER(usbd_hid, CONFIG_USBD_HID_LOG_LEVEL);
22
23 #define HID_GET_IDLE_DURATION(wValue) ((wValue) >> 8)
24 #define HID_GET_IDLE_ID(wValue) (wValue)
25 #define HID_GET_REPORT_TYPE(wValue) ((wValue) >> 8)
26 #define HID_GET_REPORT_ID(wValue) (wValue)
27
28 #define HID_SUBORDINATE_DESC_NUM 1
29
30 struct subordinate_info {
31 uint8_t bDescriptorType;
32 uint16_t wDescriptorLength;
33 } __packed;
34
35 /* See HID spec. 6.2 Class-Specific Descriptors */
36 struct hid_descriptor {
37 uint8_t bLength;
38 uint8_t bDescriptorType;
39 uint16_t bcdHID;
40 uint8_t bCountryCode;
41 uint8_t bNumDescriptors;
42 /* At least report subordinate descriptor is required. */
43 struct subordinate_info sub[HID_SUBORDINATE_DESC_NUM];
44 } __packed;
45
46 struct usbd_hid_descriptor {
47 struct usb_if_descriptor if0;
48 struct hid_descriptor hid;
49 struct usb_ep_descriptor in_ep;
50 struct usb_ep_descriptor hs_in_ep;
51 struct usb_ep_descriptor out_ep;
52 struct usb_ep_descriptor hs_out_ep;
53
54 struct usb_if_descriptor if0_1;
55 struct usb_ep_descriptor alt_hs_in_ep;
56 struct usb_ep_descriptor alt_hs_out_ep;
57 };
58
59 enum {
60 HID_DEV_CLASS_ENABLED,
61 };
62
63 struct hid_device_config {
64 struct usbd_hid_descriptor *desc;
65 struct usbd_class_data *c_data;
66 struct net_buf_pool *pool_out;
67 struct net_buf_pool *pool_in;
68 const struct usb_desc_header **fs_desc;
69 const struct usb_desc_header **hs_desc;
70 };
71
72 struct hid_device_data {
73 const struct device *dev;
74 const struct hid_device_ops *ops;
75 const uint8_t *rdesc;
76 size_t rsize;
77 atomic_t state;
78 struct k_sem in_sem;
79 struct k_work output_work;
80 uint8_t idle_rate;
81 uint8_t protocol;
82 };
83
hid_get_in_ep(struct usbd_class_data * const c_data)84 static inline uint8_t hid_get_in_ep(struct usbd_class_data *const c_data)
85 {
86 const struct device *dev = usbd_class_get_private(c_data);
87 const struct hid_device_config *dcfg = dev->config;
88 struct usbd_hid_descriptor *desc = dcfg->desc;
89
90 return desc->in_ep.bEndpointAddress;
91 }
92
hid_get_out_ep(struct usbd_class_data * const c_data)93 static inline uint8_t hid_get_out_ep(struct usbd_class_data *const c_data)
94 {
95 const struct device *dev = usbd_class_get_private(c_data);
96 const struct hid_device_config *dcfg = dev->config;
97 struct usbd_hid_descriptor *desc = dcfg->desc;
98
99 return desc->out_ep.bEndpointAddress;
100 }
101
usbd_hid_request(struct usbd_class_data * const c_data,struct net_buf * const buf,const int err)102 static int usbd_hid_request(struct usbd_class_data *const c_data,
103 struct net_buf *const buf, const int err)
104 {
105 struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
106 const struct device *dev = usbd_class_get_private(c_data);
107 struct hid_device_data *ddata = dev->data;
108 const struct hid_device_ops *ops = ddata->ops;
109 struct udc_buf_info *bi;
110
111 bi = udc_get_buf_info(buf);
112
113 if (bi->ep == hid_get_out_ep(c_data)) {
114 if (ops->output_report != NULL) {
115 if (err == 0) {
116 ops->output_report(dev, buf->len, buf->data);
117 }
118
119 k_work_submit(&ddata->output_work);
120 }
121 }
122
123 if (bi->ep == hid_get_in_ep(c_data)) {
124 if (ops->input_report_done != NULL) {
125 ops->input_report_done(dev);
126 } else {
127 k_sem_give(&ddata->in_sem);
128 }
129 }
130
131 return usbd_ep_buf_free(uds_ctx, buf);
132 }
133
handle_set_idle(const struct device * dev,const struct usb_setup_packet * const setup)134 static int handle_set_idle(const struct device *dev,
135 const struct usb_setup_packet *const setup)
136 {
137 const uint32_t duration = HID_GET_IDLE_DURATION(setup->wValue);
138 const uint8_t id = HID_GET_IDLE_ID(setup->wValue);
139 struct hid_device_data *const ddata = dev->data;
140 const struct hid_device_ops *ops = ddata->ops;
141
142 if (id == 0U) {
143 /* Only the common idle rate is stored. */
144 ddata->idle_rate = duration;
145 }
146
147 if (ops->set_idle != NULL) {
148 ops->set_idle(dev, id, duration * 4UL);
149 } else {
150 errno = -ENOTSUP;
151 }
152
153 LOG_DBG("Set Idle, Report ID %u Duration %u", id, duration);
154
155 return 0;
156 }
157
handle_get_idle(const struct device * dev,const struct usb_setup_packet * const setup,struct net_buf * const buf)158 static int handle_get_idle(const struct device *dev,
159 const struct usb_setup_packet *const setup,
160 struct net_buf *const buf)
161 {
162 const uint8_t id = HID_GET_IDLE_ID(setup->wValue);
163 struct hid_device_data *const ddata = dev->data;
164 const struct hid_device_ops *ops = ddata->ops;
165 uint32_t duration;
166
167 if (setup->wLength != 1U) {
168 errno = -ENOTSUP;
169 return 0;
170 }
171
172 /*
173 * There is no Get Idle callback in the leagacy API, do not issue a
174 * protocol error if no callback is provided but ID is 0.
175 */
176 if (id != 0U && ops->get_idle == NULL) {
177 errno = -ENOTSUP;
178 return 0;
179 }
180
181 if (id == 0U) {
182 /* Only the common idle rate is stored. */
183 duration = ddata->idle_rate;
184 } else {
185 duration = ops->get_idle(dev, id) / 4UL;
186 }
187
188 LOG_DBG("Get Idle, Report ID %u Duration %u", id, duration);
189 net_buf_add_u8(buf, duration);
190
191 return 0;
192 }
193
handle_set_report(const struct device * dev,const struct usb_setup_packet * const setup,const struct net_buf * const buf)194 static int handle_set_report(const struct device *dev,
195 const struct usb_setup_packet *const setup,
196 const struct net_buf *const buf)
197 {
198 const uint8_t type = HID_GET_REPORT_TYPE(setup->wValue);
199 const uint8_t id = HID_GET_REPORT_ID(setup->wValue);
200 struct hid_device_data *const ddata = dev->data;
201 const struct hid_device_ops *ops = ddata->ops;
202
203 if (ops->set_report == NULL) {
204 errno = -ENOTSUP;
205 LOG_DBG("Set Report not supported");
206 return 0;
207 }
208
209 switch (type) {
210 case HID_REPORT_TYPE_INPUT:
211 LOG_DBG("Set Report, Input Report ID %u", id);
212 errno = ops->set_report(dev, type, id, buf->len, buf->data);
213 break;
214 case HID_REPORT_TYPE_OUTPUT:
215 LOG_DBG("Set Report, Output Report ID %u", id);
216 errno = ops->set_report(dev, type, id, buf->len, buf->data);
217 break;
218 case HID_REPORT_TYPE_FEATURE:
219 LOG_DBG("Set Report, Feature Report ID %u", id);
220 errno = ops->set_report(dev, type, id, buf->len, buf->data);
221 break;
222 default:
223 errno = -ENOTSUP;
224 break;
225 }
226
227 return 0;
228 }
229
handle_get_report(const struct device * dev,const struct usb_setup_packet * const setup,struct net_buf * const buf)230 static int handle_get_report(const struct device *dev,
231 const struct usb_setup_packet *const setup,
232 struct net_buf *const buf)
233 {
234 const uint8_t type = HID_GET_REPORT_TYPE(setup->wValue);
235 const uint8_t id = HID_GET_REPORT_ID(setup->wValue);
236 struct hid_device_data *const ddata = dev->data;
237 const struct hid_device_ops *ops = ddata->ops;
238 const size_t size = setup->wLength;
239 int ret = 0;
240
241 switch (type) {
242 case HID_REPORT_TYPE_INPUT:
243 LOG_DBG("Get Report, Input Report ID %u", id);
244 ret = ops->get_report(dev, type, id, size, buf->data);
245 break;
246 case HID_REPORT_TYPE_OUTPUT:
247 LOG_DBG("Get Report, Output Report ID %u", id);
248 ret = ops->get_report(dev, type, id, size, buf->data);
249 break;
250 case HID_REPORT_TYPE_FEATURE:
251 LOG_DBG("Get Report, Feature Report ID %u", id);
252 ret = ops->get_report(dev, type, id, size, buf->data);
253 break;
254 default:
255 errno = -ENOTSUP;
256 break;
257 }
258
259 if (ret > 0) {
260 __ASSERT(ret <= net_buf_tailroom(buf),
261 "Buffer overflow in the HID driver");
262 net_buf_add(buf, MIN(net_buf_tailroom(buf), ret));
263 } else {
264 errno = ret ? ret : -ENOTSUP;
265 }
266
267 return 0;
268 }
269
handle_set_protocol(const struct device * dev,const struct usb_setup_packet * const setup)270 static int handle_set_protocol(const struct device *dev,
271 const struct usb_setup_packet *const setup)
272 {
273 const struct hid_device_config *dcfg = dev->config;
274 struct hid_device_data *const ddata = dev->data;
275 struct usbd_hid_descriptor *const desc = dcfg->desc;
276 const struct hid_device_ops *const ops = ddata->ops;
277 const uint16_t protocol = setup->wValue;
278
279 if (protocol > HID_PROTOCOL_REPORT) {
280 /* Can only be 0 (Boot Protocol) or 1 (Report Protocol). */
281 errno = -ENOTSUP;
282 return 0;
283 }
284
285 if (desc->if0.bInterfaceSubClass == 0) {
286 /*
287 * The device does not support the boot protocol and we will
288 * not notify it.
289 */
290 errno = -ENOTSUP;
291 return 0;
292 }
293
294 LOG_DBG("Set Protocol: %s", protocol ? "Report" : "Boot");
295
296 if (ddata->protocol != protocol) {
297 ddata->protocol = protocol;
298
299 if (ops->set_protocol) {
300 ops->set_protocol(dev, protocol);
301 }
302 }
303
304 return 0;
305 }
306
handle_get_protocol(const struct device * dev,const struct usb_setup_packet * const setup,struct net_buf * const buf)307 static int handle_get_protocol(const struct device *dev,
308 const struct usb_setup_packet *const setup,
309 struct net_buf *const buf)
310 {
311 const struct hid_device_config *dcfg = dev->config;
312 struct hid_device_data *const ddata = dev->data;
313 struct usbd_hid_descriptor *const desc = dcfg->desc;
314
315 if (setup->wValue != 0 || setup->wLength != 1) {
316 errno = -ENOTSUP;
317 return 0;
318 }
319
320 if (desc->if0.bInterfaceSubClass == 0) {
321 /* The device does not support the boot protocol */
322 errno = -ENOTSUP;
323 return 0;
324 }
325
326 LOG_DBG("Get Protocol: %s", ddata->protocol ? "Report" : "Boot");
327 net_buf_add_u8(buf, ddata->protocol);
328
329 return 0;
330 }
331
handle_get_descriptor(const struct device * dev,const struct usb_setup_packet * const setup,struct net_buf * const buf)332 static int handle_get_descriptor(const struct device *dev,
333 const struct usb_setup_packet *const setup,
334 struct net_buf *const buf)
335 {
336 const struct hid_device_config *dcfg = dev->config;
337 struct hid_device_data *const ddata = dev->data;
338 uint8_t desc_type = USB_GET_DESCRIPTOR_TYPE(setup->wValue);
339 uint8_t desc_idx = USB_GET_DESCRIPTOR_INDEX(setup->wValue);
340 struct usbd_hid_descriptor *const desc = dcfg->desc;
341
342 switch (desc_type) {
343 case USB_DESC_HID_REPORT:
344 LOG_DBG("Get descriptor report");
345 net_buf_add_mem(buf, ddata->rdesc, MIN(ddata->rsize, setup->wLength));
346 break;
347 case USB_DESC_HID:
348 LOG_DBG("Get descriptor HID");
349 net_buf_add_mem(buf, &desc->hid, MIN(desc->hid.bLength, setup->wLength));
350 break;
351 case USB_DESC_HID_PHYSICAL:
352 LOG_DBG("Get descriptor physical %u", desc_idx);
353 errno = -ENOTSUP;
354 break;
355 default:
356 errno = -ENOTSUP;
357 break;
358 }
359
360 return 0;
361 }
362
usbd_hid_ctd(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,const struct net_buf * const buf)363 static int usbd_hid_ctd(struct usbd_class_data *const c_data,
364 const struct usb_setup_packet *const setup,
365 const struct net_buf *const buf)
366 {
367 const struct device *dev = usbd_class_get_private(c_data);
368 int ret = 0;
369
370 switch (setup->bRequest) {
371 case USB_HID_SET_IDLE:
372 ret = handle_set_idle(dev, setup);
373 break;
374 case USB_HID_SET_REPORT:
375 ret = handle_set_report(dev, setup, buf);
376 break;
377 case USB_HID_SET_PROTOCOL:
378 ret = handle_set_protocol(dev, setup);
379 break;
380 default:
381 errno = -ENOTSUP;
382 break;
383 }
384
385 return ret;
386 }
387
usbd_hid_cth(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,struct net_buf * const buf)388 static int usbd_hid_cth(struct usbd_class_data *const c_data,
389 const struct usb_setup_packet *const setup,
390 struct net_buf *const buf)
391 {
392 const struct device *dev = usbd_class_get_private(c_data);
393 int ret = 0;
394
395 switch (setup->bRequest) {
396 case USB_HID_GET_IDLE:
397 ret = handle_get_idle(dev, setup, buf);
398 break;
399 case USB_HID_GET_REPORT:
400 ret = handle_get_report(dev, setup, buf);
401 break;
402 case USB_HID_GET_PROTOCOL:
403 ret = handle_get_protocol(dev, setup, buf);
404 break;
405 case USB_SREQ_GET_DESCRIPTOR:
406 ret = handle_get_descriptor(dev, setup, buf);
407 break;
408 default:
409 errno = -ENOTSUP;
410 break;
411 }
412
413 return ret;
414 }
415
usbd_hid_sof(struct usbd_class_data * const c_data)416 static void usbd_hid_sof(struct usbd_class_data *const c_data)
417 {
418 const struct device *dev = usbd_class_get_private(c_data);
419 struct hid_device_data *ddata = dev->data;
420 const struct hid_device_ops *const ops = ddata->ops;
421
422 if (ops->sof) {
423 ops->sof(dev);
424 }
425 }
426
usbd_hid_enable(struct usbd_class_data * const c_data)427 static void usbd_hid_enable(struct usbd_class_data *const c_data)
428 {
429 const struct device *dev = usbd_class_get_private(c_data);
430 const struct hid_device_config *dcfg = dev->config;
431 struct hid_device_data *ddata = dev->data;
432 const struct hid_device_ops *const ops = ddata->ops;
433 struct usbd_hid_descriptor *const desc = dcfg->desc;
434
435 atomic_set_bit(&ddata->state, HID_DEV_CLASS_ENABLED);
436 ddata->protocol = HID_PROTOCOL_REPORT;
437 if (ops->iface_ready) {
438 ops->iface_ready(dev, true);
439 }
440
441 if (desc->out_ep.bLength != 0U) {
442 k_work_submit(&ddata->output_work);
443 }
444
445 LOG_DBG("Configuration enabled");
446 }
447
usbd_hid_disable(struct usbd_class_data * const c_data)448 static void usbd_hid_disable(struct usbd_class_data *const c_data)
449 {
450 const struct device *dev = usbd_class_get_private(c_data);
451 struct hid_device_data *ddata = dev->data;
452 const struct hid_device_ops *const ops = ddata->ops;
453
454 atomic_clear_bit(&ddata->state, HID_DEV_CLASS_ENABLED);
455 if (ops->iface_ready) {
456 ops->iface_ready(dev, false);
457 }
458
459 LOG_DBG("Configuration disabled");
460 }
461
usbd_hid_suspended(struct usbd_class_data * const c_data)462 static void usbd_hid_suspended(struct usbd_class_data *const c_data)
463 {
464 const struct device *dev = usbd_class_get_private(c_data);
465
466 LOG_DBG("Configuration suspended, device %s", dev->name);
467 }
468
usbd_hid_resumed(struct usbd_class_data * const c_data)469 static void usbd_hid_resumed(struct usbd_class_data *const c_data)
470 {
471 const struct device *dev = usbd_class_get_private(c_data);
472
473 LOG_DBG("Configuration resumed, device %s", dev->name);
474 }
475
usbd_hid_get_desc(struct usbd_class_data * const c_data,const enum usbd_speed speed)476 static void *usbd_hid_get_desc(struct usbd_class_data *const c_data,
477 const enum usbd_speed speed)
478 {
479 const struct device *dev = usbd_class_get_private(c_data);
480 const struct hid_device_config *dcfg = dev->config;
481
482 if (speed == USBD_SPEED_HS) {
483 return dcfg->hs_desc;
484 }
485
486 return dcfg->fs_desc;
487 }
488
usbd_hid_init(struct usbd_class_data * const c_data)489 static int usbd_hid_init(struct usbd_class_data *const c_data)
490 {
491 LOG_DBG("HID class %s init", c_data->name);
492
493 return 0;
494 }
495
usbd_hid_shutdown(struct usbd_class_data * const c_data)496 static void usbd_hid_shutdown(struct usbd_class_data *const c_data)
497 {
498 LOG_DBG("HID class %s shutdown", c_data->name);
499 }
500
hid_buf_alloc_ext(const struct hid_device_config * const dcfg,const uint16_t size,void * const data,const uint8_t ep)501 static struct net_buf *hid_buf_alloc_ext(const struct hid_device_config *const dcfg,
502 const uint16_t size, void *const data,
503 const uint8_t ep)
504 {
505 struct net_buf *buf = NULL;
506 struct udc_buf_info *bi;
507
508 __ASSERT(IS_UDC_ALIGNED(data), "Application provided unaligned buffer");
509
510 buf = net_buf_alloc_with_data(dcfg->pool_in, data, size, K_NO_WAIT);
511 if (!buf) {
512 return NULL;
513 }
514
515 bi = udc_get_buf_info(buf);
516 bi->ep = ep;
517
518 return buf;
519 }
520
hid_buf_alloc(const struct hid_device_config * const dcfg,const uint8_t ep)521 static struct net_buf *hid_buf_alloc(const struct hid_device_config *const dcfg,
522 const uint8_t ep)
523 {
524 struct net_buf *buf = NULL;
525 struct udc_buf_info *bi;
526
527 buf = net_buf_alloc(dcfg->pool_out, K_NO_WAIT);
528 if (!buf) {
529 return NULL;
530 }
531
532 bi = udc_get_buf_info(buf);
533 bi->ep = ep;
534
535 return buf;
536 }
537
hid_dev_output_handler(struct k_work * work)538 static void hid_dev_output_handler(struct k_work *work)
539 {
540 struct hid_device_data *ddata = CONTAINER_OF(work,
541 struct hid_device_data,
542 output_work);
543 const struct device *dev = ddata->dev;
544 const struct hid_device_config *dcfg = dev->config;
545 struct usbd_class_data *c_data = dcfg->c_data;
546 struct net_buf *buf;
547
548 if (!atomic_test_bit(&ddata->state, HID_DEV_CLASS_ENABLED)) {
549 return;
550 }
551
552 buf = hid_buf_alloc(dcfg, hid_get_out_ep(c_data));
553 if (buf == NULL) {
554 LOG_ERR("Failed to allocate buffer");
555 return;
556 }
557
558 if (usbd_ep_enqueue(c_data, buf)) {
559 net_buf_unref(buf);
560 LOG_ERR("Failed to enqueue buffer");
561 }
562 }
563
hid_dev_submit_report(const struct device * dev,const uint16_t size,const uint8_t * const report)564 static int hid_dev_submit_report(const struct device *dev,
565 const uint16_t size, const uint8_t *const report)
566 {
567 const struct hid_device_config *dcfg = dev->config;
568 struct hid_device_data *const ddata = dev->data;
569 const struct hid_device_ops *ops = ddata->ops;
570 struct usbd_class_data *c_data = dcfg->c_data;
571 struct net_buf *buf;
572 int ret;
573
574 __ASSERT(IS_ALIGNED(report, sizeof(void *)), "Report buffer is not aligned");
575
576 if (!atomic_test_bit(&ddata->state, HID_DEV_CLASS_ENABLED)) {
577 return -EACCES;
578 }
579
580 buf = hid_buf_alloc_ext(dcfg, size, (void *)report, hid_get_in_ep(c_data));
581 if (buf == NULL) {
582 LOG_ERR("Failed to allocate net_buf");
583 return -ENOMEM;
584 }
585
586 ret = usbd_ep_enqueue(c_data, buf);
587 if (ret) {
588 net_buf_unref(buf);
589 return ret;
590 }
591
592 if (ops->input_report_done == NULL) {
593 k_sem_take(&ddata->in_sem, K_FOREVER);
594 }
595
596 return 0;
597 }
598
hid_dev_register(const struct device * dev,const uint8_t * const rdesc,const uint16_t rsize,const struct hid_device_ops * const ops)599 static int hid_dev_register(const struct device *dev,
600 const uint8_t *const rdesc, const uint16_t rsize,
601 const struct hid_device_ops *const ops)
602 {
603 const struct hid_device_config *dcfg = dev->config;
604 struct hid_device_data *const ddata = dev->data;
605 struct usbd_hid_descriptor *const desc = dcfg->desc;
606
607 if (atomic_test_bit(&ddata->state, HID_DEV_CLASS_ENABLED)) {
608 return -EALREADY;
609 }
610
611 /* Get Report is required for all HID device types. */
612 if (ops == NULL || ops->get_report == NULL) {
613 LOG_ERR("get_report callback is missing");
614 return -EINVAL;
615 }
616
617 /* Set Report is required when an output report is declared. */
618 if (desc->out_ep.bLength && ops->set_report == NULL) {
619 LOG_ERR("set_report callback is missing");
620 return -EINVAL;
621 }
622
623 /*
624 * Get/Set Protocol are required when device supports boot interface.
625 * Get Protocol is handled internally, no callback is required.
626 */
627 if (desc->if0.bInterfaceSubClass && ops->set_protocol == NULL) {
628 LOG_ERR("set_protocol callback is missing");
629 return -EINVAL;
630 }
631
632 ddata->rdesc = rdesc;
633 ddata->rsize = rsize;
634 ddata->ops = ops;
635
636 sys_put_le16(ddata->rsize, (uint8_t *)&(desc->hid.sub[0].wDescriptorLength));
637
638 return 0;
639 }
640
hid_device_init(const struct device * dev)641 static int hid_device_init(const struct device *dev)
642 {
643 struct hid_device_data *const ddata = dev->data;
644
645 ddata->dev = dev;
646
647 k_sem_init(&ddata->in_sem, 0, 1);
648
649 k_work_init(&ddata->output_work, hid_dev_output_handler);
650 LOG_DBG("HID device %s init", dev->name);
651
652 return 0;
653 }
654
655 struct usbd_class_api usbd_hid_api = {
656 .request = usbd_hid_request,
657 .update = NULL,
658 .sof = usbd_hid_sof,
659 .enable = usbd_hid_enable,
660 .disable = usbd_hid_disable,
661 .suspended = usbd_hid_suspended,
662 .resumed = usbd_hid_resumed,
663 .control_to_dev = usbd_hid_ctd,
664 .control_to_host = usbd_hid_cth,
665 .get_desc = usbd_hid_get_desc,
666 .init = usbd_hid_init,
667 .shutdown = usbd_hid_shutdown,
668 };
669
670 static const struct hid_device_driver_api hid_device_api = {
671 .submit_report = hid_dev_submit_report,
672 .dev_register = hid_dev_register,
673 };
674
675 #include "usbd_hid_macros.h"
676
677 #define USBD_HID_INTERFACE_SIMPLE_DEFINE(n) \
678 static struct usbd_hid_descriptor hid_desc_##n = { \
679 .if0 = HID_INTERFACE_DEFINE(n, 0), \
680 .hid = HID_DESCRIPTOR_DEFINE(n), \
681 .in_ep = HID_IN_EP_DEFINE(n, false, true), \
682 .hs_in_ep = HID_IN_EP_DEFINE(n, true, true), \
683 .out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, false, true), \
684 .hs_out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, true, true), \
685 }; \
686 \
687 const static struct usb_desc_header *hid_fs_desc_##n[] = { \
688 (struct usb_desc_header *) &hid_desc_##n.if0, \
689 (struct usb_desc_header *) &hid_desc_##n.hid, \
690 (struct usb_desc_header *) &hid_desc_##n.in_ep, \
691 (struct usb_desc_header *) &hid_desc_##n.out_ep, \
692 NULL, \
693 }; \
694 \
695 const static struct usb_desc_header *hid_hs_desc_##n[] = { \
696 (struct usb_desc_header *) &hid_desc_##n.if0, \
697 (struct usb_desc_header *) &hid_desc_##n.hid, \
698 (struct usb_desc_header *) &hid_desc_##n.hs_in_ep, \
699 (struct usb_desc_header *) &hid_desc_##n.hs_out_ep, \
700 NULL, \
701 }
702
703 #define USBD_HID_INTERFACE_ALTERNATE_DEFINE(n) \
704 static struct usbd_hid_descriptor hid_desc_##n = { \
705 .if0 = HID_INTERFACE_DEFINE(n, 0), \
706 .hid = HID_DESCRIPTOR_DEFINE(n), \
707 .in_ep = HID_IN_EP_DEFINE(n, false, false), \
708 .hs_in_ep = HID_IN_EP_DEFINE(n, true, false), \
709 .out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, false, false), \
710 .hs_out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, true, false), \
711 .if0_1 = HID_INTERFACE_DEFINE(n, 1), \
712 .alt_hs_in_ep = HID_IN_EP_DEFINE(n, true, true), \
713 .alt_hs_out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, true, true), \
714 }; \
715 \
716 const static struct usb_desc_header *hid_fs_desc_##n[] = { \
717 (struct usb_desc_header *) &hid_desc_##n.if0, \
718 (struct usb_desc_header *) &hid_desc_##n.hid, \
719 (struct usb_desc_header *) &hid_desc_##n.in_ep, \
720 (struct usb_desc_header *) &hid_desc_##n.out_ep, \
721 NULL, \
722 }; \
723 \
724 const static struct usb_desc_header *hid_hs_desc_##n[] = { \
725 (struct usb_desc_header *) &hid_desc_##n.if0, \
726 (struct usb_desc_header *) &hid_desc_##n.hid, \
727 (struct usb_desc_header *) &hid_desc_##n.hs_in_ep, \
728 COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \
729 ((struct usb_desc_header *) &hid_desc_##n.hs_out_ep,), ()) \
730 (struct usb_desc_header *)&hid_desc_##n.if0_1, \
731 (struct usb_desc_header *) &hid_desc_##n.hid, \
732 (struct usb_desc_header *) &hid_desc_##n.alt_hs_in_ep, \
733 COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \
734 ((struct usb_desc_header *) &hid_desc_##n.alt_hs_out_ep,), ()) \
735 NULL, \
736 }
737
738 #define USBD_HID_INTERFACE_DEFINE(n) \
739 COND_CODE_1(HID_ALL_MPS_LESS_65(n), \
740 (USBD_HID_INTERFACE_SIMPLE_DEFINE(n)), \
741 (USBD_HID_INTERFACE_ALTERNATE_DEFINE(n)))
742
743 #define USBD_HID_INSTANCE_DEFINE(n) \
744 HID_VERIFY_REPORT_SIZES(n); \
745 \
746 NET_BUF_POOL_DEFINE(hid_buf_pool_in_##n, \
747 CONFIG_USBD_HID_IN_BUF_COUNT, 0, \
748 sizeof(struct udc_buf_info), NULL); \
749 \
750 HID_OUT_POOL_DEFINE(n); \
751 USBD_HID_INTERFACE_DEFINE(n); \
752 \
753 USBD_DEFINE_CLASS(hid_##n, \
754 &usbd_hid_api, \
755 (void *)DEVICE_DT_GET(DT_DRV_INST(n)), NULL); \
756 \
757 static const struct hid_device_config hid_config_##n = { \
758 .desc = &hid_desc_##n, \
759 .c_data = &hid_##n, \
760 .pool_in = &hid_buf_pool_in_##n, \
761 .pool_out = HID_OUT_POOL_ADDR(n), \
762 .fs_desc = hid_fs_desc_##n, \
763 .hs_desc = hid_hs_desc_##n, \
764 }; \
765 \
766 static struct hid_device_data hid_data_##n; \
767 \
768 DEVICE_DT_INST_DEFINE(n, hid_device_init, NULL, \
769 &hid_data_##n, &hid_config_##n, \
770 POST_KERNEL, CONFIG_USBD_HID_INIT_PRIORITY, \
771 &hid_device_api);
772
773 DT_INST_FOREACH_STATUS_OKAY(USBD_HID_INSTANCE_DEFINE);
774