1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief USB device stack class instances API
10 *
11 * This file contains the USB device stack class instances API.
12 */
13
14 #ifndef ZEPHYR_INCLUDE_USBD_CLASS_API_H
15 #define ZEPHYR_INCLUDE_USBD_CLASS_API_H
16
17 #include <zephyr/usb/usbd.h>
18
19 /**
20 * @brief Endpoint request completion event handler
21 *
22 * This is the event handler for all endpoint accommodated
23 * by a class instance.
24 *
25 * @param[in] c_data Pointer to USB device class data
26 * @param[in] buf Control Request Data buffer
27 * @param[in] err Result of the transfer. 0 if the transfer was successful.
28 */
usbd_class_request(struct usbd_class_data * const c_data,struct net_buf * const buf,int err)29 static inline int usbd_class_request(struct usbd_class_data *const c_data,
30 struct net_buf *const buf,
31 int err)
32 {
33 const struct usbd_class_api *api = c_data->api;
34
35 if (api->request != NULL) {
36 return api->request(c_data, buf, err);
37 }
38
39 return -ENOTSUP;
40 }
41
42
43 /**
44 * @brief USB control request handler
45 *
46 * Common handler for all control request.
47 * Regardless requests recipient, interface or endpoint,
48 * the USB device core will identify proper class instance
49 * and call this handler.
50 * For the vendor type request USBD_VENDOR_REQ macro must be used
51 * to identify the class, if more than one class instance is
52 * present, only the first one will be called.
53 *
54 * The execution of the handler must not block.
55 *
56 * @param[in] c_data Pointer to USB device class data
57 * @param[in] setup Pointer to USB Setup Packet
58 * @param[in] buf Control Request Data buffer
59 *
60 * @return 0 on success, other values on fail.
61 */
usbd_class_control_to_host(struct usbd_class_data * const c_data,struct usb_setup_packet * const setup,struct net_buf * const buf)62 static inline int usbd_class_control_to_host(struct usbd_class_data *const c_data,
63 struct usb_setup_packet *const setup,
64 struct net_buf *const buf)
65 {
66 const struct usbd_class_api *api = c_data->api;
67
68 if (api->control_to_host != NULL) {
69 return api->control_to_host(c_data, setup, buf);
70 }
71
72 errno = -ENOTSUP;
73 return 0;
74 }
75
76 /**
77 * @brief USB control request handler
78 *
79 * Common handler for all control request.
80 * Regardless requests recipient, interface or endpoint,
81 * the USB device core will identify proper class instance
82 * and call this handler.
83 * For the vendor type request USBD_VENDOR_REQ macro must be used
84 * to identify the class, if more than one class instance is
85 * present, only the first one will be called.
86 *
87 * The execution of the handler must not block.
88 *
89 * @param[in] c_data Pointer to USB device class data
90 * @param[in] setup Pointer to USB Setup Packet
91 * @param[in] buf Control Request Data buffer
92 *
93 * @return 0 on success, other values on fail.
94 */
usbd_class_control_to_dev(struct usbd_class_data * const c_data,struct usb_setup_packet * const setup,struct net_buf * const buf)95 static inline int usbd_class_control_to_dev(struct usbd_class_data *const c_data,
96 struct usb_setup_packet *const setup,
97 struct net_buf *const buf)
98 {
99 const struct usbd_class_api *api = c_data->api;
100
101 if (api->control_to_dev != NULL) {
102 return api->control_to_dev(c_data, setup, buf);
103 }
104
105 errno = -ENOTSUP;
106 return 0;
107 }
108
109 /**
110 * @brief Feature endpoint halt update handler
111 *
112 * Called when an endpoint of the interface belonging
113 * to the instance has been halted or cleared by either
114 * a Set Feature Endpoint Halt or Clear Feature Endpoint Halt request.
115 *
116 * The execution of the handler must not block.
117 *
118 * @param[in] c_data Pointer to USB device class data
119 * @param[in] ep Endpoint
120 * @param[in] halted True if the endpoint has been halted and false if
121 * the endpoint halt has been cleared by a Feature request.
122 */
usbd_class_feature_halt(struct usbd_class_data * const c_data,const uint8_t ep,const bool halted)123 static inline void usbd_class_feature_halt(struct usbd_class_data *const c_data,
124 const uint8_t ep,
125 const bool halted)
126 {
127 const struct usbd_class_api *api = c_data->api;
128
129 if (api->feature_halt != NULL) {
130 api->feature_halt(c_data, ep, halted);
131 }
132 }
133
134 /**
135 * @brief Configuration update handler
136 *
137 * Called when the configuration of the interface belonging
138 * to the instance has been changed, either because of
139 * Set Configuration or Set Interface request.
140 *
141 * The execution of the handler must not block.
142 *
143 * @param[in] c_data Pointer to USB device class data
144 * @param[in] iface Interface
145 * @param[in] alternate Alternate setting
146 */
usbd_class_update(struct usbd_class_data * const c_data,const uint8_t iface,const uint8_t alternate)147 static inline void usbd_class_update(struct usbd_class_data *const c_data,
148 const uint8_t iface,
149 const uint8_t alternate)
150 {
151 const struct usbd_class_api *api = c_data->api;
152
153 if (api->update != NULL) {
154 api->update(c_data, iface, alternate);
155 }
156 }
157
158
159 /**
160 * @brief USB suspended handler
161 *
162 * @param[in] c_data Pointer to USB device class data
163 */
usbd_class_suspended(struct usbd_class_data * const c_data)164 static inline void usbd_class_suspended(struct usbd_class_data *const c_data)
165 {
166 const struct usbd_class_api *api = c_data->api;
167
168 if (api->suspended != NULL) {
169 api->suspended(c_data);
170 }
171 }
172
173
174 /**
175 * @brief USB resumed handler
176 *
177 * @param[in] c_data Pointer to USB device class data
178 */
usbd_class_resumed(struct usbd_class_data * const c_data)179 static inline void usbd_class_resumed(struct usbd_class_data *const c_data)
180 {
181 const struct usbd_class_api *api = c_data->api;
182
183 if (api->resumed != NULL) {
184 api->resumed(c_data);
185 }
186 }
187
188 /**
189 * @brief USB Start of Frame handler
190 *
191 * @note The execution of the handler must not block.
192 *
193 * @param[in] c_data Pointer to USB device class data
194 */
usbd_class_sof(struct usbd_class_data * const c_data)195 static inline void usbd_class_sof(struct usbd_class_data *const c_data)
196 {
197 const struct usbd_class_api *api = c_data->api;
198
199 if (api->sof != NULL) {
200 api->sof(c_data);
201 }
202 }
203
204 /**
205 * @brief Class associated configuration active handler
206 *
207 * @note The execution of the handler must not block.
208 *
209 * @param[in] c_data Pointer to USB device class data
210 */
usbd_class_enable(struct usbd_class_data * const c_data)211 static inline void usbd_class_enable(struct usbd_class_data *const c_data)
212 {
213 const struct usbd_class_api *api = c_data->api;
214
215 if (api->enable != NULL) {
216 api->enable(c_data);
217 }
218 }
219
220 /**
221 * @brief Class associated configuration disable handler
222 *
223 * @note The execution of the handler must not block.
224 *
225 * @param[in] c_data Pointer to USB device class data
226 */
usbd_class_disable(struct usbd_class_data * const c_data)227 static inline void usbd_class_disable(struct usbd_class_data *const c_data)
228 {
229 const struct usbd_class_api *api = c_data->api;
230
231 if (api->disable != NULL) {
232 api->disable(c_data);
233 }
234 }
235
236 /**
237 * @brief Initialization of the class implementation
238 *
239 * This is called for each instance during the initialization phase
240 * after the interface number and endpoint addresses are assigned
241 * to the corresponding instance.
242 * It can be used to initialize class specific descriptors or
243 * underlying systems.
244 *
245 * @note If this call fails the core will terminate stack initialization.
246 *
247 * @param[in] c_data Pointer to USB device class data
248 *
249 * @return 0 on success, other values on fail.
250 */
usbd_class_init(struct usbd_class_data * const c_data)251 static inline int usbd_class_init(struct usbd_class_data *const c_data)
252 {
253 const struct usbd_class_api *api = c_data->api;
254
255 if (api->init != NULL) {
256 return api->init(c_data);
257 }
258
259 return -ENOTSUP;
260 }
261
262 /**
263 * @brief Shutdown of the class implementation
264 *
265 * This is called for each instance during the shutdown phase.
266 *
267 * @note The execution of the handler must not block.
268 *
269 * @param[in] c_data Pointer to USB device class data
270 */
usbd_class_shutdown(struct usbd_class_data * const c_data)271 static inline void usbd_class_shutdown(struct usbd_class_data *const c_data)
272 {
273 const struct usbd_class_api *api = c_data->api;
274
275 if (api->shutdown != NULL) {
276 api->shutdown(c_data);
277 }
278 }
279
280 /**
281 * @brief Get function descriptor
282 *
283 * @param[in] c_data Pointer to USB device class data
284 * @param[in] speed For which speed descriptor is requested.
285 *
286 * @return Array of struct usb_desc_header pointers with a last element
287 * pointing to a nil descriptor on success, NULL if not available.
288 */
usbd_class_get_desc(struct usbd_class_data * const c_data,const enum usbd_speed speed)289 static inline void *usbd_class_get_desc(struct usbd_class_data *const c_data,
290 const enum usbd_speed speed)
291 {
292 const struct usbd_class_api *api = c_data->api;
293
294 if (api->get_desc != NULL) {
295 return api->get_desc(c_data, speed);
296 }
297
298 return NULL;
299 }
300
301 #endif /* ZEPHYR_INCLUDE_USBD_CLASS_API_H */
302