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