1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief USB host controller (UHC) driver API
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_UHC_H
13 #define ZEPHYR_INCLUDE_UHC_H
14 
15 #include <zephyr/kernel.h>
16 #include <zephyr/device.h>
17 #include <zephyr/net_buf.h>
18 #include <zephyr/usb/usb_ch9.h>
19 #include <zephyr/sys/dlist.h>
20 
21 /**
22  * @brief USB host controller (UHC) driver API
23  * @defgroup uhc_api USB host controller driver API
24  * @ingroup io_interfaces
25  * @since 3.3
26  * @version 0.1.1
27  * @{
28  */
29 
30 /** USB device state */
31 enum usb_device_state {
32 	USB_STATE_NOTCONNECTED,
33 	USB_STATE_DEFAULT,
34 	USB_STATE_ADDRESSED,
35 	USB_STATE_CONFIGURED,
36 };
37 
38 /**
39  * @brief USB device operating speed
40  */
41 enum usb_device_speed {
42 	/** Device is probably not connected */
43 	USB_SPEED_UNKNOWN,
44 	/** Low speed */
45 	USB_SPEED_SPEED_LS,
46 	/** Full speed */
47 	USB_SPEED_SPEED_FS,
48 	/** High speed */
49 	USB_SPEED_SPEED_HS,
50 	/** Super speed */
51 	USB_SPEED_SPEED_SS,
52 };
53 
54 #define UHC_INTERFACES_MAX 32
55 
56 struct usb_host_interface {
57 	struct usb_desc_header *dhp;
58 	uint8_t alternate;
59 };
60 
61 struct usb_host_ep {
62 	struct usb_ep_descriptor *desc;
63 };
64 
65 /**
66  * Host representation of a USB device
67  */
68 struct usb_device {
69 	/** dlist node */
70 	sys_dnode_t node;
71 	/** An opaque pointer to the host context to which this device belongs */
72 	void *ctx;
73 	/** Device mutex */
74 	struct k_mutex mutex;
75 	/** USB device descriptor */
76 	struct usb_device_descriptor dev_desc;
77 	/** Device state */
78 	enum usb_device_state state;
79 	/** Device speed */
80 	enum usb_device_speed speed;
81 	/** Actual active device configuration */
82 	uint8_t actual_cfg;
83 	/** Device address */
84 	uint8_t addr;
85 	/** Pointer to actual device configuration descriptor */
86 	void *cfg_desc;
87 	/** Pointers to device interfaces */
88 	struct usb_host_interface ifaces[UHC_INTERFACES_MAX + 1];
89 	/** Pointers to device OUT endpoints */
90 	struct usb_host_ep ep_out[16];
91 	/** Pointers to device IN endpoints */
92 	struct usb_host_ep ep_in[16];
93 };
94 
95 /**
96  * @brief USB control transfer stage
97  */
98 enum uhc_control_stage {
99 	UHC_CONTROL_STAGE_SETUP = 0,
100 	UHC_CONTROL_STAGE_DATA,
101 	UHC_CONTROL_STAGE_STATUS,
102 };
103 
104 /**
105  * UHC endpoint buffer info
106  *
107  * This structure is mandatory for all UHC request.
108  * It contains the meta data about the request and FIFOs
109  * to store net_buf structures for each request.
110  *
111  * The members of this structure should not be used
112  * directly by a higher layer (host stack).
113  */
114 struct uhc_transfer {
115 	/** dlist node */
116 	sys_dnode_t node;
117 	/** Control transfer setup packet */
118 	uint8_t setup_pkt[8];
119 	/** Transfer data buffer */
120 	struct net_buf *buf;
121 	/** Endpoint to which request is associated */
122 	uint8_t ep;
123 	/** Maximum packet size */
124 	uint16_t mps;
125 	/** Interval, used for periodic transfers only */
126 	uint16_t interval;
127 	/** Start frame, used for periodic transfers only */
128 	uint16_t start_frame;
129 	/** Flag marks request buffer is queued */
130 	unsigned int queued : 1;
131 	/** Control stage status, up to the driver to use it or not */
132 	unsigned int stage : 2;
133 	/** Pointer to USB device */
134 	struct usb_device *udev;
135 	/** Pointer to transfer completion callback (opaque for the UHC) */
136 	void *cb;
137 	/** Pointer to completion callback private data */
138 	void *priv;
139 	/** Transfer result, 0 on success, other values on error */
140 	int err;
141 };
142 
143 /**
144  * @brief USB host controller event types
145  */
146 enum uhc_event_type {
147 	/** Low speed device connected */
148 	UHC_EVT_DEV_CONNECTED_LS,
149 	/** Full speed device connected */
150 	UHC_EVT_DEV_CONNECTED_FS,
151 	/** High speed device connected */
152 	UHC_EVT_DEV_CONNECTED_HS,
153 	/** Device (peripheral) removed */
154 	UHC_EVT_DEV_REMOVED,
155 	/** Bus reset operation finished */
156 	UHC_EVT_RESETED,
157 	/** Bus suspend operation finished */
158 	UHC_EVT_SUSPENDED,
159 	/** Bus resume operation finished */
160 	UHC_EVT_RESUMED,
161 	/** Remote wakeup signal */
162 	UHC_EVT_RWUP,
163 	/** Endpoint request result event */
164 	UHC_EVT_EP_REQUEST,
165 	/**
166 	 * Non-correctable error event, requires attention from higher
167 	 * levels or application.
168 	 */
169 	UHC_EVT_ERROR,
170 };
171 
172 /**
173  * USB host controller event
174  *
175  * Common structure for all events that originate from
176  * the UHC driver and are passed to higher layer using
177  * message queue and a callback (uhc_event_cb_t) provided
178  * by higher layer during controller initialization (uhc_init).
179  */
180 struct uhc_event {
181 	/** slist node for the message queue */
182 	sys_snode_t node;
183 	/** Event type */
184 	enum uhc_event_type type;
185 	union {
186 		/** Event status value, if any */
187 		int status;
188 		/** Pointer to request used only for UHC_EVT_EP_REQUEST */
189 		struct uhc_transfer *xfer;
190 	};
191 	/** Pointer to controller's device struct */
192 	const struct device *dev;
193 };
194 
195 /**
196  * @typedef uhc_event_cb_t
197  * @brief Callback to submit UHC event to higher layer.
198  *
199  * At the higher level, the event is to be inserted into a message queue.
200  *
201  * @param[in] dev      Pointer to device struct of the driver instance
202  * @param[in] event    Point to event structure
203  *
204  * @return 0 on success, all other values should be treated as error.
205  */
206 typedef int (*uhc_event_cb_t)(const struct device *dev,
207 			      const struct uhc_event *const event);
208 
209 /**
210  * USB host controller capabilities
211  *
212  * This structure is mainly intended for the USB host stack.
213  */
214 struct uhc_device_caps {
215 	/** USB high speed capable controller */
216 	uint32_t hs : 1;
217 };
218 
219 /**
220  * Controller is initialized by uhc_init()
221  */
222 #define UHC_STATUS_INITIALIZED		0
223 /**
224  * Controller is enabled and all API functions are available
225  */
226 #define UHC_STATUS_ENABLED		1
227 
228 /**
229  * Common UHC driver data structure
230  *
231  * Mandatory structure for each UHC controller driver.
232  * To be implemented as device's private data (device->data).
233  */
234 struct uhc_data {
235 	/** Controller capabilities */
236 	struct uhc_device_caps caps;
237 	/** Driver access mutex */
238 	struct k_mutex mutex;
239 	/** dlist for control transfers */
240 	sys_dlist_t ctrl_xfers;
241 	/** dlist for bulk transfers */
242 	sys_dlist_t bulk_xfers;
243 	/** Callback to submit an UHC event to upper layer */
244 	uhc_event_cb_t event_cb;
245 	/** Opaque pointer to store higher layer context */
246 	const void *event_ctx;
247 	/** USB host controller status */
248 	atomic_t status;
249 	/** Driver private data */
250 	void *priv;
251 };
252 
253 /**
254  * @brief Checks whether the controller is initialized.
255  *
256  * @param[in] dev      Pointer to device struct of the driver instance
257  *
258  * @return true if controller is initialized, false otherwise
259  */
uhc_is_initialized(const struct device * dev)260 static inline bool uhc_is_initialized(const struct device *dev)
261 {
262 	struct uhc_data *data = dev->data;
263 
264 	return atomic_test_bit(&data->status, UHC_STATUS_INITIALIZED);
265 }
266 
267 /**
268  * @brief Checks whether the controller is enabled.
269  *
270  * @param[in] dev      Pointer to device struct of the driver instance
271  *
272  * @return true if controller is enabled, false otherwise
273  */
uhc_is_enabled(const struct device * dev)274 static inline bool uhc_is_enabled(const struct device *dev)
275 {
276 	struct uhc_data *data = dev->data;
277 
278 	return atomic_test_bit(&data->status, UHC_STATUS_ENABLED);
279 }
280 
281 /**
282  * @cond INTERNAL_HIDDEN
283  */
284 struct uhc_api {
285 	int (*lock)(const struct device *dev);
286 	int (*unlock)(const struct device *dev);
287 
288 	int (*init)(const struct device *dev);
289 	int (*enable)(const struct device *dev);
290 	int (*disable)(const struct device *dev);
291 	int (*shutdown)(const struct device *dev);
292 
293 	int (*bus_reset)(const struct device *dev);
294 	int (*sof_enable)(const struct device *dev);
295 	int (*bus_suspend)(const struct device *dev);
296 	int (*bus_resume)(const struct device *dev);
297 
298 	int (*ep_enqueue)(const struct device *dev,
299 			  struct uhc_transfer *const xfer);
300 	int (*ep_dequeue)(const struct device *dev,
301 			  struct uhc_transfer *const xfer);
302 };
303 /**
304  * @endcond
305  */
306 
307 /**
308  * @brief Reset USB bus
309  *
310  * Perform USB bus reset, controller may emit UHC_EVT_RESETED
311  * at the end of reset signaling.
312  *
313  * @param[in] dev      Pointer to device struct of the driver instance
314  *
315  * @return 0 on success, all other values should be treated as error.
316  * @retval -EBUSY if the controller is already performing a bus operation
317  */
uhc_bus_reset(const struct device * dev)318 static inline int uhc_bus_reset(const struct device *dev)
319 {
320 	const struct uhc_api *api = dev->api;
321 	int ret;
322 
323 	api->lock(dev);
324 	ret = api->bus_reset(dev);
325 	api->unlock(dev);
326 
327 	return ret;
328 }
329 
330 /**
331  * @brief Enable Start of Frame generator
332  *
333  * Enable SOF generator.
334  *
335  * @param[in] dev      Pointer to device struct of the driver instance
336  *
337  * @return 0 on success, all other values should be treated as error.
338  * @retval -EALREADY if already enabled
339  */
uhc_sof_enable(const struct device * dev)340 static inline int uhc_sof_enable(const struct device *dev)
341 {
342 	const struct uhc_api *api = dev->api;
343 	int ret;
344 
345 	api->lock(dev);
346 	ret = api->sof_enable(dev);
347 	api->unlock(dev);
348 
349 	return ret;
350 }
351 
352 /**
353  * @brief Suspend USB bus
354  *
355  * Disable SOF generator and emit UHC_EVT_SUSPENDED event when USB bus
356  * is suspended.
357  *
358  * @param[in] dev      Pointer to device struct of the driver instance
359  *
360  * @return 0 on success, all other values should be treated as error.
361  * @retval -EALREADY if already suspended
362  */
uhc_bus_suspend(const struct device * dev)363 static inline int uhc_bus_suspend(const struct device *dev)
364 {
365 	const struct uhc_api *api = dev->api;
366 	int ret;
367 
368 	api->lock(dev);
369 	ret = api->bus_suspend(dev);
370 	api->unlock(dev);
371 
372 	return ret;
373 }
374 
375 /**
376  * @brief Resume USB bus
377  *
378  * Signal resume for at least 20ms, emit UHC_EVT_RESUMED at the end of USB
379  * bus resume signaling. The SoF generator should subsequently start within 3ms.
380  *
381  * @param[in] dev      Pointer to device struct of the driver instance
382  *
383  * @return 0 on success, all other values should be treated as error.
384  * @retval -EBUSY if the controller is already performing a bus operation
385  */
uhc_bus_resume(const struct device * dev)386 static inline int uhc_bus_resume(const struct device *dev)
387 {
388 	const struct uhc_api *api = dev->api;
389 	int ret;
390 
391 	api->lock(dev);
392 	ret = api->bus_resume(dev);
393 	api->unlock(dev);
394 
395 	return ret;
396 }
397 
398 /**
399  * @brief Allocate UHC transfer
400  *
401  * Allocate a new transfer from common transfer pool.
402  * Transfer has no buffer after allocation, but can be allocated
403  * and added from different pools.
404  *
405  * @param[in] dev     Pointer to device struct of the driver instance
406  * @param[in] ep      Endpoint address
407  * @param[in] udev    Pointer to USB device
408  * @param[in] cb      Transfer completion callback
409  * @param[in] cb_priv Completion callback callback private data
410  *
411  * @return pointer to allocated transfer or NULL on error.
412  */
413 struct uhc_transfer *uhc_xfer_alloc(const struct device *dev,
414 				    const uint8_t ep,
415 				    struct usb_device *const udev,
416 				    void *const cb,
417 				    void *const cb_priv);
418 
419 /**
420  * @brief Allocate UHC transfer with buffer
421  *
422  * Allocate a new transfer from common transfer pool with buffer.
423  *
424  * @param[in] dev     Pointer to device struct of the driver instance
425  * @param[in] ep      Endpoint address
426  * @param[in] udev    Pointer to USB device
427  * @param[in] cb      Transfer completion callback
428  * @param[in] cb_priv Completion callback callback private data
429  * @param[in] size    Size of the buffer
430  *
431  * @return pointer to allocated transfer or NULL on error.
432  */
433 struct uhc_transfer *uhc_xfer_alloc_with_buf(const struct device *dev,
434 					     const uint8_t ep,
435 					     struct usb_device *const udev,
436 					     void *const cb,
437 					     void *const cb_priv,
438 					     size_t size);
439 
440 /**
441  * @brief Free UHC transfer and any buffers
442  *
443  * Free any buffers and put the transfer back into the transfer pool.
444  *
445  * @param[in] dev    Pointer to device struct of the driver instance
446  * @param[in] xfer   Pointer to UHC transfer
447  *
448  * @return 0 on success, all other values should be treated as error.
449  */
450 int uhc_xfer_free(const struct device *dev,
451 		  struct uhc_transfer *const xfer);
452 
453 /**
454  * @brief Add UHC transfer buffer
455  *
456  * Add a previously allocated buffer to the transfer.
457  *
458  * @param[in] dev    Pointer to device struct of the driver instance
459  * @param[in] xfer   Pointer to UHC transfer
460  * @param[in] buf    Pointer to UHC request buffer
461  *
462  * @return pointer to allocated request or NULL on error.
463  */
464 int uhc_xfer_buf_add(const struct device *dev,
465 		     struct uhc_transfer *const xfer,
466 		     struct net_buf *buf);
467 /**
468  * @brief Allocate UHC transfer buffer
469  *
470  * Allocate a new buffer from common request buffer pool and
471  * assign it to the transfer if the xfer parameter is not NULL.
472  *
473  * @param[in] dev    Pointer to device struct of the driver instance
474  * @param[in] size   Size of the request buffer
475  *
476  * @return pointer to allocated request or NULL on error.
477  */
478 struct net_buf *uhc_xfer_buf_alloc(const struct device *dev,
479 				   const size_t size);
480 
481 /**
482  * @brief Free UHC request buffer
483  *
484  * Put the buffer back into the request buffer pool.
485  *
486  * @param[in] dev    Pointer to device struct of the driver instance
487  * @param[in] buf    Pointer to UHC request buffer
488  */
489 void uhc_xfer_buf_free(const struct device *dev, struct net_buf *const buf);
490 
491 /**
492  * @brief Queue USB host controller transfer
493  *
494  * Add transfer to the queue. If the queue is empty, the transfer
495  * can be claimed by the controller immediately.
496  *
497  * @param[in] dev    Pointer to device struct of the driver instance
498  * @param[in] xfer   Pointer to UHC transfer
499  *
500  * @return 0 on success, all other values should be treated as error.
501  * @retval -EPERM controller is not initialized
502  */
503 int uhc_ep_enqueue(const struct device *dev, struct uhc_transfer *const xfer);
504 
505 /**
506  * @brief Remove a USB host controller transfers from queue
507  *
508  * Not implemented yet.
509  *
510  * @param[in] dev    Pointer to device struct of the driver instance
511  * @param[in] xfer   Pointer to UHC transfer
512  *
513  * @return 0 on success, all other values should be treated as error.
514  * @retval -EPERM controller is not initialized
515  */
516 int uhc_ep_dequeue(const struct device *dev, struct uhc_transfer *const xfer);
517 
518 /**
519  * @brief Initialize USB host controller
520  *
521  * Initialize USB host controller.
522  *
523  * @param[in] dev      Pointer to device struct of the driver instance
524  * @param[in] event_cb Event callback from the higher layer (USB host stack)
525  * @param[in] event_ctx Opaque pointer to higher layer context
526  *
527  * @return 0 on success, all other values should be treated as error.
528  * @retval -EINVAL on parameter error (no callback is passed)
529  * @retval -EALREADY already initialized
530  */
531 int uhc_init(const struct device *dev,
532 	     uhc_event_cb_t event_cb, const void *const event_ctx);
533 
534 /**
535  * @brief Enable USB host controller
536  *
537  * Enable powered USB host controller and allow host stack to
538  * recognize and enumerate devices.
539  *
540  * @param[in] dev    Pointer to device struct of the driver instance
541  *
542  * @return 0 on success, all other values should be treated as error.
543  * @retval -EPERM controller is not initialized
544  * @retval -EALREADY already enabled
545  */
546 int uhc_enable(const struct device *dev);
547 
548 /**
549  * @brief Disable USB host controller
550  *
551  * Disable enabled USB host controller.
552  *
553  * @param[in] dev    Pointer to device struct of the driver instance
554  *
555  * @return 0 on success, all other values should be treated as error.
556  * @retval -EALREADY already disabled
557  */
558 int uhc_disable(const struct device *dev);
559 
560 /**
561  * @brief Poweroff USB host controller
562  *
563  * Shut down the controller completely to reduce energy consumption
564  * or to change the role of the controller.
565  *
566  * @param[in] dev    Pointer to device struct of the driver instance
567  *
568  * @return 0 on success, all other values should be treated as error.
569  * @retval -EALREADY controller is already uninitialized
570  */
571 int uhc_shutdown(const struct device *dev);
572 
573 /**
574  * @brief Get USB host controller capabilities
575  *
576  * Obtain the capabilities of the controller
577  * such as high speed (HS), and more.
578  *
579  * @param[in] dev    Pointer to device struct of the driver instance
580  *
581  * @return USB host controller capabilities.
582  */
uhc_caps(const struct device * dev)583 static inline struct uhc_device_caps uhc_caps(const struct device *dev)
584 {
585 	struct uhc_data *data = dev->data;
586 
587 	return data->caps;
588 }
589 
590 /**
591  * @brief Get pointer to higher layer context
592  *
593  * The address of the context is passed as an argument to the uhc_init()
594  * function and is stored in the uhc data.
595  *
596  * @param[in] dev Pointer to device struct of the driver instance
597  *
598  * @return Opaque pointer to higher layer context
599  */
uhc_get_event_ctx(const struct device * dev)600 static inline const void *uhc_get_event_ctx(const struct device *dev)
601 {
602 	struct uhc_data *data = dev->data;
603 
604 	return data->event_ctx;
605 }
606 
607 /**
608  * @}
609  */
610 
611 #endif /* ZEPHYR_INCLUDE_UHC_H */
612