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