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