471 lines
22 KiB
C
471 lines
22 KiB
C
/**************************************************************************//**
|
|
* @file usb.h
|
|
* @version V1.00
|
|
* @brief USB Host library header file.
|
|
* @note
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
* Copyright (C) 2019-2020 Nuvoton Technology Corp. All rights reserved.
|
|
*****************************************************************************/
|
|
|
|
#ifndef _USBH_H_
|
|
#define _USBH_H_
|
|
|
|
#include "config.h"
|
|
#include "usbh_lib.h"
|
|
#include "ohci.h"
|
|
|
|
/// @cond HIDDEN_SYMBOLS
|
|
|
|
struct utr_t;
|
|
struct udev_t;
|
|
struct hub_dev_t;
|
|
struct iface_t;
|
|
struct ep_info_t;
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* USB device request setup packet */
|
|
/*----------------------------------------------------------------------------------*/
|
|
#ifdef __ICCARM__
|
|
typedef struct
|
|
{
|
|
__packed uint8_t bmRequestType;
|
|
__packed uint8_t bRequest;
|
|
__packed uint16_t wValue;
|
|
__packed uint16_t wIndex;
|
|
__packed uint16_t wLength;
|
|
} DEV_REQ_T;
|
|
#else
|
|
typedef struct __attribute__((__packed__))
|
|
{
|
|
uint8_t bmRequestType;
|
|
uint8_t bRequest;
|
|
uint16_t wValue;
|
|
uint16_t wIndex;
|
|
uint16_t wLength;
|
|
}
|
|
DEV_REQ_T;
|
|
#endif
|
|
|
|
/*
|
|
* bmRequestType[7] - Data transfer direction
|
|
*/
|
|
#define REQ_TYPE_OUT 0x00
|
|
#define REQ_TYPE_IN 0x80
|
|
/*
|
|
* bmRequestType[6:5] - Type
|
|
*/
|
|
#define REQ_TYPE_STD_DEV 0x00
|
|
#define REQ_TYPE_CLASS_DEV 0x20
|
|
#define REQ_TYPE_VENDOR_DEV 0x40
|
|
/*
|
|
* bmRequestType[4:0] - Recipient
|
|
*/
|
|
#define REQ_TYPE_TO_DEV 0x00
|
|
#define REQ_TYPE_TO_IFACE 0x01
|
|
#define REQ_TYPE_TO_EP 0x02
|
|
#define REQ_TYPE_TO_OTHER 0x03
|
|
/*
|
|
* Standard Requests
|
|
*/
|
|
#define USB_REQ_GET_STATUS 0x00
|
|
#define USB_REQ_CLEAR_FEATURE 0x01
|
|
#define USB_REQ_SET_FEATURE 0x03
|
|
#define USB_REQ_SET_ADDRESS 0x05
|
|
#define USB_REQ_GET_DESCRIPTOR 0x06
|
|
#define USB_REQ_SET_CONFIGURATION 0x09
|
|
#define USB_REQ_SET_INTERFACE 0x0B
|
|
/*
|
|
* Descriptor Types
|
|
*/
|
|
#define USB_DT_STANDARD 0x00
|
|
#define USB_DT_CLASS 0x20
|
|
#define USB_DT_VENDOR 0x40
|
|
|
|
#define USB_DT_DEVICE 0x01
|
|
#define USB_DT_CONFIGURATION 0x02
|
|
#define USB_DT_STRING 0x03
|
|
#define USB_DT_INTERFACE 0x04
|
|
#define USB_DT_ENDPOINT 0x05
|
|
#define USB_DT_DEVICE_QUALIFIER 0x06
|
|
#define USB_DT_OTHER_SPEED_CONF 0x07
|
|
#define USB_DT_IFACE_POWER 0x08
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* USB standard descriptors */
|
|
/*----------------------------------------------------------------------------------*/
|
|
|
|
/* Descriptor header */
|
|
#ifdef __ICCARM__
|
|
typedef struct
|
|
{
|
|
__packed uint8_t bLength;
|
|
__packed uint8_t bDescriptorType;
|
|
} DESC_HDR_T;
|
|
#else
|
|
typedef struct __attribute__((__packed__))
|
|
{
|
|
uint8_t bLength;
|
|
uint8_t bDescriptorType;
|
|
}
|
|
DESC_HDR_T;
|
|
#endif
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* USB device descriptor */
|
|
/*----------------------------------------------------------------------------------*/
|
|
#ifdef __ICCARM__
|
|
typedef struct /*!< device descriptor structure */
|
|
{
|
|
__packed uint8_t bLength; /*!< Length of device descriptor */
|
|
__packed uint8_t bDescriptorType; /*!< Device descriptor type */
|
|
__packed uint16_t bcdUSB; /*!< USB version number */
|
|
__packed uint8_t bDeviceClass; /*!< Device class code */
|
|
__packed uint8_t bDeviceSubClass; /*!< Device subclass code */
|
|
__packed uint8_t bDeviceProtocol; /*!< Device protocol code */
|
|
__packed uint8_t bMaxPacketSize0; /*!< Maximum packet size of control endpoint*/
|
|
__packed uint16_t idVendor; /*!< Vendor ID */
|
|
__packed uint16_t idProduct; /*!< Product ID */
|
|
__packed uint16_t bcdDevice; /*!< Device ID */
|
|
__packed uint8_t iManufacturer; /*!< Manufacture description string ID */
|
|
__packed uint8_t iProduct; /*!< Product description string ID */
|
|
__packed uint8_t iSerialNumber; /*!< Serial number description string ID */
|
|
__packed uint8_t bNumConfigurations; /*!< Total number of configurations */
|
|
} DESC_DEV_T; /*!< device descriptor structure */
|
|
#else
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* USB device descriptor */
|
|
/*----------------------------------------------------------------------------------*/
|
|
typedef struct __attribute__((__packed__)) /*!< device descriptor structure */
|
|
{
|
|
uint8_t bLength; /*!< Length of device descriptor */
|
|
uint8_t bDescriptorType; /*!< Device descriptor type */
|
|
uint16_t bcdUSB; /*!< USB version number */
|
|
uint8_t bDeviceClass; /*!< Device class code */
|
|
uint8_t bDeviceSubClass; /*!< Device subclass code */
|
|
uint8_t bDeviceProtocol; /*!< Device protocol code */
|
|
uint8_t bMaxPacketSize0; /*!< Maximum packet size of control endpoint*/
|
|
uint16_t idVendor; /*!< Vendor ID */
|
|
uint16_t idProduct; /*!< Product ID */
|
|
uint16_t bcdDevice; /*!< Device ID */
|
|
uint8_t iManufacturer; /*!< Manufacture description string ID */
|
|
uint8_t iProduct; /*!< Product description string ID */
|
|
uint8_t iSerialNumber; /*!< Serial number description string ID */
|
|
uint8_t bNumConfigurations; /*!< Total number of configurations */
|
|
}
|
|
DESC_DEV_T; /*!< device descriptor structure */
|
|
#endif
|
|
|
|
/*
|
|
* Configuration Descriptor
|
|
*/
|
|
#ifdef __ICCARM__
|
|
typedef struct usb_config_descriptor /*!< Configuration descriptor structure */
|
|
{
|
|
__packed uint8_t bLength; /*!< Length of configuration descriptor */
|
|
__packed uint8_t bDescriptorType; /*!< Descriptor type */
|
|
__packed uint16_t wTotalLength; /*!< Total length of this configuration */
|
|
__packed uint8_t bNumInterfaces; /*!< Total number of interfaces */
|
|
__packed uint8_t bConfigurationValue; /*!< Configuration descriptor number */
|
|
__packed uint8_t iConfiguration; /*!< String descriptor ID */
|
|
__packed uint8_t bmAttributes; /*!< Configuration characteristics */
|
|
__packed uint8_t MaxPower; /*!< Maximum power consumption */
|
|
} DESC_CONF_T; /*!< Configuration descriptor structure */
|
|
#else
|
|
typedef struct __attribute__((__packed__)) usb_config_descriptor /*!< Configuration descriptor structure */
|
|
{
|
|
uint8_t bLength; /*!< Length of configuration descriptor */
|
|
uint8_t bDescriptorType; /*!< Descriptor type */
|
|
uint16_t wTotalLength; /*!< Total length of this configuration */
|
|
uint8_t bNumInterfaces; /*!< Total number of interfaces */
|
|
uint8_t bConfigurationValue; /*!< Configuration descriptor number */
|
|
uint8_t iConfiguration; /*!< String descriptor ID */
|
|
uint8_t bmAttributes; /*!< Configuration characteristics */
|
|
uint8_t MaxPower; /*!< Maximum power consumption */
|
|
} DESC_CONF_T; /*!< Configuration descriptor structure */
|
|
#endif
|
|
|
|
/*
|
|
* Interface Descriptor
|
|
*/
|
|
#ifdef __ICCARM__
|
|
typedef struct usb_interface_descriptor /*!< Interface descriptor structure */
|
|
{
|
|
__packed uint8_t bLength; /*!< Length of interface descriptor */
|
|
__packed uint8_t bDescriptorType; /*!< Descriptor type */
|
|
__packed uint8_t bInterfaceNumber; /*!< Interface number */
|
|
__packed uint8_t bAlternateSetting;/*!< Alternate setting number */
|
|
__packed uint8_t bNumEndpoints; /*!< Number of endpoints */
|
|
__packed uint8_t bInterfaceClass; /*!< Interface class code */
|
|
__packed uint8_t bInterfaceSubClass; /*!< Interface subclass code */
|
|
__packed uint8_t bInterfaceProtocol; /*!< Interface protocol code */
|
|
__packed uint8_t iInterface; /*!< Interface ID */
|
|
} DESC_IF_T; /*!< Interface descriptor structure */
|
|
#else
|
|
typedef struct __attribute__((__packed__)) usb_interface_descriptor /*!< Interface descriptor structure */
|
|
{
|
|
uint8_t bLength; /*!< Length of interface descriptor */
|
|
uint8_t bDescriptorType; /*!< Descriptor type */
|
|
uint8_t bInterfaceNumber; /*!< Interface number */
|
|
uint8_t bAlternateSetting; /*!< Alternate setting number */
|
|
uint8_t bNumEndpoints; /*!< Number of endpoints */
|
|
uint8_t bInterfaceClass; /*!< Interface class code */
|
|
uint8_t bInterfaceSubClass; /*!< Interface subclass code */
|
|
uint8_t bInterfaceProtocol; /*!< Interface protocol code */
|
|
uint8_t iInterface; /*!< Interface ID */
|
|
} DESC_IF_T; /*!< Interface descriptor structure */
|
|
#endif
|
|
|
|
/*
|
|
* Interface descriptor bInterfaceClass[7:0]
|
|
*/
|
|
#if 0
|
|
#define USB_CLASS_AUDIO 0x01
|
|
#define USB_CLASS_COMM 0x02
|
|
#define USB_CLASS_HID 0x03
|
|
#define USB_CLASS_PRINTER 0x07
|
|
#define USB_CLASS_MASS_STORAGE 0x08
|
|
#define USB_CLASS_HUB 0x09
|
|
#define USB_CLASS_DATA 0x0A
|
|
#define USB_CLASS_VIDEO 0x0E
|
|
#endif
|
|
/*
|
|
* Endpoint Descriptor
|
|
*/
|
|
#ifdef __ICCARM__
|
|
typedef struct usb_endpoint_descriptor /*!< Endpoint descriptor structure */
|
|
{
|
|
__packed uint8_t bLength; /*!< Length of endpoint descriptor */
|
|
__packed uint8_t bDescriptorType; /*!< Descriptor type */
|
|
__packed uint8_t bEndpointAddress; /*!< Endpoint address */
|
|
__packed uint8_t bmAttributes; /*!< Endpoint attribute */
|
|
__packed uint16_t wMaxPacketSize; /*!< Maximum packet size */
|
|
__packed uint8_t bInterval; /*!< Synchronous transfer interval */
|
|
__packed uint8_t bRefresh; /*!< Refresh */
|
|
__packed uint8_t bSynchAddress; /*!< Sync address */
|
|
} DESC_EP_T; /*!< Endpoint descriptor structure */
|
|
#else
|
|
typedef struct __attribute__((__packed__)) usb_endpoint_descriptor /*!< Endpoint descriptor structure */
|
|
{
|
|
uint8_t bLength; /*!< Length of endpoint descriptor */
|
|
uint8_t bDescriptorType; /*!< Descriptor type */
|
|
uint8_t bEndpointAddress; /*!< Endpoint address */
|
|
uint8_t bmAttributes; /*!< Endpoint attribute */
|
|
uint16_t wMaxPacketSize; /*!< Maximum packet size */
|
|
uint8_t bInterval; /*!< Synchronous transfer interval */
|
|
uint8_t bRefresh; /*!< Refresh */
|
|
uint8_t bSynchAddress; /*!< Sync address */
|
|
} DESC_EP_T; /*!< Endpoint descriptor structure */
|
|
#endif
|
|
|
|
/*
|
|
* Endpoint descriptor bEndpointAddress[7] - direction
|
|
*/
|
|
#define EP_ADDR_DIR_MASK 0x80
|
|
#define EP_ADDR_DIR_IN 0x80
|
|
#define EP_ADDR_DIR_OUT 0x00
|
|
|
|
/*
|
|
* Endpoint descriptor bmAttributes[1:0] - transfer type
|
|
*/
|
|
#define EP_ATTR_TT_MASK 0x03
|
|
#define EP_ATTR_TT_CTRL 0x00
|
|
#define EP_ATTR_TT_ISO 0x01
|
|
#define EP_ATTR_TT_BULK 0x02
|
|
#define EP_ATTR_TT_INT 0x03
|
|
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* USB Host controller driver */
|
|
/*----------------------------------------------------------------------------------*/
|
|
typedef struct
|
|
{
|
|
int (*init) (void);
|
|
void (*shutdown) (void);
|
|
void (*suspend) (void);
|
|
void (*resume) (void);
|
|
int (*ctrl_xfer)(struct utr_t *utr);
|
|
int (*bulk_xfer)(struct utr_t *utr);
|
|
int (*int_xfer)(struct utr_t *utr);
|
|
int (*iso_xfer)(struct utr_t *utr);
|
|
int (*quit_xfer)(struct utr_t *utr, struct ep_info_t *ep);
|
|
|
|
/* root hub support */
|
|
int (*rthub_port_reset)(int port);
|
|
int (*rthub_polling) (void);
|
|
} HC_DRV_T;
|
|
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* USB device driver */
|
|
/*----------------------------------------------------------------------------------*/
|
|
typedef struct
|
|
{
|
|
int (*probe) (struct iface_t *iface);
|
|
void (*disconnect) (struct iface_t *iface);
|
|
void (*suspend) (struct iface_t *iface);
|
|
void (*resume) (struct iface_t *iface);
|
|
} UDEV_DRV_T;
|
|
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* USB device */
|
|
/*----------------------------------------------------------------------------------*/
|
|
|
|
typedef enum
|
|
{
|
|
SPEED_LOW,
|
|
SPEED_FULL,
|
|
SPEED_HIGH
|
|
} SPEED_E;
|
|
|
|
typedef struct ep_info_t
|
|
{
|
|
uint8_t bEndpointAddress;
|
|
uint8_t bmAttributes;
|
|
uint8_t bInterval;
|
|
uint8_t bToggle;
|
|
uint16_t wMaxPacketSize;
|
|
void *hw_pipe; /*!< point to the HC assocaied endpoint \hideinitializer */
|
|
} EP_INFO_T;
|
|
|
|
typedef struct udev_t
|
|
{
|
|
DESC_DEV_T descriptor; /*!< Device descriptor. \hideinitializer */
|
|
struct hub_dev_t *parent; /*!< parent hub device \hideinitializer */
|
|
uint8_t port_num; /*!< The hub port this device connected on \hideinitializer */
|
|
uint8_t dev_num; /*!< device number \hideinitializer */
|
|
int8_t cur_conf; /*!< Currentll selected configuration \hideinitializer */
|
|
SPEED_E speed; /*!< device speed (low/full/high) \hideinitializer */
|
|
/*
|
|
* The followings are lightweight USB stack internal used .
|
|
*/
|
|
uint8_t *cfd_buff; /*!< Configuration descriptor buffer. \hideinitializer */
|
|
EP_INFO_T ep0; /*!< Endpoint 0 \hideinitializer */
|
|
HC_DRV_T *hc_driver; /*!< host controller driver \hideinitializer */
|
|
struct iface_t *iface_list; /*!< Working interface list \hideinitializer */
|
|
struct udev_t *next; /*!< link for global usb device list \hideinitializer */
|
|
} UDEV_T;
|
|
|
|
typedef struct alt_iface_t
|
|
{
|
|
DESC_IF_T *ifd; /*!< point to the location of this alternative interface descriptor in UDEV_T->cfd_buff */
|
|
EP_INFO_T ep[MAX_EP_PER_IFACE]; /*!< endpoints of this alternative interface */
|
|
} ALT_IFACE_T;
|
|
|
|
typedef struct iface_t
|
|
{
|
|
UDEV_T *udev; /*!< USB device \hideinitializer */
|
|
uint8_t if_num; /*!< Interface number \hideinitializer */
|
|
uint8_t num_alt; /*!< Number of alternative interface \hideinitializer */
|
|
ALT_IFACE_T *aif; /*!< Point to the active alternative interface */
|
|
ALT_IFACE_T alt[MAX_ALT_PER_IFACE]; /*!< List of alternative interface \hideinitializer */
|
|
UDEV_DRV_T *driver; /*!< Interface associated driver \hideinitializer */
|
|
void *context; /*!< Reference to device context \hideinitializer */
|
|
struct iface_t *next; /*!< Point to next interface of the same device. Started from UDEV_T->iface_list \hideinitializer */
|
|
} IFACE_T;
|
|
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* URB (USB Request Block) */
|
|
/*----------------------------------------------------------------------------------*/
|
|
|
|
#define IF_PER_UTR 8 /* number of frames per UTR isochronous transfer (DO NOT modify it!) */
|
|
|
|
typedef void (*FUNC_UTR_T)(struct utr_t *);
|
|
|
|
typedef struct utr_t
|
|
{
|
|
UDEV_T *udev; /*!< point to associated USB device \hideinitializer */
|
|
DEV_REQ_T setup; /*!< buffer for setup packet \hideinitializer */
|
|
EP_INFO_T *ep; /*!< associated endpoint \hideinitializer */
|
|
uint8_t *buff; /*!< transfer buffer \hideinitializer */
|
|
uint8_t bIsTransferDone; /*!< tansfer done? \hideinitializer */
|
|
uint32_t data_len; /*!< length of data to be transferred \hideinitializer */
|
|
uint32_t xfer_len; /*!< length of transferred data \hideinitializer */
|
|
uint8_t bIsoNewSched; /*!< New schedule isochronous transfer \hideinitializer */
|
|
uint16_t iso_sf; /*!< Isochronous start frame number \hideinitializer */
|
|
uint16_t iso_xlen[IF_PER_UTR]; /*!< transfer length of isochronous frames \hideinitializer */
|
|
uint8_t * iso_buff[IF_PER_UTR]; /*!< transfer buffer address of isochronous frames \hideinitializer */
|
|
int iso_status[IF_PER_UTR]; /*!< transfer status of isochronous frames \hideinitializer */
|
|
int td_cnt; /*!< number of transfer descriptors \hideinitializer */
|
|
int status; /*!< return status \hideinitializer */
|
|
int interval; /*!< interrupt/isochronous interval \hideinitializer */
|
|
void *context; /*!< point to deivce proprietary data area \hideinitializer */
|
|
FUNC_UTR_T func; /*!< tansfer done call-back function \hideinitializer */
|
|
struct utr_t *next; /* point to the next UTR of the same endpoint. \hideinitializer */
|
|
} UTR_T;
|
|
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* Global variables */
|
|
/*----------------------------------------------------------------------------------*/
|
|
extern USBH_T *_ohci;
|
|
|
|
extern HC_DRV_T ohci_driver;
|
|
|
|
extern UDEV_T * g_udev_list;
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/* USB stack exported functions */
|
|
/*----------------------------------------------------------------------------------*/
|
|
extern void usbh_delay_ms(int msec);
|
|
|
|
extern void dump_ohci_regs(void);
|
|
extern void dump_ohci_ports(void);
|
|
extern void dump_ohci_int_table(void);
|
|
extern void usbh_dump_buff_bytes(uint8_t *buff, int nSize);
|
|
extern void usbh_dump_interface_descriptor(DESC_IF_T *if_desc);
|
|
extern void usbh_dump_endpoint_descriptor(DESC_EP_T *ep_desc);
|
|
extern void usbh_dump_iface(IFACE_T *iface);
|
|
extern void usbh_dump_ep_info(EP_INFO_T *ep);
|
|
|
|
/*
|
|
* Memory management functions
|
|
*/
|
|
extern void usbh_memory_init(void);
|
|
extern uint32_t usbh_memory_used(void);
|
|
extern void * usbh_alloc_mem(int size);
|
|
extern void usbh_free_mem(void *p, int size);
|
|
extern int alloc_dev_address(void);
|
|
extern void free_dev_address(int dev_addr);
|
|
extern UDEV_T * alloc_device(void);
|
|
extern void free_device(UDEV_T *udev);
|
|
extern UTR_T * alloc_utr(UDEV_T *udev);
|
|
extern void free_utr(UTR_T *utr);
|
|
extern ED_T * alloc_ohci_ED(void);
|
|
extern void free_ohci_ED(ED_T *ed);
|
|
extern TD_T * alloc_ohci_TD(UTR_T *utr);
|
|
extern void free_ohci_TD(TD_T *td);
|
|
|
|
|
|
extern void usbh_hub_init(void);
|
|
extern int usbh_connect_device(UDEV_T *);
|
|
extern void usbh_disconnect_device(UDEV_T *);
|
|
extern int usbh_register_driver(UDEV_DRV_T *driver);
|
|
extern EP_INFO_T * usbh_iface_find_ep(IFACE_T *iface, uint8_t ep_addr, uint8_t dir_type);
|
|
extern int usbh_reset_device(UDEV_T *);
|
|
extern int usbh_reset_port(UDEV_T *);
|
|
|
|
/*
|
|
* USB Standard Request functions
|
|
*/
|
|
extern int usbh_get_device_descriptor(UDEV_T *udev, DESC_DEV_T *desc_buff);
|
|
extern int usbh_get_config_descriptor(UDEV_T *udev, uint8_t *desc_buff, int buff_len);
|
|
extern int usbh_set_configuration(UDEV_T *udev, uint8_t conf_val);
|
|
extern int usbh_set_interface(IFACE_T *iface, uint16_t alt_setting);
|
|
extern int usbh_clear_halt(UDEV_T *udev, uint16_t ep_addr);
|
|
|
|
extern int usbh_ctrl_xfer(UDEV_T *udev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t *buff, uint32_t *xfer_len, uint32_t timeout);
|
|
extern int usbh_bulk_xfer(UTR_T *utr);
|
|
extern int usbh_int_xfer(UTR_T *utr);
|
|
extern int usbh_iso_xfer(UTR_T *utr);
|
|
extern int usbh_quit_utr(UTR_T *utr);
|
|
extern int usbh_quit_xfer(UDEV_T *udev, EP_INFO_T *ep);
|
|
|
|
|
|
/// @endcond HIDDEN_SYMBOLS
|
|
|
|
#endif /* _USBH_H_ */
|