/* * Copyright (c) 2020 Actions Corporation. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief useful constants and macros for the USB controller * * This file contains useful constants and macros for the USB controller. */ #ifndef __USB_H__ #define __USB_H__ /* * USB directions * * This bit flag is used in endpoint descriptors' bEndpointAddress field. * It's also one of three fields in control requests bRequestType. */ #define USB_DIR_OUT 0x00 /* to device */ #define USB_DIR_IN 0x80 /* to host */ /* * NOTE: USB types, recipients, Standard requests, feature flags are also * defined in usb/usbstruct.h (with device names), it is more reasonable * to place here. */ /* * USB types, the second of three bRequestType fields */ #define USB_TYPE_MASK (0x03 << 5) #define USB_TYPE_STANDARD (0x00 << 5) #define USB_TYPE_CLASS (0x01 << 5) #define USB_TYPE_VENDOR (0x02 << 5) #define USB_TYPE_RESERVED (0x03 << 5) /* * USB recipients, the third of three bRequestType fields */ #define USB_RECIP_MASK 0x1f #define USB_RECIP_DEVICE 0x00 #define USB_RECIP_INTERFACE 0x01 #define USB_RECIP_ENDPOINT 0x02 #define USB_RECIP_OTHER 0x03 /* From Wireless USB 1.0 */ #define USB_RECIP_PORT 0x04 #define USB_RECIP_RPIPE 0x05 /* * Standard requests, for the bRequest field of a SETUP packet. * * These are qualified by the bRequestType field, so that for example * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved * by a GET_STATUS request. */ #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_DESCRIPTOR 0x07 #define USB_REQ_GET_CONFIGURATION 0x08 #define USB_REQ_SET_CONFIGURATION 0x09 #define USB_REQ_GET_INTERFACE 0x0A #define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SYNCH_FRAME 0x0C #define USB_REQ_SET_SEL 0x30 #define USB_REQ_SET_ISOCH_DELAY 0x31 #define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ #define USB_REQ_GET_ENCRYPTION 0x0E #define USB_REQ_RPIPE_ABORT 0x0E #define USB_REQ_SET_HANDSHAKE 0x0F #define USB_REQ_RPIPE_RESET 0x0F #define USB_REQ_GET_HANDSHAKE 0x10 #define USB_REQ_SET_CONNECTION 0x11 #define USB_REQ_SET_SECURITY_DATA 0x12 #define USB_REQ_GET_SECURITY_DATA 0x13 #define USB_REQ_SET_WUSB_DATA 0x14 #define USB_REQ_LOOPBACK_DATA_WRITE 0x15 #define USB_REQ_LOOPBACK_DATA_READ 0x16 #define USB_REQ_SET_INTERFACE_DS 0x17 /* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command, * used by hubs to put ports into a new L1 suspend state, except that it * forgot to define its number ... */ /* * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and * are read as a bit array returned by USB_REQ_GET_STATUS. (So there * are at most sixteen features of each type.) Hubs may also support a * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend. */ #define USB_DEVICE_SELF_POWERED 0 /* (read only) */ #define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ #define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ #define USB_DEVICE_BATTERY 2 /* (wireless) */ #define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ #define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ #define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ #define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ #define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ /* * Test Mode Selectors * See USB 2.0 spec Table 9-7 */ #define TEST_J 1 #define TEST_K 2 #define TEST_SE0_NAK 3 #define TEST_PACKET 4 #define TEST_FORCE_EN 5 /** setup packet definitions */ struct usb_setup_packet { uint8_t bmRequestType; /**< characteristics of the specific request */ uint8_t bRequest; /**< specific request */ uint16_t wValue; /**< request specific parameter */ uint16_t wIndex; /**< request specific parameter */ uint16_t wLength; /**< length of data transferred in data phase */ } __packed; #define USB_REQ_DIR_IN(bmRequestType) (bmRequestType & USB_DIR_IN) /* * Endpoints */ #define USB_EP_NUM_MASK 0x07 /* in bEndpointAddress */ #define USB_EP_DIR_MASK 0x80 /* Default USB control EP */ #define USB_CONTROL_OUT_EP0 0 #define USB_CONTROL_IN_EP0 0x80 /* For compatibility */ #define USB_EP_DIR_IN USB_DIR_IN #define USB_EP_DIR_OUT USB_DIR_OUT /* Convert from endpoint address to hardware endpoint index */ #define USB_EP_ADDR2IDX(ep) ((ep) & USB_EP_NUM_MASK) /* Get direction from endpoint address */ #define USB_EP_ADDR2DIR(ep) ((ep) & USB_EP_DIR_MASK) /* Convert from hardware endpoint index and direction to endpoint address */ #define USB_EP_IDX2ADDR(idx, dir) ((idx) | ((dir) & USB_EP_DIR_MASK)) /* If endpoint direction is out */ #define USB_EP_DIR_IS_OUT(ep) (USB_EP_ADDR2DIR(ep) == USB_EP_DIR_OUT) /* If endpoint direction is in */ #define USB_EP_DIR_IS_IN(ep) (USB_EP_ADDR2DIR(ep) == USB_EP_DIR_IN) static inline uint8_t usb_endpoint_num(const uint8_t ep) { return ep & USB_EP_NUM_MASK; } static inline bool usb_ep_dir_in(const uint8_t ep) { return ((ep & USB_EP_DIR_MASK) == USB_EP_DIR_IN); } static inline bool usb_ep_dir_out(const uint8_t ep) { return ((ep & USB_EP_DIR_MASK) == USB_EP_DIR_OUT); } #define USB_EP_TYPE_MASK 0x03 /* in bmAttributes */ enum usb_ep_type { USB_EP_CONTROL = 0, /* Control type endpoint */ USB_EP_ISOCHRONOUS, /* Isochronous type endpoint */ USB_EP_BULK, /* Bulk type endpoint */ USB_EP_INTERRUPT /* Interrupt type endpoint */ }; /* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */ #define USB_EP_INTRTYPE 0x30 #define USB_EP_INTR_PERIODIC (0 << 4) #define USB_EP_INTR_NOTIFICATION (1 << 4) #define USB_EP_SYNCTYPE 0x0c #define USB_EP_SYNC_NONE (0 << 2) #define USB_EP_SYNC_ASYNC (1 << 2) #define USB_EP_SYNC_ADAPTIVE (2 << 2) #define USB_EP_SYNC_SYNC (3 << 2) #define USB_EP_USAGE_MASK 0x30 #define USB_EP_USAGE_DATA 0x00 #define USB_EP_USAGE_FEEDBACK 0x10 #define USB_EP_USAGE_IMPLICIT_FB 0x20 /* Implicit feedback Data endpoint */ static inline enum usb_ep_type usb_endpoint_type(uint8_t bmAttributes) { return bmAttributes & USB_EP_TYPE_MASK; } static inline int usb_endpoint_xfer_bulk(uint8_t bmAttributes) { return ((bmAttributes & USB_EP_TYPE_MASK) == USB_EP_BULK); } static inline int usb_endpoint_xfer_control(uint8_t bmAttributes) { return ((bmAttributes & USB_EP_TYPE_MASK) == USB_EP_CONTROL); } static inline int usb_endpoint_xfer_int(uint8_t bmAttributes) { return ((bmAttributes & USB_EP_TYPE_MASK) == USB_EP_INTERRUPT); } static inline int usb_endpoint_xfer_isoc(uint8_t bmAttributes) { return ((bmAttributes & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS); } /* * USB endpoint max packet size. */ #define USB_MAX_FS_BULK_MPS 64 /**< full speed MPS for bulk EP */ #define USB_MAX_FS_INTR_MPS 64 /**< full speed MPS for interrupt EP */ #define USB_MAX_FS_ISOC_MPS 1023 /**< full speed MPS for isochronous EP */ #define USB_MAX_HS_BULK_MPS 512 /**< high speed MPS for bulk EP */ #define USB_MAX_HS_INTR_MPS 1024 /**< high speed MPS for interrupt EP */ #define USB_MAX_HS_ISOC_MPS 1024 /**< high speed MPS for isochronous EP */ #define MAX_PACKET_SIZE0 64 /**< maximum packet size for EP 0 */ #define USB_MAX_CTRL_MPS MAX_PACKET_SIZE0 /* alias */ enum usb_device_state { /* NOTATTACHED isn't in the USB spec, and this state acts * the same as ATTACHED ... but it's clearer this way. */ USB_STATE_NOTATTACHED = 0, /* chapter 9 and authentication (wireless) device states */ USB_STATE_ATTACHED, USB_STATE_POWERED, /* wired */ USB_STATE_RECONNECTING, /* auth */ USB_STATE_UNAUTHENTICATED, /* auth */ USB_STATE_DEFAULT, /* limited function */ USB_STATE_ADDRESS, USB_STATE_CONFIGURED, /* most functions */ USB_STATE_SUSPENDED /* NOTE: there are actually four different SUSPENDED * states, returning to POWERED, DEFAULT, ADDRESS, or * CONFIGURED respectively when SOF tokens flow again. * At this level there's no difference between L1 and L2 * suspend states. (L2 being original USB 1.1 suspend.) */ }; /* * USB Device Speed */ enum usb_device_speed { USB_SPEED_UNKNOWN = 0, /* enumerating */ USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ USB_SPEED_HIGH, /* usb 2.0 */ USB_SPEED_WIRELESS, /* wireless (usb 2.5) */ USB_SPEED_SUPER, /* usb 3.0 */ }; #endif /* __USB_H__ */