diff options
| author | jzlv <[email protected]> | 2021-07-10 18:31:58 +0800 |
|---|---|---|
| committer | jzlv <[email protected]> | 2021-07-10 18:31:58 +0800 |
| commit | 8a143df5094b0b1db72c8b9c3120cfc390b54c50 (patch) | |
| tree | eb1e18cb31abc4fafb45b5b7e6cf25f2d15a5932 /common | |
first commit
Diffstat (limited to 'common')
| -rw-r--r-- | common/usb_dc.h | 179 | ||||
| -rw-r--r-- | common/usb_def.h | 522 | ||||
| -rw-r--r-- | common/usb_slist.h | 224 | ||||
| -rw-r--r-- | common/usb_util.h | 131 |
4 files changed, 1056 insertions, 0 deletions
diff --git a/common/usb_dc.h b/common/usb_dc.h new file mode 100644 index 00000000..ea57fcde --- /dev/null +++ b/common/usb_dc.h @@ -0,0 +1,179 @@ +#ifndef _USB_DC_H
+#define _USB_DC_H
+
+#include "stdint.h"
+#include "bflb_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief USB Device Controller API
+ * @defgroup _usb_device_controller_api USB Device Controller API
+ * @{
+ */
+/**< maximum packet size (MPS) for EP 0 */
+#define USB_CTRL_EP_MPS 64
+/**
+ * USB endpoint Transfer Type mask.
+ */
+#define USBD_EP_TYPE_CTRL 0
+#define USBD_EP_TYPE_ISOC 1
+#define USBD_EP_TYPE_BULK 2
+#define USBD_EP_TYPE_INTR 3
+#define USBD_EP_TYPE_MASK 3
+
+/* Default USB control EP, always 0 and 0x80 */
+#define USB_CONTROL_OUT_EP0 0
+#define USB_CONTROL_IN_EP0 0x80
+
+/**
+ * @brief USB Endpoint Transfer Type
+ */
+enum usb_dc_ep_transfer_type {
+ /** Control type endpoint */
+ USB_DC_EP_CONTROL = 0,
+ /** Isochronous type endpoint */
+ USB_DC_EP_ISOCHRONOUS,
+ /** Bulk type endpoint */
+ USB_DC_EP_BULK,
+ /** Interrupt type endpoint */
+ USB_DC_EP_INTERRUPT
+};
+
+/**
+ * @brief USB Endpoint Configuration.
+ *
+ * Structure containing the USB endpoint configuration.
+ */
+struct usbd_endpoint_cfg {
+ /** The number associated with the EP in the device
+ * configuration structure
+ * IN EP = 0x80 | \<endpoint number\>
+ * OUT EP = 0x00 | \<endpoint number\>
+ */
+ uint8_t ep_addr;
+ /** Endpoint max packet size */
+ uint16_t ep_mps;
+ /** Endpoint Transfer Type.
+ * May be Bulk, Interrupt, Control or Isochronous
+ */
+ enum usb_dc_ep_transfer_type ep_type;
+};
+
+/**
+ * @brief USB Device Core Layer API
+ * @defgroup _usb_device_core_api USB Device Core API
+ * @{
+ */
+
+/**
+ * @brief Set USB device address
+ *
+ * @param[in] addr Device address
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_set_address(const uint8_t addr);
+
+/*
+ * @brief configure and enable endpoint
+ *
+ * This function sets endpoint configuration according to one specified in USB
+ * endpoint descriptor and then enables it for data transfers.
+ *
+ * @param [in] ep_desc Endpoint descriptor byte array
+ *
+ * @return true if successfully configured and enabled
+ */
+int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
+/**
+ * @brief Disable the selected endpoint
+ *
+ * Function to disable the selected endpoint. Upon success interrupts are
+ * disabled for the corresponding endpoint and the endpoint is no longer able
+ * for transmitting/receiving data.
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_close(const uint8_t ep);
+/**
+ * @brief Set stall condition for the selected endpoint
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_set_stall(const uint8_t ep);
+/**
+ * @brief Clear stall condition for the selected endpoint
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_clear_stall(const uint8_t ep);
+/**
+ * @brief Check if the selected endpoint is stalled
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ * @param[out] stalled Endpoint stall status
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
+/**
+ * @brief Write data to the specified endpoint
+ *
+ * This function is called to write data to the specified endpoint. The
+ * supplied usbd_endpoint_callback function will be called when data is transmitted
+ * out.
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ * @param[in] data Pointer to data to write
+ * @param[in] data_len Length of the data requested to write. This may
+ * be zero for a zero length status packet.
+ * @param[out] ret_bytes Bytes scheduled for transmission. This value
+ * may be NULL if the application expects all
+ * bytes to be written
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes);
+/**
+ * @brief Read data from the specified endpoint
+ *
+ * This is similar to usb_dc_ep_read, the difference being that, it doesn't
+ * clear the endpoint NAKs so that the consumer is not bogged down by further
+ * upcalls till he is done with the processing of the data. The caller should
+ * reactivate ep by invoking usb_dc_ep_read_continue() do so.
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ * @param[in] data Pointer to data buffer to write to
+ * @param[in] max_data_len Max length of data to read
+ * @param[out] read_bytes Number of bytes read. If data is NULL and
+ * max_data_len is 0 the number of bytes
+ * available for read should be returned.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/common/usb_def.h b/common/usb_def.h new file mode 100644 index 00000000..8a592c3a --- /dev/null +++ b/common/usb_def.h @@ -0,0 +1,522 @@ +#ifndef USB_REQUEST_H
+#define USB_REQUEST_H
+
+/* Useful define */
+#define USB_1_1 0x0110
+#define USB_2_0 0x0200
+/* Set USB version to 2.1 so that the host will request the BOS descriptor */
+#define USB_2_1 0x0210
+
+// USB Speed
+#define USB_SPEED_LOW 0U
+#define USB_SPEED_FULL 1U
+#define USB_SPEED_HIGH 2U
+
+// USB PID Types
+#define USB_PID_RESERVED 0U
+#define USB_PID_OUT 1U
+#define USB_PID_ACK 2U
+#define USB_PID_DATA0 3U
+#define USB_PID_PING 4U
+#define USB_PID_SOF 5U
+#define USB_PID_DATA2 7U
+#define USB_PID_NYET 6U
+#define USB_PID_SPLIT 8U
+#define USB_PID_IN 9U
+#define USB_PID_NAK 10U
+#define USB_PID_DATA1 11U
+#define USB_PID_PRE 12U
+#define USB_PID_ERR 12U
+#define USB_PID_SETUP 13U
+#define USB_PID_STALL 14U
+#define USB_PID_MDATA 15U
+
+// bmRequestType.Dir
+#define USB_REQUEST_HOST_TO_DEVICE 0U
+#define USB_REQUEST_DEVICE_TO_HOST 1U
+
+// bmRequestType.Type
+#define USB_REQUEST_STANDARD 0U
+#define USB_REQUEST_CLASS 1U
+#define USB_REQUEST_VENDOR 2U
+#define USB_REQUEST_RESERVED 3U
+
+// bmRequestType.Recipient
+#define USB_REQUEST_TO_DEVICE 0U
+#define USB_REQUEST_TO_INTERFACE 1U
+#define USB_REQUEST_TO_ENDPOINT 2U
+#define USB_REQUEST_TO_OTHER 3U
+
+/* USB Standard Request Codes */
+#define USB_REQUEST_GET_STATUS 0x00
+#define USB_REQUEST_CLEAR_FEATURE 0x01
+#define USB_REQUEST_SET_FEATURE 0x03
+#define USB_REQUEST_SET_ADDRESS 0x05
+#define USB_REQUEST_GET_DESCRIPTOR 0x06
+#define USB_REQUEST_SET_DESCRIPTOR 0x07
+#define USB_REQUEST_GET_CONFIGURATION 0x08
+#define USB_REQUEST_SET_CONFIGURATION 0x09
+#define USB_REQUEST_GET_INTERFACE 0x0A
+#define USB_REQUEST_SET_INTERFACE 0x0B
+#define USB_REQUEST_SYNCH_FRAME 0x0C
+#define USB_REQUEST_SET_ENCRYPTION 0x0D
+#define USB_REQUEST_GET_ENCRYPTION 0x0E
+#define USB_REQUEST_RPIPE_ABORT 0x0E
+#define USB_REQUEST_SET_HANDSHAKE 0x0F
+#define USB_REQUEST_RPIPE_RESET 0x0F
+#define USB_REQUEST_GET_HANDSHAKE 0x10
+#define USB_REQUEST_SET_CONNECTION 0x11
+#define USB_REQUEST_SET_SECURITY_DATA 0x12
+#define USB_REQUEST_GET_SECURITY_DATA 0x13
+#define USB_REQUEST_SET_WUSB_DATA 0x14
+#define USB_REQUEST_LOOPBACK_DATA_WRITE 0x15
+#define USB_REQUEST_LOOPBACK_DATA_READ 0x16
+#define USB_REQUEST_SET_INTERFACE_DS 0x17
+
+/* USB GET_STATUS Bit Values */
+#define USB_GETSTATUS_SELF_POWERED 0x01
+#define USB_GETSTATUS_REMOTE_WAKEUP 0x02
+#define USB_GETSTATUS_ENDPOINT_STALL 0x01
+
+/* USB Standard Feature selectors */
+#define USB_FEATURE_ENDPOINT_STALL 0
+#define USB_FEATURE_REMOTE_WAKEUP 1
+#define USB_FEATURE_TEST_MODE 2
+
+/* Descriptor size in bytes */
+#define USB_DEVICE_DESC_SIZE 0x12
+#define USB_CONFIGURATION_DESC_SIZE 0x09
+#define USB_INTERFACE_DESC_SIZE 0x09
+#define USB_ENDPOINT_DESC_SIZE 0x07
+#define USB_LANGID_STRING_DESC_SIZE 0x04
+#define USB_OTHER_SPEED_DESC_SIZE 0x09
+#define USB_DEVICE_QUAL_DESC_SIZE 0x0A
+#define USB_INTERFACE_ASSOC_DESC_SIZE 0x08
+#define USB_FUNCTION_DESC_SIZE 0x03
+#define USB_OTG_DESC_SIZE 0x03
+
+/* USB Descriptor Types */
+#define USB_DESCRIPTOR_TYPE_DEVICE 0x01U
+#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02U
+#define USB_DESCRIPTOR_TYPE_STRING 0x03U
+#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04U
+#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05U
+#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06U
+#define USB_DESCRIPTOR_TYPE_OTHER_SPEED 0x07U
+#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08U
+#define USB_DESCRIPTOR_TYPE_OTG 0x09U
+#define USB_DESCRIPTOR_TYPE_DEBUG 0x0AU
+#define USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0BU
+#define USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE 0x0FU
+#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 0x10U
+
+#define USB_DESCRIPTOR_TYPE_FUNCTIONAL 0x21U
+
+// Class Specific Descriptor
+#define USB_CS_DESCRIPTOR_TYPE_DEVICE 0x21U
+#define USB_CS_DESCRIPTOR_TYPE_CONFIGURATION 0x22U
+#define USB_CS_DESCRIPTOR_TYPE_STRING 0x23U
+#define USB_CS_DESCRIPTOR_TYPE_INTERFACE 0x24U
+#define USB_CS_DESCRIPTOR_TYPE_ENDPOINT 0x25U
+
+#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ENDPOINT_COMPANION 0x30U
+#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ISO_ENDPOINT_COMPANION 0x31U
+
+/* USB Device Classes */
+#define USB_DEVICE_CLASS_RESERVED 0x00
+#define USB_DEVICE_CLASS_AUDIO 0x01
+#define USB_DEVICE_CLASS_CDC 0x02
+#define USB_DEVICE_CLASS_HID 0x03
+#define USB_DEVICE_CLASS_MONITOR 0x04
+#define USB_DEVICE_CLASS_PHYSICAL 0x05
+#define USB_DEVICE_CLASS_IMAGE 0x06
+#define USB_DEVICE_CLASS_PRINTER 0x07
+#define USB_DEVICE_CLASS_MASS_STORAGE 0x08
+#define USB_DEVICE_CLASS_HUB 0x09
+#define USB_DEVICE_CLASS_CDC_DATA 0x0a
+#define USB_DEVICE_CLASS_SMART_CARD 0x0b
+#define USB_DEVICE_CLASS_SECURITY 0x0d
+#define USB_DEVICE_CLASS_VIDEO 0x0e
+#define USB_DEVICE_CLASS_HEALTHCARE 0x0f
+#define USB_DEVICE_CLASS_DIAG_DEVICE 0xdc
+#define USB_DEVICE_CLASS_WIRELESS 0xe0
+#define USB_DEVICE_CLASS_MISC 0xef
+#define USB_DEVICE_CLASS_APP_SPECIFIC 0xfe
+#define USB_DEVICE_CLASS_VEND_SPECIFIC 0xff
+
+/* usb string index define */
+#define USB_STRING_LANGID_INDEX 0x00
+#define USB_STRING_MFC_INDEX 0x01
+#define USB_STRING_PRODUCT_INDEX 0x02
+#define USB_STRING_SERIAL_INDEX 0x03
+#define USB_STRING_CONFIG_INDEX 0x04
+#define USB_STRING_INTERFACE_INDEX 0x05
+#define USB_STRING_OS_INDEX 0x06
+#define USB_STRING_MAX USB_STRING_OS_INDEX
+/*
+ * Devices supporting Microsoft OS Descriptors store special string
+ * descriptor at fixed index (0xEE). It is read when a new device is
+ * attached to a computer for the first time.
+ */
+#define USB_OSDESC_STRING_DESC_INDEX 0xEE
+
+/* bmAttributes in Configuration Descriptor */
+#define USB_CONFIG_POWERED_MASK 0x40
+#define USB_CONFIG_BUS_POWERED 0x80
+#define USB_CONFIG_SELF_POWERED 0xC0
+#define USB_CONFIG_REMOTE_WAKEUP 0x20
+
+/* bMaxPower in Configuration Descriptor */
+#define USB_CONFIG_POWER_MA(mA) ((mA) / 2)
+
+/* bEndpointAddress in Endpoint Descriptor */
+#define USB_ENDPOINT_DIRECTION_MASK 0x80
+#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
+#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
+
+/* bmAttributes in Endpoint Descriptor */
+#define USB_ENDPOINT_TYPE_MASK 0x03
+#define USB_ENDPOINT_TYPE_CONTROL 0x00
+#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
+#define USB_ENDPOINT_TYPE_BULK 0x02
+#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
+#define USB_ENDPOINT_SYNC_MASK 0x0C
+#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION 0x00
+#define USB_ENDPOINT_SYNC_ASYNCHRONOUS 0x04
+#define USB_ENDPOINT_SYNC_ADAPTIVE 0x08
+#define USB_ENDPOINT_SYNC_SYNCHRONOUS 0x0C
+#define USB_ENDPOINT_USAGE_MASK 0x30
+#define USB_ENDPOINT_USAGE_DATA 0x00
+#define USB_ENDPOINT_USAGE_FEEDBACK 0x10
+#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK 0x20
+#define USB_ENDPOINT_USAGE_RESERVED 0x30
+
+/* bDevCapabilityType in Device Capability Descriptor */
+#define USB_DEVICE_CAPABILITY_WIRELESS_USB 1
+#define USB_DEVICE_CAPABILITY_USB_2_0_EXTENSION 2
+#define USB_DEVICE_CAPABILITY_SUPERSPEED_USB 3
+#define USB_DEVICE_CAPABILITY_CONTAINER_ID 4
+#define USB_DEVICE_CAPABILITY_PLATFORM 5
+#define USB_DEVICE_CAPABILITY_POWER_DELIVERY_CAPABILITY 6
+#define USB_DEVICE_CAPABILITY_BATTERY_INFO_CAPABILITY 7
+#define USB_DEVICE_CAPABILITY_PD_CONSUMER_PORT_CAPABILITY 8
+#define USB_DEVICE_CAPABILITY_PD_PROVIDER_PORT_CAPABILITY 9
+#define USB_DEVICE_CAPABILITY_SUPERSPEED_PLUS 10
+#define USB_DEVICE_CAPABILITY_PRECISION_TIME_MEASUREMENT 11
+#define USB_DEVICE_CAPABILITY_WIRELESS_USB_EXT 12
+
+#define USB_BOS_CAPABILITY_EXTENSION 0x02
+#define USB_BOS_CAPABILITY_PLATFORM 0x05
+
+/* Setup packet definition used to read raw data from USB line */
+struct usb_setup_packet {
+ __packed union {
+ uint8_t bmRequestType; /* bmRequestType */
+ struct
+ {
+ uint8_t Recipient : 5; /* D4..0: Recipient */
+ uint8_t Type : 2; /* D6..5: Type */
+ uint8_t Dir : 1; /* D7: Data Phase Txsfer Direction */
+ } bmRequestType_b;
+ };
+ uint8_t bRequest;
+ __packed union {
+ uint16_t wValue; /* wValue */
+ struct
+ {
+ uint8_t wValueL;
+ uint8_t wValueH;
+ };
+ };
+ __packed union {
+ uint16_t wIndex; /* wIndex */
+ struct
+ {
+ uint8_t wIndexL;
+ uint8_t wIndexH;
+ };
+ };
+ uint16_t wLength;
+} __packed;
+
+/** Standard Device Descriptor */
+struct usb_device_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 18 */
+ uint8_t bDescriptorType; /* DEVICE descriptor type = 1 */
+ uint16_t bcdUSB; /* USB spec in BCD, e.g. 0x0200 */
+ uint8_t bDeviceClass; /* Class code, if 0 see interface */
+ uint8_t bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */
+ uint8_t bDeviceProtocol; /* Protocol, if 0 see interface */
+ uint8_t bMaxPacketSize0; /* Endpoint 0 max. size */
+ uint16_t idVendor; /* Vendor ID per USB-IF */
+ uint16_t idProduct; /* Product ID per manufacturer */
+ uint16_t bcdDevice; /* Device release # in BCD */
+ uint8_t iManufacturer; /* Index to manufacturer string */
+ uint8_t iProduct; /* Index to product string */
+ uint8_t iSerialNumber; /* Index to serial number string */
+ uint8_t bNumConfigurations; /* Number of possible configurations */
+} __packed;
+
+/** USB device_qualifier descriptor */
+struct usb_device_qualifier_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 10 */
+ uint8_t bDescriptorType; /* DEVICE QUALIFIER type = 6 */
+ uint16_t bcdUSB; /* USB spec in BCD, e.g. 0x0200 */
+ uint8_t bDeviceClass; /* Class code, if 0 see interface */
+ uint8_t bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */
+ uint8_t bDeviceProtocol; /* Protocol, if 0 see interface */
+ uint8_t bMaxPacketSize; /* Endpoint 0 max. size */
+ uint8_t bNumConfigurations; /* Number of possible configurations */
+ uint8_t bReserved; /* Reserved = 0 */
+} __packed;
+
+/** Standard Configuration Descriptor */
+struct usb_configuration_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 9 */
+ uint8_t bDescriptorType; /* CONFIGURATION type = 2 or 7 */
+ uint16_t wTotalLength; /* Length of concatenated descriptors */
+ uint8_t bNumInterfaces; /* Number of interfaces, this config. */
+ uint8_t bConfigurationValue; /* Value to set this config. */
+ uint8_t iConfiguration; /* Index to configuration string */
+ uint8_t bmAttributes; /* Config. characteristics */
+ uint8_t bMaxPower; /* Max.power from bus, 2mA units */
+} __packed;
+
+/** Standard Interface Descriptor */
+struct usb_interface_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 9 */
+ uint8_t bDescriptorType; /* INTERFACE descriptor type = 4 */
+ uint8_t bInterfaceNumber; /* Interface no.*/
+ uint8_t bAlternateSetting; /* Value to select this IF */
+ uint8_t bNumEndpoints; /* Number of endpoints excluding 0 */
+ uint8_t bInterfaceClass; /* Class code, 0xFF = vendor */
+ uint8_t bInterfaceSubClass; /* Sub-Class code, 0 if class = 0 */
+ uint8_t bInterfaceProtocol; /* Protocol, 0xFF = vendor */
+ uint8_t iInterface; /* Index to interface string */
+} __packed;
+
+/** Standard Endpoint Descriptor */
+struct usb_endpoint_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 7 */
+ uint8_t bDescriptorType; /* ENDPOINT descriptor type = 5 */
+ uint8_t bEndpointAddress; /* Endpoint # 0 - 15 | IN/OUT */
+ uint8_t bmAttributes; /* Transfer type */
+ uint16_t wMaxPacketSize; /* Bits 10:0 = max. packet size */
+ uint8_t bInterval; /* Polling interval in (micro) frames */
+} __packed;
+
+/** Unicode (UTF16LE) String Descriptor */
+struct usb_string_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bString;
+} __packed;
+
+/* USB Interface Association Descriptor */
+struct usb_interface_association_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bFirstInterface;
+ uint8_t bInterfaceCount;
+ uint8_t bFunctionClass;
+ uint8_t bFunctionSubClass;
+ uint8_t bFunctionProtocol;
+ uint8_t iFunction;
+} __packed;
+
+/* MS OS 1.0 string descriptor */
+struct usb_msosv1_string_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bString[14];
+ uint8_t bMS_VendorCode; /* Vendor Code, used for a control request */
+ uint8_t bPad; /* Padding byte for VendorCode look as UTF16 */
+} __packed;
+
+/* MS OS 1.0 Header descriptor */
+struct usb_msosv1_compat_id_header_descriptor {
+ uint32_t dwLength;
+ uint16_t bcdVersion;
+ uint16_t wIndex;
+ uint8_t bCount;
+ uint8_t reserved[7];
+} __packed;
+
+/* MS OS 1.0 Function descriptor */
+struct usb_msosv1_comp_id_function_descriptor {
+ uint8_t bFirstInterfaceNumber;
+ uint8_t reserved1;
+ uint8_t compatibleID[8];
+ uint8_t subCompatibleID[8];
+ uint8_t reserved2[6];
+} __packed;
+
+#define usb_msosv1_comp_id_property_create(x) \
+ struct usb_msosv1_comp_id_property { \
+ struct usb_msosv1_compat_id_header_descriptor compat_id_header; \
+ struct usb_msosv1_comp_id_function_descriptor compat_id_function[x]; \
+ };
+
+struct usb_msosv1_descriptor {
+ uint8_t *string;
+ uint8_t string_len;
+ uint8_t vendor_code;
+ uint8_t *compat_id;
+ uint16_t compat_id_len;
+ uint8_t *comp_id_property;
+ uint16_t comp_id_property_len;
+};
+
+/* MS OS 2.0 Header descriptor */
+struct usb_msosv2_property_header_descriptor {
+ uint32_t dwLength;
+ uint16_t bcdVersion;
+ uint16_t wIndex;
+ uint8_t bCount;
+} __packed;
+
+/* WinUSB Microsoft OS 2.0 descriptor set header */
+struct winusb_header_descriptor {
+ uint16_t wLength;
+ uint16_t wDescriptorType;
+ uint32_t dwWindowsVersion;
+ uint16_t wDescriptorSetTotalLength;
+} __packed;
+
+/* WinUSB Microsoft OS 2.0 subset function descriptor */
+struct winusb_subset_function_descriptor {
+ uint16_t wLength;
+ uint16_t wDescriptorType;
+ uint8_t bFirstInterface;
+ uint8_t bReserved;
+ uint16_t wSubsetLength;
+} __packed;
+
+/* MS OS 2.0 Function Section */
+struct usb_msosv2_comp_id_function_descriptor {
+ uint16_t wLength;
+ uint16_t wDescriptorType;
+ uint8_t compatibleID[8];
+ uint8_t subCompatibleID[8];
+} __packed;
+
+/* MS OS 2.0 property descriptor */
+struct usb_msosv2_proerty_descriptor {
+ uint16_t wLength;
+ uint16_t wDescriptorType;
+ uint32_t dwPropertyDataType;
+ uint16_t wPropertyNameLength;
+ const char *bPropertyName;
+ uint32_t dwPropertyDataLength;
+ const char *bPropertyData;
+};
+
+struct usb_msosv2_descriptor {
+ uint8_t *compat_id;
+ uint16_t compat_id_len;
+};
+
+/* BOS Descriptor */
+struct usb_bos_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wTotalLength;
+ uint8_t bNumDeviceCaps;
+} __packed;
+
+/* BOS Capability Descriptor */
+struct usb_bos_capability_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint8_t bReserved;
+ uint8_t PlatformCapabilityUUID[16];
+} __packed;
+
+struct usb_bos_capability_lpm {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint32_t bmAttributes;
+} __packed;
+
+struct usb_bos_descriptor {
+ uint8_t *bos_id;
+ uint8_t bos_id_len;
+};
+
+/* USB Device Capability Descriptor */
+struct usb_device_capability__descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+} __packed;
+
+/** USB descriptor header */
+struct usb_desc_header {
+ uint8_t bLength; /**< descriptor length */
+ uint8_t bDescriptorType; /**< descriptor type */
+};
+
+#define USB_DEVICE_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct, bcdDevice, bNumConfigurations) \
+ 0x12, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_DEVICE, /* bDescriptorType */ \
+ WBVAL(bcdUSB), /* bcdUSB */ \
+ bDeviceClass, /* bDeviceClass */ \
+ bDeviceSubClass, /* bDeviceSubClass */ \
+ bDeviceProtocol, /* bDeviceProtocol */ \
+ 0x40, /* bMaxPacketSize */ \
+ WBVAL(idVendor), /* idVendor */ \
+ WBVAL(idProduct), /* idProduct */ \
+ WBVAL(bcdDevice), /* bcdDevice */ \
+ USB_STRING_MFC_INDEX, /* iManufacturer */ \
+ USB_STRING_PRODUCT_INDEX, /* iProduct */ \
+ USB_STRING_SERIAL_INDEX, /* iSerial */ \
+ bNumConfigurations /* bNumConfigurations */
+
+#define USB_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_CONFIGURATION, /* bDescriptorType */ \
+ WBVAL(wTotalLength), /* wTotalLength */ \
+ bNumInterfaces, /* bNumInterfaces */ \
+ bConfigurationValue, /* bConfigurationValue */ \
+ 0x00, /* iConfiguration */ \
+ bmAttributes, /* bmAttributes */ \
+ USB_CONFIG_POWER_MA(bMaxPower) /* bMaxPower */
+
+#define USB_INTERFACE_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints, \
+ bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface) \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bInterfaceNumber, /* bInterfaceNumber */ \
+ bAlternateSetting, /* bAlternateSetting */ \
+ bNumEndpoints, /* bNumEndpoints */ \
+ bInterfaceClass, /* bInterfaceClass */ \
+ bInterfaceSubClass, /* bInterfaceSubClass */ \
+ bInterfaceProtocol, /* bInterfaceProtocol */ \
+ iInterface /* iInterface */
+
+#define USB_ENDPOINT_DESCRIPTOR_INIT(bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ bEndpointAddress, /* bEndpointAddress */ \
+ bmAttributes, /* bmAttributes */ \
+ WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
+ bInterval /* bInterval */
+
+#define USB_IAD_INIT(bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol) \
+ 0x08, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
+ bFirstInterface, /* bFirstInterface */ \
+ bInterfaceCount, /* bInterfaceCount */ \
+ bFunctionClass, /* bFunctionClass */ \
+ bFunctionSubClass, /* bFunctionSubClass */ \
+ bFunctionProtocol, /* bFunctionProtocol */ \
+ 0x00 /* iFunction */
+
+#define USB_LANGID_INIT(id) \
+ 0x04, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ \
+ WBVAL(id) /* wLangID0 */
+
+#endif
\ No newline at end of file diff --git a/common/usb_slist.h b/common/usb_slist.h new file mode 100644 index 00000000..357df1be --- /dev/null +++ b/common/usb_slist.h @@ -0,0 +1,224 @@ +#ifndef __USB_SLIST_H__
+#define __USB_SLIST_H__
+
+#include "string.h"
+#include "stdint.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * usb_container_of - return the member address of ptr, if the type of ptr is the
+ * struct type.
+ */
+#define usb_container_of(ptr, type, member) \
+ ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
+
+/**
+ * Single List structure
+ */
+struct usb_slist_node {
+ struct usb_slist_node *next; /**< point to next node. */
+};
+typedef struct usb_slist_node usb_slist_t; /**< Type for single list. */
+
+/**
+ * @brief initialize a single list
+ *
+ * @param l the single list to be initialized
+ */
+static inline void usb_slist_init(usb_slist_t *l)
+{
+ l->next = NULL;
+}
+
+static inline void usb_slist_add_head(usb_slist_t *l, usb_slist_t *n)
+{
+ n->next = l->next;
+ l->next = n;
+}
+
+static inline void usb_slist_add_tail(usb_slist_t *l, usb_slist_t *n)
+{
+ while (l->next) {
+ l = l->next;
+ }
+
+ /* append the node to the tail */
+ l->next = n;
+ n->next = NULL;
+}
+
+static inline void usb_slist_insert(usb_slist_t *l, usb_slist_t *next, usb_slist_t *n)
+{
+ if (!next) {
+ usb_slist_add_tail(next, l);
+ return;
+ }
+
+ while (l->next) {
+ if (l->next == next) {
+ l->next = n;
+ n->next = next;
+ }
+
+ l = l->next;
+ }
+}
+
+static inline usb_slist_t *usb_slist_remove(usb_slist_t *l, usb_slist_t *n)
+{
+ /* remove slist head */
+ while (l->next && l->next != n) {
+ l = l->next;
+ }
+
+ /* remove node */
+ if (l->next != (usb_slist_t *)0) {
+ l->next = l->next->next;
+ }
+
+ return l;
+}
+
+static inline unsigned int usb_slist_len(const usb_slist_t *l)
+{
+ unsigned int len = 0;
+ const usb_slist_t *list = l->next;
+
+ while (list != NULL) {
+ list = list->next;
+ len++;
+ }
+
+ return len;
+}
+
+static inline unsigned int usb_slist_contains(usb_slist_t *l, usb_slist_t *n)
+{
+ while (l->next) {
+ if (l->next == n) {
+ return 0;
+ }
+
+ l = l->next;
+ }
+
+ return 1;
+}
+
+static inline usb_slist_t *usb_slist_head(usb_slist_t *l)
+{
+ return l->next;
+}
+
+static inline usb_slist_t *usb_slist_tail(usb_slist_t *l)
+{
+ while (l->next) {
+ l = l->next;
+ }
+
+ return l;
+}
+
+static inline usb_slist_t *usb_slist_next(usb_slist_t *n)
+{
+ return n->next;
+}
+
+static inline int usb_slist_isempty(usb_slist_t *l)
+{
+ return l->next == NULL;
+}
+
+/**
+ * @brief initialize a slist object
+ */
+#define USB_SLIST_OBJECT_INIT(object) \
+ { \
+ NULL \
+ }
+
+/**
+ * @brief initialize a slist object
+ */
+#define USB_SLIST_DEFINE(slist) \
+ usb_slist_t slist = { NULL }
+
+/**
+ * @brief get the struct for this single list node
+ * @param node the entry point
+ * @param type the type of structure
+ * @param member the name of list in structure
+ */
+#define usb_slist_entry(node, type, member) \
+ usb_container_of(node, type, member)
+
+/**
+ * usb_slist_first_entry - get the first element from a slist
+ * @ptr: the slist head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the slist_struct within the struct.
+ *
+ * Note, that slist is expected to be not empty.
+ */
+#define usb_slist_first_entry(ptr, type, member) \
+ usb_slist_entry((ptr)->next, type, member)
+
+/**
+ * usb_slist_tail_entry - get the tail element from a slist
+ * @ptr: the slist head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the slist_struct within the struct.
+ *
+ * Note, that slist is expected to be not empty.
+ */
+#define usb_slist_tail_entry(ptr, type, member) \
+ usb_slist_entry(usb_slist_tail(ptr), type, member)
+
+/**
+ * usb_slist_first_entry_or_null - get the first element from a slist
+ * @ptr: the slist head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the slist_struct within the struct.
+ *
+ * Note, that slist is expected to be not empty.
+ */
+#define usb_slist_first_entry_or_null(ptr, type, member) \
+ (usb_slist_isempty(ptr) ? NULL : usb_slist_first_entry(ptr, type, member))
+
+/**
+ * usb_slist_for_each - iterate over a single list
+ * @pos: the usb_slist_t * to use as a loop cursor.
+ * @head: the head for your single list.
+ */
+#define usb_slist_for_each(pos, head) \
+ for (pos = (head)->next; pos != NULL; pos = pos->next)
+
+#define usb_slist_for_each_safe(pos, next, head) \
+ for (pos = (head)->next, next = pos->next; pos; \
+ pos = next, next = pos->next)
+
+/**
+ * usb_slist_for_each_entry - iterate over single list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your single list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define usb_slist_for_each_entry(pos, head, member) \
+ for (pos = usb_slist_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (NULL); \
+ pos = usb_slist_entry(pos->member.next, typeof(*pos), member))
+
+#define usb_slist_for_each_entry_safe(pos, n, head, member) \
+ for (pos = usb_slist_entry((head)->next, typeof(*pos), member), \
+ n = usb_slist_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (NULL); \
+ pos = n, n = usb_slist_entry(pos->member.next, typeof(*pos), member))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file diff --git a/common/usb_util.h b/common/usb_util.h new file mode 100644 index 00000000..83c59744 --- /dev/null +++ b/common/usb_util.h @@ -0,0 +1,131 @@ +#ifndef _USB_UTIL_H
+#define _USB_UTIL_H
+
+#include "stdbool.h"
+#include "string.h"
+#include "stdint.h"
+#include "stdio.h"
+#include "usb_slist.h"
+
+#ifndef __packed
+#define __packed __attribute__((__packed__))
+#endif
+#ifndef __aligned
+#define __aligned(x) __attribute__((__aligned__(x)))
+#endif
+#define __may_alias __attribute__((__may_alias__))
+#ifndef __printf_like
+#define __printf_like(f, a) __attribute__((format(printf, f, a)))
+#endif
+#define __used __attribute__((__used__))
+#ifndef __deprecated
+#define __deprecated __attribute__((deprecated))
+#endif
+#define ARG_UNUSED(x) (void)(x)
+
+// #define likely(x) __builtin_expect((bool)!!(x), true)
+// #define unlikely(x) __builtin_expect((bool)!!(x), false)
+
+#define popcount(x) __builtin_popcount(x)
+
+#ifndef __no_optimization
+#define __no_optimization __attribute__((optimize("-O0")))
+#endif
+
+#ifndef __weak
+#define __weak __attribute__((__weak__))
+#endif
+#define __unused __attribute__((__unused__))
+
+#define __ALIGN_END __attribute__((aligned(4)))
+#define __ALIGN_BEGIN
+
+#ifndef LO_BYTE
+#define LO_BYTE(x) ((uint8_t)(x & 0x00FF))
+#endif
+
+#ifndef HI_BYTE
+#define HI_BYTE(x) ((uint8_t)((x & 0xFF00) >> 8))
+#endif
+
+/**
+ * @def MAX
+ * @brief The larger value between @p a and @p b.
+ * @note Arguments are evaluated twice.
+ */
+#ifndef MAX
+/* Use Z_MAX for a GCC-only, single evaluation version */
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/**
+ * @def MIN
+ * @brief The smaller value between @p a and @p b.
+ * @note Arguments are evaluated twice.
+ */
+#ifndef MIN
+/* Use Z_MIN for a GCC-only, single evaluation version */
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define BCD(x) ((((x) / 10) << 4) | ((x) % 10))
+
+#define BIT(x) (1 << (x))
+
+#define ARRAY_SIZE(array) \
+ ((int)((sizeof(array) / sizeof((array)[0]))))
+
+#define USB_DESC_SECTION __attribute__((section("usb_desc"))) __used __aligned(1)
+
+#define BSWAP16(u16) (__builtin_bswap16(u16))
+#define BSWAP32(u32) (__builtin_bswap32(u32))
+
+#define GET_BE16(field) \
+ (((uint16_t)(field)[0] << 8) | ((uint16_t)(field)[1]))
+
+#define GET_BE32(field) \
+ (((uint32_t)(field)[0] << 24) | ((uint32_t)(field)[1] << 16) | ((uint32_t)(field)[2] << 8) | ((uint32_t)(field)[3] << 0))
+
+#define SET_BE16(field, value) \
+ do { \
+ (field)[0] = (uint8_t)((value) >> 8); \
+ (field)[1] = (uint8_t)((value) >> 0); \
+ } while (0)
+
+#define SET_BE24(field, value) \
+ do { \
+ (field)[0] = (uint8_t)((value) >> 16); \
+ (field)[1] = (uint8_t)((value) >> 8); \
+ (field)[2] = (uint8_t)((value) >> 0); \
+ } while (0)
+
+#define SET_BE32(field, value) \
+ do { \
+ (field)[0] = (uint8_t)((value) >> 24); \
+ (field)[1] = (uint8_t)((value) >> 16); \
+ (field)[2] = (uint8_t)((value) >> 8); \
+ (field)[3] = (uint8_t)((value) >> 0); \
+ } while (0)
+
+#define REQTYPE_GET_DIR(x) (((x) >> 7) & 0x01)
+#define REQTYPE_GET_TYPE(x) (((x) >> 5) & 0x03U)
+#define REQTYPE_GET_RECIP(x) ((x)&0x1F)
+
+#define GET_DESC_TYPE(x) (((x) >> 8) & 0xFFU)
+#define GET_DESC_INDEX(x) ((x)&0xFFU)
+
+#define WBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF)
+#define DBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF), ((x >> 16) & 0xFF), ((x >> 24) & 0xFF)
+
+#if 0
+#define USBD_LOG_WRN(a, ...) bflb_platform_printf(a, ##__VA_ARGS__)
+#define USBD_LOG_DBG(a, ...) bflb_platform_printf(a, ##__VA_ARGS__)
+#define USBD_LOG_ERR(a, ...) bflb_platform_printf(a, ##__VA_ARGS__)
+#else
+#define USBD_LOG_WRN(a, ...) bflb_platform_printf(a, ##__VA_ARGS__)
+#define USBD_LOG_DBG(a, ...)
+#define USBD_LOG_ERR(a, ...) bflb_platform_printf(a, ##__VA_ARGS__)
+#define USBD_LOG(a, ...) bflb_platform_printf(a, ##__VA_ARGS__)
+#endif
+
+#endif
\ No newline at end of file |
