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