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