1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief USBD HID device API header
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_USBD_HID_CLASS_DEVICE_H_
13 #define ZEPHYR_INCLUDE_USBD_HID_CLASS_DEVICE_H_
14 
15 #include <stdint.h>
16 #include <zephyr/device.h>
17 #include <zephyr/usb/class/hid.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /**
24  * @brief USBD HID Device API
25  * @defgroup usbd_hid_device USBD HID device API
26  * @ingroup usb
27  * @since 3.7
28  * @version 0.1.0
29  * @{
30  */
31 
32 /*
33  * HID Device overview:
34  *
35  *         +---------------------+
36  *         |                     |
37  *         |                     |
38  *         |     HID Device      |
39  *         |  User "top half"    |
40  *         |  of the device that +-------+
41  *         |  deals with input   |       |
42  *         |     sampling        |       |
43  *         |                     |       |
44  *         |                     |       |
45  *         | ------------------- |       |
46  *         |                     |       |
47  *         |   HID Device user   |       |
48  *         |      callbacks      |       |
49  *         |      handlers       |       |
50  *         +---------------------+       |
51  *                    ^                  |  HID Device Driver API:
52  *                    |                  |
53  *  set_protocol()    |                  |  hid_device_register()
54  *  get_report()      |                  |  hid_device_submit_report(
55  *  ....              |                  |  ...
56  *                    v                  |
57  *         +---------------------+       |
58  *         |                     |       |
59  *         |      HID Device     |       |
60  *         |     "bottom half"   |<------+
61  *         |    USB HID class    |
62  *         |    implementation   |
63  *         |                     |
64  *         |                     |
65  *         +---------------------+
66  *                    ^
67  *                    v
68  *          +--------------------+
69  *          |                    |
70  *          |     USB Device     |
71  *          |       Support      |
72  *          |                    |
73  *          +--------------------+
74  */
75 
76 /** HID report types
77  * Report types used in Get/Set Report requests.
78  */
79 enum {
80 	HID_REPORT_TYPE_INPUT = 1,
81 	HID_REPORT_TYPE_OUTPUT,
82 	HID_REPORT_TYPE_FEATURE,
83 };
84 
85 /**
86  * @brief HID device user callbacks
87  *
88  * Each device depends on a user part that handles feature, input, and output
89  * report processing according to the device functionality described by the
90  * report descriptor. Which callbacks must be implemented depends on the device
91  * functionality. The USB device part of the HID device, cannot interpret
92  * device specific report descriptor and only handles USB specific parts,
93  * transfers and validation of requests, all reports are opaque to it.
94  * Callbacks are called from the USB device stack thread and must not block.
95  */
96 struct hid_device_ops {
97 	/**
98 	 * The interface ready callback is called with the ready argument set
99 	 * to true when the corresponding interface is part of the active
100 	 * configuration and the device can e.g. begin submitting input
101 	 * reports, and with the argument set to false when the interface is no
102 	 * longer active. This callback is optional.
103 	 */
104 	void (*iface_ready)(const struct device *dev, const bool ready);
105 
106 	/**
107 	 * This callback is called for the HID Get Report request to get a
108 	 * feature, input, or output report, which is specified by the argument
109 	 * type. If there is no report ID in the report descriptor, the id
110 	 * argument is zero. The callback implementation must check the
111 	 * arguments, such as whether the report type is supported and the
112 	 * report length, and return a negative value to indicate an
113 	 * unsupported type or an error, or return the length of the report
114 	 * written to the buffer.
115 	 */
116 	int (*get_report)(const struct device *dev,
117 			  const uint8_t type, const uint8_t id,
118 			  const uint16_t len, uint8_t *const buf);
119 
120 	/**
121 	 * This callback is called for the HID Set Report request to set a
122 	 * feature, input, or output report, which is specified by the argument
123 	 * type. If there is no report ID in the report descriptor, the id
124 	 * argument is zero. The callback implementation must check the
125 	 * arguments, such as whether the report type is supported, and return
126 	 * a nonzero value to indicate an unsupported type or an error.
127 	 */
128 	int (*set_report)(const struct device *dev,
129 			  const uint8_t type, const uint8_t id,
130 			  const uint16_t len, const uint8_t *const buf);
131 
132 	/**
133 	 * Notification to limit input report frequency.
134 	 * The device should mute an input report submission until a new
135 	 * event occurs or until the time specified by the duration value has
136 	 * elapsed. If a report ID is used in the report descriptor, the
137 	 * device must store the duration and handle the specified report
138 	 * accordingly. Duration time resolution is in milliseconds.
139 	 */
140 	void (*set_idle)(const struct device *dev,
141 			 const uint8_t id, const uint32_t duration);
142 
143 	/**
144 	 * If a report ID is used in the report descriptor, the device
145 	 * must implement this callback and return the duration for the
146 	 * specified report ID. Duration time resolution is in milliseconds.
147 	 */
148 	uint32_t (*get_idle)(const struct device *dev, const uint8_t id);
149 
150 	/**
151 	 * Notification that the host has changed the protocol from
152 	 * Boot Protocol(0) to Report Protocol(1) or vice versa.
153 	 */
154 	void (*set_protocol)(const struct device *dev, const uint8_t proto);
155 
156 	/**
157 	 * Notification that input report submitted with
158 	 * hid_device_submit_report() has been sent.
159 	 * If the device does not use the callback, hid_device_submit_report()
160 	 * will be processed synchronously.
161 	 */
162 	void (*input_report_done)(const struct device *dev);
163 
164 	/**
165 	 * New output report callback. Callback will only be called for reports
166 	 * received through the optional interrupt OUT pipe. If there is no
167 	 * interrupt OUT pipe, output reports will be received using set_report().
168 	 * If a report ID is used in the report descriptor, the host places the ID
169 	 * in the buffer first, followed by the report data.
170 	 */
171 	void (*output_report)(const struct device *dev, const uint16_t len,
172 			      const uint8_t *const buf);
173 	/**
174 	 * Optional Start of Frame (SoF) event callback.
175 	 * There will always be software and hardware dependent jitter and
176 	 * latency. This should be used very carefully, it should not block
177 	 * and the execution time should be quite short.
178 	 */
179 	void (*sof)(const struct device *dev);
180 };
181 
182 /**
183  * @brief Register HID device report descriptor and user callbacks
184  *
185  * The device must register report descriptor and user callbacks before
186  * USB device support is initialized and enabled.
187  *
188  * @param[in]  dev   Pointer to HID device
189  * @param[in]  rdesc Pointer to HID report descriptor
190  * @param[in]  rsize Size of HID report descriptor
191  * @param[in]  ops   Pointer to HID device callbacks
192  */
193 int hid_device_register(const struct device *dev,
194 			const uint8_t *const rdesc, const uint16_t rsize,
195 			const struct hid_device_ops *const ops);
196 
197 /**
198  * @brief Submit new input report
199  *
200  * Submit a new input report to be sent via the interrupt IN pipe. If sync is
201  * true, the functions will block until the report is sent.
202  * If the device does not provide input_report_done() callback,
203  * hid_device_submit_report() will be processed synchronously.
204  *
205  * @param[in] dev    Pointer to HID device
206  * @param[in] size   Size of the input report
207  * @param[in] report Input report buffer. Report buffer must be aligned.
208  *
209  * @return 0 on success, negative errno code on fail.
210  */
211 int hid_device_submit_report(const struct device *dev,
212 			     const uint16_t size, const uint8_t *const report);
213 
214 /**
215  * @}
216  */
217 
218 #ifdef __cplusplus
219 }
220 #endif
221 
222 #endif /* ZEPHYR_INCLUDE_USBD_HID_CLASS_DEVICE_H_ */
223