123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649 |
- /* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA").
- * All rights reserved.
- *
- * This software is supplied "AS IS" without any warranties.
- * RDA assumes no responsibility or liability for the use of the software,
- * conveys no license or title under any patent, copyright, or mask work
- * right to the product. RDA reserves the right to make changes in the
- * software without notification. RDA also make no representation or
- * warranty that such application will be suitable for the specified use
- * without further testing or modification.
- */
- #ifndef _USB__DEVICE_H_
- #define _USB__DEVICE_H_
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include <stdint.h>
- #include <stdbool.h>
- #include <stddef.h>
- #include "usb/usb_ch9.h"
- typedef enum
- {
- EP0_SETUP = 0,
- #define EP0_STATE_DIRIN_MASK 0b10
- #define EP0_STATE_DATA_MASK 0b1
- EP0_DATA_IN = 0b111,
- EP0_DATA_OUT = 0b101,
- EP0_STATUS_IN = 0b110,
- EP0_STATUS_OUT = 0b100,
- } ep0State_t;
- typedef enum
- {
- UDC_IDLE = 0,
- UDC_CONNECTED,
- UDC_DISCONNECT,
- } udcEvent_t;
- typedef void (*udcNotifier_t)(void *param, udcEvent_t event);
- /**
- * @brief USB device controller
- */
- typedef struct udc_s udc_t;
- /**
- * @brief USB device driver
- *
- * Such as a specific class, or a composite driver
- */
- typedef struct usb_dev_driver_s udevDrv_t;
- /**
- * @brief usb endpoint
- */
- typedef struct usb_ep
- {
- union {
- struct
- {
- uint8_t num : 7;
- uint8_t dirin : 1;
- };
- uint8_t address;
- };
- uint16_t mps;
- } usbEp_t;
- /**
- * @brief usb string
- */
- typedef struct usb_string
- {
- uint8_t id;
- uint8_t ref_count;
- const char *s;
- } usbString_t;
- /**
- * @brief the usb transfer request
- */
- typedef struct usb_xfer
- {
- void *buf; ///< transfer buffer
- uint32_t length; ///< transfer data length
- uint32_t actual; ///< actual transfered length, udc set it, caller only read
- int status; ///< transfer status, (0 - success; other negative - fail)
- uint8_t zlp; ///< may send zero packet or not, in transfer only
- uint8_t uncached; ///< address is uncached
- void *param; ///< caller context
- void (*complete)(usbEp_t *ep, struct usb_xfer *xfer); ///< transfer done callback
- } usbXfer_t;
- typedef struct
- {
- void (*setclk)(udc_t *udc, bool on); ///< set controller clock
- void (*setpower)(udc_t *udc, bool on); ///< set controller power
- void (*enable)(udc_t *udc); ///< enable the usb controller
- void (*disable)(udc_t *udc); ///< disable the usb controller
- void (*suspend)(udc_t *udc); ///< suspend the usb controller
- void (*resume)(udc_t *udc); ///< resume the usb controller
- } udcPlatOps_t;
- /**
- * @brief struct for udc operations
- */
- typedef struct
- {
- void (*start)(udc_t *udc); ///< start the udc
- void (*stop)(udc_t *udc); ///< stop the udc
- bool (*remote_wakeup)(udc_t *udc); ///< remote wakeup
- int (*enqueue)(udc_t *udc, usbEp_t *ep, usbXfer_t *req); ///< enqueue an usb request
- void (*dequeue)(udc_t *udc, usbEp_t *ep, usbXfer_t *req); ///< dequeue an usb request
- void (*dequeue_all)(udc_t *udc, usbEp_t *ep); ///< dequeue all for specific endpoint
- usbEp_t *(*ep_alloc)(udc_t *udc, usb_endpoint_descriptor_t *desc); ///< allocate an usb endpoint
- void (*ep_free)(udc_t *udc, usbEp_t *ep); ///< free an usb endpoint
- int (*ep_enable)(udc_t *udc, usbEp_t *ep); ///< enable the endpoint
- void (*ep_disable)(udc_t *udc, usbEp_t *ep); ///< disable the endpoint
- void (*ep_stall)(udc_t *udc, usbEp_t *ep, bool halt); ///< stall or clear stall for an endpoint
- usbXfer_t *(*xfer_alloc)(udc_t *udc); ///< allocate an usb xfer
- void (*xfer_free)(udc_t *udc, usbXfer_t *xfer); ///< free the usb xfer
- // gdb mode
- void (*gdb_poll)(udc_t *udc); ///< poll intr in gdb mode
- } udcOps_t;
- enum udc_feature
- {
- #define UDC_FEATURE_ATTRIBUTE_MASK 0xff
- /// UC Attribute
- UDC_FEATURE_REMOTE_WAKEUP = UC_REMOTE_WAKEUP,
- UDC_FEATURE_SELF_POWERED = UC_SELF_POWERED,
- UDC_FEATURE_BUS_POWERED = UC_BUS_POWERED,
- /// Software defined
- UDC_FEATURE_WAKEUP_ON_WRITE = (1 << 8),
- };
- #ifdef CONFIG_SOC_8850
- typedef struct musbFifo
- {
- void *data; ///< FIFO buffer
- size_t size; ///< FIFO buffer size
- size_t rd; ///< FIFO read pointer
- size_t wr; ///< FIFO write pointer
- } musbFifo_t;
- typedef struct
- {
- uint32_t addr;
- uint16_t frag_len;
- uint16_t blk_len;
- uint32_t link_end : 1;
- uint32_t sp : 1;
- uint32_t ioc : 1;
- uint32_t : 5;
- uint32_t haddr : 4;
- uint32_t : 20;
- uint32_t : 32; // This word is needed
- } UdcLinkList_t;
- #endif
- struct udc_s
- {
- int speed; ///< controller speed, from controller
- int feature; ///< controller feature defined in udc_feature
- udcPlatOps_t plat_ops; ///< operates for specific platform
- udcOps_t ops; ///< controller operates
- unsigned long platform_priv; ///< platform private data
- unsigned long controller_priv; ///< controller private data
- usbEp_t *ep0; ///< ep0, from controller
- #ifdef CONFIG_SOC_8850
- bool is_configured;
- void *rx_dma_buf;
- void *tx_dma_buf;
- UdcLinkList_t rx_linklist[15]; ///RX_dma linklist
- UdcLinkList_t tx_linklist[15]; ///TX_dma linklist
- musbFifo_t rx_fifo;
- musbFifo_t tx_fifo;
- unsigned int node_start;
- #endif
- };
- typedef struct
- {
- int (*bind)(udevDrv_t *driver);
- void (*unbind)(udevDrv_t *driver);
- int (*setup)(udevDrv_t *driver, const usb_device_request_t *setup);
- void (*start)(udevDrv_t *driver);
- void (*stop)(udevDrv_t *driver);
- void (*connect)(udevDrv_t *driver);
- void (*disconnect)(udevDrv_t *driver);
- void (*resume)(udevDrv_t *driver);
- void (*suspend)(udevDrv_t *driver);
- } udevDrvOps_t;
- struct usb_dev_driver_s
- {
- udc_t *udc;
- udevDrvOps_t ops;
- };
- #define USB_DUMMY_RX_BUF_SIZE (512)
- extern char gDummyUsbRxBuf[USB_DUMMY_RX_BUF_SIZE];
- /**
- * @brief Create the usb device controller instance
- *
- * @param name the controller device name
- * @return
- * - NULL fail
- * - the usb device controller
- */
- udc_t *udcCreate(uint32_t name);
- /**
- * @brief Destroy the udc
- *
- * @param udc the udc
- */
- void udcDestroy(udc_t *udc);
- /**
- * @brief Bind the udc driver to the udc
- *
- * @param udc the udc
- * @param drv the udc driver
- */
- void udcBindDriver(udc_t *udc, udevDrv_t *drv);
- /**
- * @brief Get the binding driver
- *
- * @param udc the udc
- * @return
- * - NULL No driver bind to this udc
- * - other the udc driver
- */
- udevDrv_t *udcGetDriver(udc_t *udc);
- /**
- * @brief udc set event notifier
- *
- * @param udc the udc
- * @param n the notifier
- * @param param caller context
- */
- void udcSetNotifier(udc_t *udc, udcNotifier_t n, void *param);
- /**
- * @brief udc connect
- * @param udc the udc
- */
- void udcConnect(udc_t *udc);
- /**
- * @brief udc disconnect
- * @param udc the udc
- */
- void udcDisconnect(udc_t *udc);
- /**
- * @brief udc suspend
- * @param udc the udc
- */
- void udcSuspend(udc_t *udc);
- /**
- * @brief udc resume
- * @param udc the udc
- */
- void udcResume(udc_t *udc);
- /**
- * @brief udc remote wakeup
- * @param udc the udc
- */
- bool udcRemoteWakeup(udc_t *udc);
- /**
- * @brief usb suspend or other status
- *
- * @param udc the udc
- * @return
- * - NULL fail
- * - the usb device controller
- */
- bool udcUsbIsSuspend(udc_t *udc);
- #define CHECK_UDC_PLAT_OPS(u, o) ((u) != NULL && (u)->plat_ops.o != NULL)
- #define CHECK_UDC_OPS(u, o) ((u) != NULL && (u)->ops.o != NULL)
- #define CHECK_DRV_OPS(d, o) ((d) != NULL && (d)->ops.o != NULL)
- /**
- * @brief The platform turn on/off usb power
- *
- * @param udc the udc
- * @param on on or off the power
- */
- static inline void udcPlatSetPower(udc_t *udc, bool on)
- {
- if (CHECK_UDC_PLAT_OPS(udc, setpower))
- return udc->plat_ops.setpower(udc, on);
- }
- /**
- * @brief The platform turn on/off clock
- *
- * @param udc the udc
- * @param on on or off the clock
- */
- static inline void udcPlatSetClock(udc_t *udc, bool on)
- {
- if (CHECK_UDC_PLAT_OPS(udc, setclk))
- return udc->plat_ops.setclk(udc, on);
- }
- /**
- * @brief The platform process on usb controller suspend
- *
- * @param udc the udc
- */
- static inline void udcPlatSuspend(udc_t *udc)
- {
- if (CHECK_UDC_PLAT_OPS(udc, suspend))
- udc->plat_ops.suspend(udc);
- }
- /**
- * @brief The platform process on usb controller resume
- *
- * @param udc the udc
- */
- static inline void udcPlatResume(udc_t *udc)
- {
- if (CHECK_UDC_PLAT_OPS(udc, resume))
- udc->plat_ops.resume(udc);
- }
- /**
- * @brief The platform enable usb module
- *
- * Init usb phy and others
- * @param udc the udc
- */
- static inline void udcPlatEnable(udc_t *udc)
- {
- if (CHECK_UDC_PLAT_OPS(udc, enable))
- return udc->plat_ops.enable(udc);
- }
- /**
- * @brief The platform disable usb module
- *
- * @param udc the udc
- */
- static inline void udcPlatDisable(udc_t *udc)
- {
- if (CHECK_UDC_PLAT_OPS(udc, disable))
- return udc->plat_ops.disable(udc);
- }
- /**
- * @brief Start udc, make the controller works
- *
- * @param udc the udc
- */
- void udcStart(udc_t *udc);
- /**
- * @brief Stop udc, the controller will be closed
- *
- * @param udc the udc
- */
- void udcStop(udc_t *udc);
- /**
- * @brief Enqueue an usb transfer
- *
- * Before call the method, caller should be sure ep is a valid
- * usb endpoint, and make sure full fill the usb transfer.
- *
- * @param udc the udc
- * @param ep the usb endpoint
- * @param xfer the usb transfer
- * @return
- * - 0 success
- * - (-1) fail
- */
- static inline int udcEpQueue(udc_t *udc, usbEp_t *ep, usbXfer_t *xfer)
- {
- if (CHECK_UDC_OPS(udc, enqueue) && ep != NULL && xfer != NULL)
- return udc->ops.enqueue(udc, ep, xfer);
- return -1;
- }
- /**
- * @brief Dequeue an usb transfer
- *
- * @param udc the udc
- * @param ep the usb endpoint
- * @param xfer the usb transfer
- */
- static inline void udcEpDequeue(udc_t *udc, usbEp_t *ep, usbXfer_t *xfer)
- {
- if (CHECK_UDC_OPS(udc, dequeue) && ep != NULL && xfer != NULL)
- udc->ops.dequeue(udc, ep, xfer);
- }
- /**
- * @brief Dequeue all transfers for an usb endpoint
- *
- * @param udc the udc
- * @param ep the usb endpoint
- */
- static inline void udcEpDequeueAll(udc_t *udc, usbEp_t *ep)
- {
- if (CHECK_UDC_OPS(udc, dequeue_all) && ep != NULL)
- udc->ops.dequeue_all(udc, ep);
- }
- /**
- * @brief Allocate an usb endpoint
- *
- * @param udc the udc
- * @param desc the usb endpoint descriptor
- * @return
- * - NULL fail
- * - other usb endpoint
- */
- static inline usbEp_t *udcEpAlloc(udc_t *udc, usb_endpoint_descriptor_t *desc)
- {
- if (CHECK_UDC_OPS(udc, ep_alloc) && desc != NULL)
- return udc->ops.ep_alloc(udc, desc);
- return NULL;
- }
- /**
- * @brief Free an usb endpoint
- *
- * @param udc the udc
- * @param ep the usb endpoint
- */
- static inline void udcEpFree(udc_t *udc, usbEp_t *ep)
- {
- if (CHECK_UDC_OPS(udc, ep_free) && ep != NULL)
- return udc->ops.ep_free(udc, ep);
- }
- /**
- * @brief Allocate an usb xfer
- *
- * @param udc the udc
- * @return
- * - NULL fail
- * - other the xfer
- */
- static inline usbXfer_t *udcXferAlloc(udc_t *udc)
- {
- if (CHECK_UDC_OPS(udc, xfer_alloc))
- return udc->ops.xfer_alloc(udc);
- return NULL;
- }
- /**
- * @brief Free an usb xfer
- *
- * @param udc the udc
- * @param xfer the xfer
- */
- static inline void udcXferFree(udc_t *udc, usbXfer_t *xfer)
- {
- if (CHECK_UDC_OPS(udc, xfer_free) && xfer)
- return udc->ops.xfer_free(udc, xfer);
- }
- /**
- * @brief Enable the endpoint
- *
- * @param udc the udc
- * @param ep the endpoint
- * @return
- * - (-1) fail
- * - other success
- */
- static inline int udcEpEnable(udc_t *udc, usbEp_t *ep)
- {
- if (CHECK_UDC_OPS(udc, ep_enable) && ep != NULL)
- return udc->ops.ep_enable(udc, ep);
- return -1;
- }
- /**
- * @brief Disable the endpoint
- *
- * @param udc the udc
- * @param ep the endpoint
- */
- static inline void udcEpDisable(udc_t *udc, usbEp_t *ep)
- {
- if (CHECK_UDC_OPS(udc, ep_disable) && ep != NULL)
- return udc->ops.ep_disable(udc, ep);
- }
- /**
- * @brief Stall an endpoint
- *
- * @param udc the udc
- * @param ep the usb endpoint
- * @param halt true: stall; false: clear stall
- */
- static inline void udcEpStall(udc_t *udc, usbEp_t *ep, bool halt)
- {
- if (CHECK_UDC_OPS(udc, ep_stall) && ep != NULL)
- udc->ops.ep_stall(udc, ep, halt);
- }
- /**
- * @brief Poll usb interrupt in gdb mode
- *
- * @param udc the usb device controller
- */
- static inline void udcGdbPollIntr(udc_t *udc)
- {
- if (CHECK_UDC_OPS(udc, gdb_poll))
- udc->ops.gdb_poll(udc);
- }
- /**
- * @brief usb deivce driver process setup packet
- *
- * @param drv the driver
- * @param setup the setup packet
- * @return
- * - (-1) process failed
- * - 0 success
- */
- static inline int udevDriverSetup(udevDrv_t *drv, const usb_device_request_t *setup)
- {
- if (CHECK_DRV_OPS(drv, setup))
- return drv->ops.setup(drv, setup);
- return -1;
- }
- /**
- * @brief usb device driver bind the usb controller
- *
- * @param drv the driver
- * @return
- * - (-1) failed
- * - 0 success
- */
- static inline int udevDriverBind(udevDrv_t *drv)
- {
- if (CHECK_DRV_OPS(drv, bind))
- return drv->ops.bind(drv);
- return -1;
- }
- /**
- * @brief usb device driver unbind the controller
- *
- * @param drv the driver
- */
- static inline void udevDriverUnbind(udevDrv_t *drv)
- {
- if (CHECK_DRV_OPS(drv, unbind))
- drv->ops.unbind(drv);
- }
- /**
- * @brief usb device driver start.
- *
- * Prepare environment, etc.
- *
- * @param drv the driver
- */
- static inline void udevDriverStart(udevDrv_t *drv)
- {
- if (CHECK_DRV_OPS(drv, start))
- drv->ops.start(drv);
- }
- /**
- * @brief usb device driver stop.
- *
- * Release resource and etc.
- *
- * @param drv the driver
- */
- static inline void udevDriverStop(udevDrv_t *drv)
- {
- if (CHECK_DRV_OPS(drv, stop))
- drv->ops.stop(drv);
- }
- /**
- * @brief usb device connect to a host
- *
- * @param drv the driver
- */
- static inline void udevDriverConnect(udevDrv_t *drv)
- {
- if (CHECK_DRV_OPS(drv, connect))
- drv->ops.connect(drv);
- }
- /**
- * @brief usb device disconnect to a host
- *
- * @param drv the driver
- */
- static inline void udevDriverDisconnect(udevDrv_t *drv)
- {
- if (CHECK_DRV_OPS(drv, disconnect))
- drv->ops.disconnect(drv);
- }
- /**
- * @brief usb device suspend to a host
- *
- * @param drv the driver
- */
- static inline void udevDriverSuspend(udevDrv_t *drv)
- {
- if (CHECK_DRV_OPS(drv, suspend))
- drv->ops.suspend(drv);
- }
- /**
- * @brief usb device resume to a host
- *
- * @param drv the driver
- */
- static inline void udevDriverResume(udevDrv_t *drv)
- {
- if (CHECK_DRV_OPS(drv, resume))
- drv->ops.resume(drv);
- }
- #ifdef __cplusplus
- }
- #endif
- #endif
|