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