LCOV - code coverage report
Current view: top level - zephyr/drivers/usb - uhc.h Coverage Total Hit
Test: new.info Lines: 88.8 % 80 71
Test Date: 2025-09-05 20:47:19

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

Generated by: LCOV version 2.0-1