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] dev Pointer to device struct of the class instance
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_node * const node,struct net_buf * const buf,int err)29 static inline int usbd_class_request(struct usbd_class_node *const node,
30 				     struct net_buf *const buf,
31 				     int err)
32 {
33 	const struct usbd_class_api *api = node->api;
34 
35 	if (api->request != NULL) {
36 		return api->request(node, 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] dev Pointer to device struct of the class instance
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_node * const node,struct usb_setup_packet * const setup,struct net_buf * const buf)62 static inline int usbd_class_control_to_host(struct usbd_class_node *const node,
63 					     struct usb_setup_packet *const setup,
64 					     struct net_buf *const buf)
65 {
66 	const struct usbd_class_api *api = node->api;
67 
68 	if (api->control_to_host != NULL) {
69 		return api->control_to_host(node, 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] dev Pointer to device struct of the class instance
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_node * const node,struct usb_setup_packet * const setup,struct net_buf * const buf)95 static inline int usbd_class_control_to_dev(struct usbd_class_node *const node,
96 					    struct usb_setup_packet *const setup,
97 					    struct net_buf *const buf)
98 {
99 	const struct usbd_class_api *api = node->api;
100 
101 	if (api->control_to_dev != NULL) {
102 		return api->control_to_dev(node, 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] dev Pointer to device struct of the class instance
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_node * const node,const uint8_t ep,const bool halted)123 static inline void usbd_class_feature_halt(struct usbd_class_node *const node,
124 					   const uint8_t ep,
125 					   const bool halted)
126 {
127 	const struct usbd_class_api *api = node->api;
128 
129 	if (api->feature_halt != NULL) {
130 		api->feature_halt(node, 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] dev Pointer to device struct of the class instance
144  * @param[in] setup Pointer to USB setup packet
145  */
usbd_class_update(struct usbd_class_node * const node,const uint8_t iface,const uint8_t alternate)146 static inline void usbd_class_update(struct usbd_class_node *const node,
147 				     const uint8_t iface,
148 				     const uint8_t alternate)
149 {
150 	const struct usbd_class_api *api = node->api;
151 
152 	if (api->update != NULL) {
153 		api->update(node, iface, alternate);
154 	}
155 }
156 
157 /**
158  * @brief USB suspended handler
159  *
160  * @param[in] dev Pointer to device struct of the class instance
161  * @param[in] event Power management event
162  *
163  * @return 0 on success, other values on fail.
164  */
usbd_class_suspended(struct usbd_class_node * const node)165 static inline void usbd_class_suspended(struct usbd_class_node *const node)
166 {
167 	const struct usbd_class_api *api = node->api;
168 
169 	if (api->suspended != NULL) {
170 		api->suspended(node);
171 	}
172 }
173 
174 
175 /**
176  * @brief USB resumed handler
177  *
178  * @param[in] dev Pointer to device struct of the class instance
179  * @param[in] event Power management event
180  *
181  * @return 0 on success, other values on fail.
182  */
usbd_class_resumed(struct usbd_class_node * const node)183 static inline void usbd_class_resumed(struct usbd_class_node *const node)
184 {
185 	const struct usbd_class_api *api = node->api;
186 
187 	if (api->resumed != NULL) {
188 		api->resumed(node);
189 	}
190 }
191 
192 /**
193  * @brief Class associated configuration active handler
194  *
195  * @note The execution of the handler must not block.
196  *
197  * @param[in] dev Pointer to device struct of the class instance
198  */
usbd_class_enable(struct usbd_class_node * const node)199 static inline void usbd_class_enable(struct usbd_class_node *const node)
200 {
201 	const struct usbd_class_api *api = node->api;
202 
203 	if (api->enable != NULL) {
204 		api->enable(node);
205 	}
206 }
207 
208 /**
209  * @brief Class associated configuration disable handler
210  *
211  * @note The execution of the handler must not block.
212  *
213  * @param[in] dev Pointer to device struct of the class instance
214  */
usbd_class_disable(struct usbd_class_node * const node)215 static inline void usbd_class_disable(struct usbd_class_node *const node)
216 {
217 	const struct usbd_class_api *api = node->api;
218 
219 	if (api->disable != NULL) {
220 		api->disable(node);
221 	}
222 }
223 
224 /**
225  * @brief Initialization of the class implementation
226  *
227  * This is called for each instance during the initialization phase
228  * after the interface number and endpoint addresses are assigned
229  * to the corresponding instance.
230  * It can be used to initialize class specific descriptors or
231  * underlying systems.
232  *
233  * @note If this call fails the core will terminate stack initialization.
234  *
235  * @param[in] dev Pointer to device struct of the class instance
236  *
237  * @return 0 on success, other values on fail.
238  */
usbd_class_init(struct usbd_class_node * const node)239 static inline int usbd_class_init(struct usbd_class_node *const node)
240 {
241 	const struct usbd_class_api *api = node->api;
242 
243 	if (api->init != NULL) {
244 		return api->init(node);
245 	}
246 
247 	return -ENOTSUP;
248 }
249 
250 /**
251  * @brief Shutdown of the class implementation
252  *
253  * This is called for each instance during the shutdown phase.
254  *
255  * @note The execution of the handler must not block.
256  *
257  * @param[in] dev Pointer to device struct of the class instance
258  */
usbd_class_shutdown(struct usbd_class_node * const node)259 static inline void usbd_class_shutdown(struct usbd_class_node *const node)
260 {
261 	const struct usbd_class_api *api = node->api;
262 
263 	if (api->shutdown != NULL) {
264 		api->shutdown(node);
265 	}
266 }
267 
268 #endif /* ZEPHYR_INCLUDE_USBD_CLASS_API_H */
269