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