1*54fd6939SJiyong Park /* 2*54fd6939SJiyong Park * Copyright (c) 2021, STMicroelectronics - All Rights Reserved 3*54fd6939SJiyong Park * 4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause 5*54fd6939SJiyong Park */ 6*54fd6939SJiyong Park 7*54fd6939SJiyong Park #ifndef USB_DEVICE_H 8*54fd6939SJiyong Park #define USB_DEVICE_H 9*54fd6939SJiyong Park 10*54fd6939SJiyong Park #include <stdint.h> 11*54fd6939SJiyong Park 12*54fd6939SJiyong Park #include <lib/utils_def.h> 13*54fd6939SJiyong Park 14*54fd6939SJiyong Park #define USBD_MAX_NUM_INTERFACES 1U 15*54fd6939SJiyong Park #define USBD_MAX_NUM_CONFIGURATION 1U 16*54fd6939SJiyong Park 17*54fd6939SJiyong Park #define USB_LEN_DEV_QUALIFIER_DESC 0x0AU 18*54fd6939SJiyong Park #define USB_LEN_DEV_DESC 0x12U 19*54fd6939SJiyong Park #define USB_LEN_CFG_DESC 0x09U 20*54fd6939SJiyong Park #define USB_LEN_IF_DESC 0x09U 21*54fd6939SJiyong Park #define USB_LEN_EP_DESC 0x07U 22*54fd6939SJiyong Park #define USB_LEN_OTG_DESC 0x03U 23*54fd6939SJiyong Park #define USB_LEN_LANGID_STR_DESC 0x04U 24*54fd6939SJiyong Park #define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09U 25*54fd6939SJiyong Park 26*54fd6939SJiyong Park #define USBD_IDX_LANGID_STR 0x00U 27*54fd6939SJiyong Park #define USBD_IDX_MFC_STR 0x01U 28*54fd6939SJiyong Park #define USBD_IDX_PRODUCT_STR 0x02U 29*54fd6939SJiyong Park #define USBD_IDX_SERIAL_STR 0x03U 30*54fd6939SJiyong Park #define USBD_IDX_CONFIG_STR 0x04U 31*54fd6939SJiyong Park #define USBD_IDX_INTERFACE_STR 0x05U 32*54fd6939SJiyong Park #define USBD_IDX_USER0_STR 0x06U 33*54fd6939SJiyong Park 34*54fd6939SJiyong Park #define USB_REQ_TYPE_STANDARD 0x00U 35*54fd6939SJiyong Park #define USB_REQ_TYPE_CLASS 0x20U 36*54fd6939SJiyong Park #define USB_REQ_TYPE_VENDOR 0x40U 37*54fd6939SJiyong Park #define USB_REQ_TYPE_MASK 0x60U 38*54fd6939SJiyong Park 39*54fd6939SJiyong Park #define USB_REQ_RECIPIENT_DEVICE 0x00U 40*54fd6939SJiyong Park #define USB_REQ_RECIPIENT_INTERFACE 0x01U 41*54fd6939SJiyong Park #define USB_REQ_RECIPIENT_ENDPOINT 0x02U 42*54fd6939SJiyong Park #define USB_REQ_RECIPIENT_MASK 0x1FU 43*54fd6939SJiyong Park 44*54fd6939SJiyong Park #define USB_REQ_DIRECTION 0x80U 45*54fd6939SJiyong Park 46*54fd6939SJiyong Park #define USB_REQ_GET_STATUS 0x00U 47*54fd6939SJiyong Park #define USB_REQ_CLEAR_FEATURE 0x01U 48*54fd6939SJiyong Park #define USB_REQ_SET_FEATURE 0x03U 49*54fd6939SJiyong Park #define USB_REQ_SET_ADDRESS 0x05U 50*54fd6939SJiyong Park #define USB_REQ_GET_DESCRIPTOR 0x06U 51*54fd6939SJiyong Park #define USB_REQ_SET_DESCRIPTOR 0x07U 52*54fd6939SJiyong Park #define USB_REQ_GET_CONFIGURATION 0x08U 53*54fd6939SJiyong Park #define USB_REQ_SET_CONFIGURATION 0x09U 54*54fd6939SJiyong Park #define USB_REQ_GET_INTERFACE 0x0AU 55*54fd6939SJiyong Park #define USB_REQ_SET_INTERFACE 0x0BU 56*54fd6939SJiyong Park #define USB_REQ_SYNCH_FRAME 0x0CU 57*54fd6939SJiyong Park 58*54fd6939SJiyong Park #define USB_DESC_TYPE_DEVICE 0x01U 59*54fd6939SJiyong Park #define USB_DESC_TYPE_CONFIGURATION 0x02U 60*54fd6939SJiyong Park #define USB_DESC_TYPE_STRING 0x03U 61*54fd6939SJiyong Park #define USB_DESC_TYPE_INTERFACE 0x04U 62*54fd6939SJiyong Park #define USB_DESC_TYPE_ENDPOINT 0x05U 63*54fd6939SJiyong Park #define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U 64*54fd6939SJiyong Park #define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U 65*54fd6939SJiyong Park #define USB_DESC_TYPE_BOS 0x0FU 66*54fd6939SJiyong Park 67*54fd6939SJiyong Park #define USB_CONFIG_REMOTE_WAKEUP 2U 68*54fd6939SJiyong Park #define USB_CONFIG_SELF_POWERED 1U 69*54fd6939SJiyong Park 70*54fd6939SJiyong Park #define USB_MAX_EP0_SIZE 64U 71*54fd6939SJiyong Park 72*54fd6939SJiyong Park /* Device Status */ 73*54fd6939SJiyong Park #define USBD_STATE_DEFAULT 1U 74*54fd6939SJiyong Park #define USBD_STATE_ADDRESSED 2U 75*54fd6939SJiyong Park #define USBD_STATE_CONFIGURED 3U 76*54fd6939SJiyong Park #define USBD_STATE_SUSPENDED 4U 77*54fd6939SJiyong Park 78*54fd6939SJiyong Park /* EP0 State */ 79*54fd6939SJiyong Park #define USBD_EP0_IDLE 0U 80*54fd6939SJiyong Park #define USBD_EP0_SETUP 1U 81*54fd6939SJiyong Park #define USBD_EP0_DATA_IN 2U 82*54fd6939SJiyong Park #define USBD_EP0_DATA_OUT 3U 83*54fd6939SJiyong Park #define USBD_EP0_STATUS_IN 4U 84*54fd6939SJiyong Park #define USBD_EP0_STATUS_OUT 5U 85*54fd6939SJiyong Park #define USBD_EP0_STALL 6U 86*54fd6939SJiyong Park 87*54fd6939SJiyong Park #define USBD_EP_TYPE_CTRL 0U 88*54fd6939SJiyong Park #define USBD_EP_TYPE_ISOC 1U 89*54fd6939SJiyong Park #define USBD_EP_TYPE_BULK 2U 90*54fd6939SJiyong Park #define USBD_EP_TYPE_INTR 3U 91*54fd6939SJiyong Park 92*54fd6939SJiyong Park #define USBD_OUT_EPNUM_MASK GENMASK(15, 0) 93*54fd6939SJiyong Park #define USBD_OUT_COUNT_MASK GENMASK(31, 16) 94*54fd6939SJiyong Park #define USBD_OUT_COUNT_SHIFT 16U 95*54fd6939SJiyong Park 96*54fd6939SJiyong Park /* Number of EP supported, allow to reduce footprint: default max = 15 */ 97*54fd6939SJiyong Park #ifndef CONFIG_USBD_EP_NB 98*54fd6939SJiyong Park #define USBD_EP_NB 15U 99*54fd6939SJiyong Park #else 100*54fd6939SJiyong Park #define USBD_EP_NB CONFIG_USBD_EP_NB 101*54fd6939SJiyong Park #endif 102*54fd6939SJiyong Park 103*54fd6939SJiyong Park #define LOBYTE(x) ((uint8_t)((x) & 0x00FF)) 104*54fd6939SJiyong Park #define HIBYTE(x) ((uint8_t)(((x) & 0xFF00) >> 8)) 105*54fd6939SJiyong Park 106*54fd6939SJiyong Park struct usb_setup_req { 107*54fd6939SJiyong Park uint8_t bm_request; 108*54fd6939SJiyong Park uint8_t b_request; 109*54fd6939SJiyong Park uint16_t value; 110*54fd6939SJiyong Park uint16_t index; 111*54fd6939SJiyong Park uint16_t length; 112*54fd6939SJiyong Park }; 113*54fd6939SJiyong Park 114*54fd6939SJiyong Park struct usb_handle; 115*54fd6939SJiyong Park 116*54fd6939SJiyong Park struct usb_class { 117*54fd6939SJiyong Park uint8_t (*init)(struct usb_handle *pdev, uint8_t cfgidx); 118*54fd6939SJiyong Park uint8_t (*de_init)(struct usb_handle *pdev, uint8_t cfgidx); 119*54fd6939SJiyong Park /* Control Endpoints */ 120*54fd6939SJiyong Park uint8_t (*setup)(struct usb_handle *pdev, struct usb_setup_req *req); 121*54fd6939SJiyong Park uint8_t (*ep0_tx_sent)(struct usb_handle *pdev); 122*54fd6939SJiyong Park uint8_t (*ep0_rx_ready)(struct usb_handle *pdev); 123*54fd6939SJiyong Park /* Class Specific Endpoints */ 124*54fd6939SJiyong Park uint8_t (*data_in)(struct usb_handle *pdev, uint8_t epnum); 125*54fd6939SJiyong Park uint8_t (*data_out)(struct usb_handle *pdev, uint8_t epnum); 126*54fd6939SJiyong Park uint8_t (*sof)(struct usb_handle *pdev); 127*54fd6939SJiyong Park uint8_t (*iso_in_incomplete)(struct usb_handle *pdev, uint8_t epnum); 128*54fd6939SJiyong Park uint8_t (*iso_out_incomplete)(struct usb_handle *pdev, uint8_t epnum); 129*54fd6939SJiyong Park }; 130*54fd6939SJiyong Park 131*54fd6939SJiyong Park /* Following USB Device status */ 132*54fd6939SJiyong Park enum usb_status { 133*54fd6939SJiyong Park USBD_OK = 0U, 134*54fd6939SJiyong Park USBD_BUSY, 135*54fd6939SJiyong Park USBD_FAIL, 136*54fd6939SJiyong Park USBD_TIMEOUT 137*54fd6939SJiyong Park }; 138*54fd6939SJiyong Park 139*54fd6939SJiyong Park /* Action to do after IT handling */ 140*54fd6939SJiyong Park enum usb_action { 141*54fd6939SJiyong Park USB_NOTHING = 0U, 142*54fd6939SJiyong Park USB_DATA_OUT, 143*54fd6939SJiyong Park USB_DATA_IN, 144*54fd6939SJiyong Park USB_SETUP, 145*54fd6939SJiyong Park USB_ENUM_DONE, 146*54fd6939SJiyong Park USB_READ_DATA_PACKET, 147*54fd6939SJiyong Park USB_READ_SETUP_PACKET, 148*54fd6939SJiyong Park USB_RESET, 149*54fd6939SJiyong Park USB_RESUME, 150*54fd6939SJiyong Park USB_SUSPEND, 151*54fd6939SJiyong Park USB_LPM, 152*54fd6939SJiyong Park USB_SOF, 153*54fd6939SJiyong Park USB_DISCONNECT, 154*54fd6939SJiyong Park USB_WRITE_EMPTY 155*54fd6939SJiyong Park }; 156*54fd6939SJiyong Park 157*54fd6939SJiyong Park /* USB Device descriptors structure */ 158*54fd6939SJiyong Park struct usb_desc { 159*54fd6939SJiyong Park uint8_t *(*get_device_desc)(uint16_t *length); 160*54fd6939SJiyong Park uint8_t *(*get_lang_id_desc)(uint16_t *length); 161*54fd6939SJiyong Park uint8_t *(*get_manufacturer_desc)(uint16_t *length); 162*54fd6939SJiyong Park uint8_t *(*get_product_desc)(uint16_t *length); 163*54fd6939SJiyong Park uint8_t *(*get_serial_desc)(uint16_t *length); 164*54fd6939SJiyong Park uint8_t *(*get_configuration_desc)(uint16_t *length); 165*54fd6939SJiyong Park uint8_t *(*get_interface_desc)(uint16_t *length); 166*54fd6939SJiyong Park uint8_t *(*get_usr_desc)(uint8_t index, uint16_t *length); 167*54fd6939SJiyong Park uint8_t *(*get_config_desc)(uint16_t *length); 168*54fd6939SJiyong Park uint8_t *(*get_device_qualifier_desc)(uint16_t *length); 169*54fd6939SJiyong Park /* optional: high speed capable device operating at its other speed */ 170*54fd6939SJiyong Park uint8_t *(*get_other_speed_config_desc)(uint16_t *length); 171*54fd6939SJiyong Park }; 172*54fd6939SJiyong Park 173*54fd6939SJiyong Park /* USB Device handle structure */ 174*54fd6939SJiyong Park struct usb_endpoint { 175*54fd6939SJiyong Park uint32_t status; 176*54fd6939SJiyong Park uint32_t total_length; 177*54fd6939SJiyong Park uint32_t rem_length; 178*54fd6939SJiyong Park uint32_t maxpacket; 179*54fd6939SJiyong Park }; 180*54fd6939SJiyong Park 181*54fd6939SJiyong Park /* 182*54fd6939SJiyong Park * EndPoint descriptor 183*54fd6939SJiyong Park * num : Endpoint number, between 0 and 15 (limited by USBD_EP_NB) 184*54fd6939SJiyong Park * is_in: Endpoint direction 185*54fd6939SJiyong Park * type : Endpoint type 186*54fd6939SJiyong Park * maxpacket: Endpoint Max packet size: between 0 and 64KB 187*54fd6939SJiyong Park * xfer_buff: Pointer to transfer buffer 188*54fd6939SJiyong Park * xfer_len: Current transfer lengt 189*54fd6939SJiyong Park * hxfer_count: Partial transfer length in case of multi packet transfer 190*54fd6939SJiyong Park */ 191*54fd6939SJiyong Park struct usbd_ep { 192*54fd6939SJiyong Park uint8_t num; 193*54fd6939SJiyong Park bool is_in; 194*54fd6939SJiyong Park uint8_t type; 195*54fd6939SJiyong Park uint32_t maxpacket; 196*54fd6939SJiyong Park uint8_t *xfer_buff; 197*54fd6939SJiyong Park uint32_t xfer_len; 198*54fd6939SJiyong Park uint32_t xfer_count; 199*54fd6939SJiyong Park }; 200*54fd6939SJiyong Park 201*54fd6939SJiyong Park enum pcd_lpm_state { 202*54fd6939SJiyong Park LPM_L0 = 0x00U, /* on */ 203*54fd6939SJiyong Park LPM_L1 = 0x01U, /* LPM L1 sleep */ 204*54fd6939SJiyong Park LPM_L2 = 0x02U, /* suspend */ 205*54fd6939SJiyong Park LPM_L3 = 0x03U, /* off */ 206*54fd6939SJiyong Park }; 207*54fd6939SJiyong Park 208*54fd6939SJiyong Park /* USB Device descriptors structure */ 209*54fd6939SJiyong Park struct usb_driver { 210*54fd6939SJiyong Park enum usb_status (*ep0_out_start)(void *handle); 211*54fd6939SJiyong Park enum usb_status (*ep_start_xfer)(void *handle, struct usbd_ep *ep); 212*54fd6939SJiyong Park enum usb_status (*ep0_start_xfer)(void *handle, struct usbd_ep *ep); 213*54fd6939SJiyong Park enum usb_status (*write_packet)(void *handle, uint8_t *src, 214*54fd6939SJiyong Park uint8_t ch_ep_num, uint16_t len); 215*54fd6939SJiyong Park void *(*read_packet)(void *handle, uint8_t *dest, uint16_t len); 216*54fd6939SJiyong Park enum usb_status (*ep_set_stall)(void *handle, struct usbd_ep *ep); 217*54fd6939SJiyong Park enum usb_status (*start_device)(void *handle); 218*54fd6939SJiyong Park enum usb_status (*stop_device)(void *handle); 219*54fd6939SJiyong Park enum usb_status (*set_address)(void *handle, uint8_t address); 220*54fd6939SJiyong Park enum usb_status (*write_empty_tx_fifo)(void *handle, 221*54fd6939SJiyong Park uint32_t epnum, uint32_t xfer_len, 222*54fd6939SJiyong Park uint32_t *xfer_count, 223*54fd6939SJiyong Park uint32_t maxpacket, 224*54fd6939SJiyong Park uint8_t **xfer_buff); 225*54fd6939SJiyong Park enum usb_action (*it_handler)(void *handle, uint32_t *param); 226*54fd6939SJiyong Park }; 227*54fd6939SJiyong Park 228*54fd6939SJiyong Park /* USB Peripheral Controller Drivers */ 229*54fd6939SJiyong Park struct pcd_handle { 230*54fd6939SJiyong Park void *instance; /* Register base address */ 231*54fd6939SJiyong Park struct usbd_ep in_ep[USBD_EP_NB]; /* IN endpoint parameters */ 232*54fd6939SJiyong Park struct usbd_ep out_ep[USBD_EP_NB]; /* OUT endpoint parameters */ 233*54fd6939SJiyong Park uint32_t setup[12]; /* Setup packet buffer */ 234*54fd6939SJiyong Park enum pcd_lpm_state lpm_state; /* LPM State */ 235*54fd6939SJiyong Park }; 236*54fd6939SJiyong Park 237*54fd6939SJiyong Park /* USB Device handle structure */ 238*54fd6939SJiyong Park struct usb_handle { 239*54fd6939SJiyong Park uint8_t id; 240*54fd6939SJiyong Park uint32_t dev_config; 241*54fd6939SJiyong Park uint32_t dev_config_status; 242*54fd6939SJiyong Park struct usb_endpoint ep_in[USBD_EP_NB]; 243*54fd6939SJiyong Park struct usb_endpoint ep_out[USBD_EP_NB]; 244*54fd6939SJiyong Park uint32_t ep0_state; 245*54fd6939SJiyong Park uint32_t ep0_data_len; 246*54fd6939SJiyong Park uint8_t dev_state; 247*54fd6939SJiyong Park uint8_t dev_old_state; 248*54fd6939SJiyong Park uint8_t dev_address; 249*54fd6939SJiyong Park uint32_t dev_remote_wakeup; 250*54fd6939SJiyong Park struct usb_setup_req request; 251*54fd6939SJiyong Park const struct usb_desc *desc; 252*54fd6939SJiyong Park struct usb_class *class; 253*54fd6939SJiyong Park void *class_data; 254*54fd6939SJiyong Park void *user_data; 255*54fd6939SJiyong Park struct pcd_handle *data; 256*54fd6939SJiyong Park const struct usb_driver *driver; 257*54fd6939SJiyong Park }; 258*54fd6939SJiyong Park 259*54fd6939SJiyong Park enum usb_status usb_core_handle_it(struct usb_handle *pdev); 260*54fd6939SJiyong Park enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr, 261*54fd6939SJiyong Park uint8_t *p_buf, uint32_t len); 262*54fd6939SJiyong Park enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr, 263*54fd6939SJiyong Park uint8_t *p_buf, uint32_t len); 264*54fd6939SJiyong Park enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *p_buf, 265*54fd6939SJiyong Park uint32_t len); 266*54fd6939SJiyong Park enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *p_buf, 267*54fd6939SJiyong Park uint32_t len); 268*54fd6939SJiyong Park void usb_core_ctl_error(struct usb_handle *pdev); 269*54fd6939SJiyong Park enum usb_status usb_core_start(struct usb_handle *pdev); 270*54fd6939SJiyong Park enum usb_status usb_core_stop(struct usb_handle *pdev); 271*54fd6939SJiyong Park enum usb_status register_usb_driver(struct usb_handle *pdev, 272*54fd6939SJiyong Park struct pcd_handle *pcd_handle, 273*54fd6939SJiyong Park const struct usb_driver *driver, 274*54fd6939SJiyong Park void *driver_handle); 275*54fd6939SJiyong Park enum usb_status register_platform(struct usb_handle *pdev, 276*54fd6939SJiyong Park const struct usb_desc *plat_call_back); 277*54fd6939SJiyong Park 278*54fd6939SJiyong Park #endif /* USB_DEVICE_H */ 279