1 /*
2 * Copyright (c) 2021-2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Private API for USB device controller (UDC) drivers
10 */
11
12 #ifndef ZEPHYR_INCLUDE_UDC_COMMON_H
13 #define ZEPHYR_INCLUDE_UDC_COMMON_H
14
15 #include <zephyr/drivers/usb/udc.h>
16 #include <zephyr/sys/byteorder.h>
17
18 #define CTRL_PIPE_STAGE_SETUP 0
19 #define CTRL_PIPE_STAGE_DATA_OUT 1
20 #define CTRL_PIPE_STAGE_DATA_IN 2
21 #define CTRL_PIPE_STAGE_NO_DATA 3
22 #define CTRL_PIPE_STAGE_STATUS_OUT 4
23 #define CTRL_PIPE_STAGE_STATUS_IN 5
24 #define CTRL_PIPE_STAGE_ERROR 6
25
26 /**
27 * @brief Get driver's private data
28 *
29 * @param[in] dev Pointer to device struct of the driver instance
30 *
31 * @return pointer to driver's private data
32 */
udc_get_private(const struct device * dev)33 static inline void *udc_get_private(const struct device *dev)
34 {
35 struct udc_data *data = dev->data;
36
37 return data->priv;
38 }
39
40 /**
41 * @brief Helper function to set suspended status
42 *
43 * This function can be used by the driver to set suspended status
44 *
45 * @param[in] dev Pointer to device struct of the driver instance
46 * @param[in] values True to set suspended status
47 */
48 void udc_set_suspended(const struct device *dev, const bool value);
49
50 /**
51 * @brief Get pointer to endpoint configuration structure.
52 *
53 * @param[in] dev Pointer to device struct of the driver instance
54 * @param[in] ep Endpoint address
55 *
56 * @return pointer to endpoint configuration or NULL on error.
57 */
58 struct udc_ep_config *udc_get_ep_cfg(const struct device *dev,
59 const uint8_t ep);
60
61 /**
62 * @brief Checks if the endpoint is busy
63 *
64 * @param[in] ep_cfg Pointer to endpoint configuration
65 *
66 * @return true if endpoint is busy
67 */
68 bool udc_ep_is_busy(const struct udc_ep_config *const ep_cfg);
69
70 /**
71 * @brief Helper function to set endpoint busy state
72 *
73 * @param[in] ep_cfg Pointer to endpoint configuration
74 * @param[in] busy Busy state
75 */
76 void udc_ep_set_busy(struct udc_ep_config *const ep_cfg,
77 const bool busy);
78
79 /**
80 * @brief Get UDC request from endpoint FIFO.
81 *
82 * This function removes request from endpoint FIFO.
83 * Use it when transfer is finished and request should
84 * be passed to the higher level.
85 *
86 * @param[in] ep_cfg Pointer to endpoint configuration
87 *
88 * @return pointer to UDC request or NULL on error.
89 */
90 struct net_buf *udc_buf_get(struct udc_ep_config *const ep_cfg);
91
92 /**
93 * @brief Get all UDC request from endpoint FIFO.
94 *
95 * Get all UDC request from endpoint FIFO as single-linked list.
96 * This function removes all request from endpoint FIFO and
97 * is typically used to dequeue endpoint FIFO.
98 *
99 * @param[in] ep_cfg Pointer to endpoint configuration
100 *
101 * @return pointer to UDC request or NULL on error.
102 */
103 struct net_buf *udc_buf_get_all(struct udc_ep_config *const ep_cfg);
104
105 /**
106 * @brief Peek request at the head of endpoint FIFO.
107 *
108 * Return request from the head of endpoint FIFO without removing.
109 * Use it when request buffer is required for a transfer.
110 *
111 * @param[in] ep_cfg Pointer to endpoint configuration
112 *
113 * @return pointer to request or NULL on error.
114 */
115 struct net_buf *udc_buf_peek(struct udc_ep_config *const ep_cfg);
116
117 /**
118 * @brief Put request at the tail of endpoint FIFO.
119 *
120 * @param[in] ep_cfg Pointer to endpoint configuration
121 * @param[in] buf Pointer to UDC request buffer
122 *
123 * @return pointer to request or NULL on error.
124 */
125 void udc_buf_put(struct udc_ep_config *const ep_cfg,
126 struct net_buf *const buf);
127 /**
128 * @brief Helper function to send UDC event to a higher level.
129 *
130 * The callback would typically sends UDC even to a message queue (k_msgq).
131 *
132 * @param[in] dev Pointer to device struct of the driver instance
133 * @param[in] type Event type
134 * @param[in] status Event status
135 *
136 * @return 0 on success, all other values should be treated as error.
137 * @retval -EPERM controller is not initialized
138 */
139 int udc_submit_event(const struct device *dev,
140 const enum udc_event_type type,
141 const int status);
142
143 /**
144 * @brief Helper function to send UDC endpoint event to a higher level.
145 *
146 * Type of this event is hardcoded to UDC_EVT_EP_REQUEST.
147 * The callback would typically sends UDC even to a message queue (k_msgq).
148 *
149 * @param[in] dev Pointer to device struct of the driver instance
150 * @param[in] buf Pointer to UDC request buffer
151 * @param[in] err Request result
152 *
153 * @return 0 on success, all other values should be treated as error.
154 * @retval -EPERM controller is not initialized
155 */
156 int udc_submit_ep_event(const struct device *dev,
157 struct net_buf *const buf,
158 const int err);
159
160 /**
161 * @brief Helper function to send UDC SOF event to a higher level.
162 *
163 * Type of this event is hardcoded to UDC_EVT_SOF.
164 *
165 * @param[in] dev Pointer to device struct of the driver instance
166 */
167 #if defined(CONFIG_UDC_ENABLE_SOF)
udc_submit_sof_event(const struct device * dev)168 static inline void udc_submit_sof_event(const struct device *dev)
169 {
170 struct udc_data *data = dev->data;
171 struct udc_event drv_evt = {
172 .type = UDC_EVT_SOF,
173 .dev = dev,
174 };
175
176 (void)data->event_cb(dev, &drv_evt);
177 }
178 #else
179 #define udc_submit_sof_event(dev) ARG_UNUSED(dev)
180 #endif
181
182 /**
183 * @brief Helper function to enable endpoint.
184 *
185 * This function can be used by the driver to enable control IN/OUT endpoint.
186 *
187 * @param[in] dev Pointer to device struct of the driver instance
188 * @param[in] ep Endpoint address (same as bEndpointAddress)
189 * @param[in] attributes Endpoint attributes (same as bmAttributes)
190 * @param[in] mps Maximum packet size (same as wMaxPacketSize)
191 * @param[in] interval Polling interval (same as bInterval)
192 *
193 * @return 0 on success, all other values should be treated as error.
194 * @retval -ENODEV endpoint is not assigned or no configuration found
195 * @retval -EALREADY endpoint is already enabled
196 */
197 int udc_ep_enable_internal(const struct device *dev,
198 const uint8_t ep,
199 const uint8_t attributes,
200 const uint16_t mps,
201 const uint8_t interval);
202
203 /**
204 * @brief Helper function to disable endpoint.
205 *
206 * This function can be used by the driver to disable control IN/OUT endpoint.
207 *
208 * @param[in] dev Pointer to device struct of the driver instance
209 * @param[in] ep Endpoint address
210 *
211 * @return 0 on success, all other values should be treated as error.
212 * @retval -ENODEV endpoint is not assigned or no configuration found
213 * @retval -EALREADY endpoint is already enabled
214 */
215 int udc_ep_disable_internal(const struct device *dev,
216 const uint8_t ep);
217
218 /**
219 * @brief Helper function to register endpoint configuration.
220 *
221 * This function initializes endpoint FIFO and
222 * appends endpoint configuration to drivers endpoint list.
223 *
224 * @param[in] dev Pointer to device struct of the driver instance
225 * @param[in] cfg Pointer to endpoint configuration structure
226 *
227 * @return 0 on success, all other values should be treated as error.
228 * @retval -EACCES controller is initialized or enabled
229 */
230 int udc_register_ep(const struct device *dev,
231 struct udc_ep_config *const cfg);
232
233 /**
234 * @brief Set setup flag in requests metadata.
235 *
236 * A control transfer can be either setup or data OUT,
237 * use this function to mark request as setup packet.
238 *
239 * @param[in] buf Pointer to UDC request buffer
240 */
241 void udc_ep_buf_set_setup(struct net_buf *const buf);
242
243 /**
244 * @brief Checks whether the driver must finish transfer with a ZLP
245 *
246 * @param[in] buf Pointer to UDC request buffer
247 *
248 * @return true if ZLP is requested
249 */
250 bool udc_ep_buf_has_zlp(const struct net_buf *const buf);
251
252 /**
253 * @brief Clear ZLP flag
254 *
255 * @param[in] buf Pointer to UDC request buffer
256 */
257 void udc_ep_buf_clear_zlp(const struct net_buf *const buf);
258
259 /**
260 * @brief Locking function for the drivers.
261 *
262 * @param[in] dev Pointer to device struct of the driver instance
263 * @param[in] timeout Timeout
264 *
265 * @return values provided by k_mutex_lock()
266 */
udc_lock_internal(const struct device * dev,k_timeout_t timeout)267 static inline int udc_lock_internal(const struct device *dev,
268 k_timeout_t timeout)
269 {
270 struct udc_data *data = dev->data;
271
272 return k_mutex_lock(&data->mutex, timeout);
273 }
274
275 /**
276 * @brief Unlocking function for the drivers.
277 *
278 * @param[in] dev Pointer to device struct of the driver instance
279 *
280 * @return values provided by k_mutex_lock()
281 */
udc_unlock_internal(const struct device * dev)282 static inline int udc_unlock_internal(const struct device *dev)
283 {
284 struct udc_data *data = dev->data;
285
286 return k_mutex_unlock(&data->mutex);
287 }
288
289 /**
290 * @brief Allocate UDC control transfer buffer
291 *
292 * Allocate a new buffer from common control transfer buffer pool.
293 *
294 * @param[in] dev Pointer to device struct of the driver instance
295 * @param[in] ep Endpoint address
296 * @param[in] size Size of the request buffer
297 *
298 * @return pointer to allocated request or NULL on error.
299 */
300 struct net_buf *udc_ctrl_alloc(const struct device *dev,
301 const uint8_t ep,
302 const size_t size);
303
udc_data_stage_length(const struct net_buf * const buf)304 static inline uint16_t udc_data_stage_length(const struct net_buf *const buf)
305 {
306 struct usb_setup_packet *setup = (void *)buf->data;
307
308 return sys_le16_to_cpu(setup->wLength);
309 }
310
311 /**
312 * @brief Checks whether the current control transfer stage is Data Stage OUT
313 *
314 * @param[in] dev Pointer to device struct of the driver instance
315 *
316 * @return true if stage is Data Stage OUT
317 */
318 bool udc_ctrl_stage_is_data_out(const struct device *dev);
319
320 /**
321 * @brief Checks whether the current control transfer stage is Data Stage IN
322 *
323 * @param[in] dev Pointer to device struct of the driver instance
324 *
325 * @return true if stage is Data Stage IN
326 */
327 bool udc_ctrl_stage_is_data_in(const struct device *dev);
328
329 /**
330 * @brief Checks whether the current control transfer stage is Status IN
331 *
332 * @param[in] dev Pointer to device struct of the driver instance
333 *
334 * @return true if stage is Data Stage IN
335 */
336 bool udc_ctrl_stage_is_status_in(const struct device *dev);
337
338 /**
339 * @brief Checks whether the current control transfer stage is Status OUT
340 *
341 * @param[in] dev Pointer to device struct of the driver instance
342 *
343 * @return true if stage is Data Stage OUT
344 */
345 bool udc_ctrl_stage_is_status_out(const struct device *dev);
346
347 /**
348 * @brief Checks whether the current control transfer stage is Status no-data
349 *
350 * @param[in] dev Pointer to device struct of the driver instance
351 *
352 * @return true if stage is Status no-data
353 */
354 bool udc_ctrl_stage_is_no_data(const struct device *dev);
355
356 /**
357 * @brief Submit Control Write (s-out-status) transfer
358 *
359 * Allocate buffer for data stage IN,
360 * submit both setup and data buffer to upper layer.
361 *
362 * @param[in] dev Pointer to device struct of the driver instance
363 * @param[in] dout Pointer to UDC buffer containing data transaction
364 *
365 * @return 0 on success, all other values should be treated as error.
366 */
367 int udc_ctrl_submit_s_out_status(const struct device *dev,
368 struct net_buf *const dout);
369
370 /**
371 * @brief Prepare control data IN stage
372 *
373 * Allocate buffer for data stage IN,
374 * submit both setup and data buffer to upper layer.
375 *
376 * @param[in] dev Pointer to device struct of the driver instance
377 *
378 * @return 0 on success, all other values should be treated as error.
379 */
380 int udc_ctrl_submit_s_in_status(const struct device *dev);
381
382 /**
383 * @brief Prepare control (no-data) status stage
384 *
385 * Allocate buffer for status stage IN,
386 * submit both setup and status buffer to upper layer.
387 *
388 * @param[in] dev Pointer to device struct of the driver instance
389 *
390 * @return 0 on success, all other values should be treated as error.
391 */
392 int udc_ctrl_submit_s_status(const struct device *dev);
393
394 /**
395 * @brief Submit status transaction
396 *
397 * Submit both status transaction to upper layer.
398 *
399 * @param[in] dev Pointer to device struct of the driver instance
400 * @param[in] dout Pointer to UDC buffer containing data transaction
401 *
402 * @return 0 on success, all other values should be treated as error.
403 */
404 int udc_ctrl_submit_status(const struct device *dev,
405 struct net_buf *const buf);
406
407 /**
408 * @brief Update internal control stage status based on the net_buf metadata
409 *
410 * Use it in the driver to update the stage, typically there are
411 * three places where this function should be called:
412 * - when a setup packet is received
413 * - when a data stage is completed (all data stage transactions)
414 * - when a status stage transaction is finished
415 *
416 * The functions of type udc_ctrl_stage_is_*() can be called before or
417 * after this function, depending on the desired action.
418 * To keep protocol processing running the following should be taken
419 * into account:
420 *
421 * - Upper layer may not allocate buffers but remove or release buffers
422 * from the chain that are no longer needed. Only control IN transfers may
423 * be enqueued by the upper layer.
424 *
425 * - For "Control Write" (s-out-status), the driver should allocate the buffer,
426 * insert it as a fragment to setup buffer and perform the Data Stage
427 * transaction. Allocate and insert a fragment for the status (IN) stage to
428 * setup buffer, and then pass setup packet with the chain of s-out-status to
429 * upper layer. Upper layer should either halt control endpoint or
430 * enqueue status buffer for status stage. There should be second
431 * notification to upper layer when the status transaction is finished.
432 *
433 * ->driver_foo_setup_rcvd(dev)
434 * ->udc_ctrl_update_stage(dev, buf)
435 * ->udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, wLength)
436 * ->driver_foo_xfer_start(dev, USB_CONTROL_EP_OUT)
437 *
438 * ->driver_foo_dout_rcvd(dev)
439 * -...
440 * ->driver_foo_feed_next_dout(dev, ....)
441 * -...
442 * ->udc_ctrl_update_stage(dev, dout_buf)
443 * -...
444 * ->udc_ctrl_submit_s_out_status(dev, dout_buf);
445 *
446 * ->driver_foo_din_rcvd(dev)
447 * -...
448 * ->udc_ctrl_submit_status(dev, status_buf);
449 * -...
450 * ->udc_ctrl_update_stage(dev, status_buf)
451 *
452 * - For "Control Read" (s-in-status), depending on the controller,
453 * the driver should reserve the buffers for subsequent status stage and
454 * setup packet and prepare everything. The driver should allocate the buffer
455 * for IN transaction insert it as a fragment to setup buffer, and pass
456 * the chain of s-in to upper layer. Upper layer should either halt control
457 * endpoint or enqueue (in) buffer. There should be second
458 * notification to upper layer when the status transaction is finished.
459 *
460 * ->driver_foo_setup_rcvd(dev)
461 * ->udc_ctrl_update_stage(dev, buf)
462 * ->driver_foo_feed_next_dout(dev, ....)
463 * -...
464 * ->udc_ctrl_submit_s_in_status(dev);
465 *
466 * ->driver_foo_din_rcvd(dev)
467 * -...
468 * ->udc_ctrl_update_stage(dev, dout_buf)
469 * -...
470 *
471 * ->driver_foo_dout_rcvd(dev)
472 * -...
473 * ->udc_ctrl_submit_status(dev, status_buf);
474 * -...
475 * ->udc_ctrl_update_stage(dev, dout_buf)
476 *
477 * - For "No-data Control" (s-status), the driver should allocate the buffer
478 * for the status (IN) stage, insert it as a fragment to setup buffer,
479 * and then pass setup packet with the chain of s-status to
480 * upper layer. Upper layer should either halt control endpoint or
481 * enqueue status buffer for status stage. There should be second
482 * notification to upper layer when the status transaction is finished.
483 *
484 * ->driver_foo_setup_rcvd(dev)
485 * ->udc_ctrl_update_stage(dev, buf)
486 * ->driver_foo_feed_next_dout(dev, ....)
487 * -...
488 * ->udc_ctrl_submit_s_status(dev);
489 *
490 * ->driver_foo_din_rcvd(dev)
491 * -...
492 * ->udc_ctrl_submit_status(dev, status_buf);
493 * -...
494 * ->udc_ctrl_update_stage(dev, status_buf)
495 *
496 * Please refer to Chapter 8.5.3 Control Transfers USB 2.0 spec.
497 *
498 * @param[in] dev Pointer to device struct of the driver instance
499 * @param[in] buf Buffer containing setup packet
500 *
501 * @return 0 on success, all other values should be treated as error.
502 */
503 void udc_ctrl_update_stage(const struct device *dev,
504 struct net_buf *const buf);
505
506 #if defined(CONFIG_UDC_WORKQUEUE)
507 extern struct k_work_q udc_work_q;
508
udc_get_work_q(void)509 static inline struct k_work_q *udc_get_work_q(void)
510 {
511 return &udc_work_q;
512 }
513 #else
udc_get_work_q(void)514 static inline struct k_work_q *udc_get_work_q(void)
515 {
516 return &k_sys_work_q;
517 }
518 #endif
519
520 #endif /* ZEPHYR_INCLUDE_UDC_COMMON_H */
521