LCOV - code coverage report
Current view: top level - zephyr/drivers/usb - uhc.h Hit Total Coverage
Test: new.info Lines: 54 56 96.4 %
Date: 2024-12-22 00:14:23

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

Generated by: LCOV version 1.14