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