esp-idf/components/usb/private_include/usb.h

457 wiersze
18 KiB
C

// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Note: This header file contains the types and macros belong/relate to the USB2.0 protocol and are HW implementation
agnostic. In other words, this header is only meant to be used in the HCD layer and above of the USB Host stack. For
types and macros that are HW implementation specific (i.e., HAL layer and below), add them to the "usb_types.h" header
instead.
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <sys/queue.h>
#define USB_CTRL_REQ_ATTR __attribute__((packed))
#define USB_DESC_ATTR __attribute__((packed))
// ------------------------------------------------ Common USB Types ---------------------------------------------------
// --------------------- Bus Related -----------------------
/**
* @brief USB Standard Speeds
*/
typedef enum {
USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */
USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */
} usb_speed_t;
// ------------------ Transfer Related ---------------------
/**
* @brief The type of USB transfer
*
* @note The enum values need to match the bmAttributes field of an EP descriptor
*/
typedef enum {
USB_XFER_TYPE_CTRL = 0,
USB_XFER_TYPE_ISOCHRONOUS,
USB_XFER_TYPE_BULK,
USB_XFER_TYPE_INTR,
} usb_transfer_type_t;
/**
* @brief The status of a particular transfer
*/
typedef enum {
USB_TRANSFER_STATUS_COMPLETED, /**< The transfer was successful (but may be short) */
USB_TRANSFER_STATUS_ERROR, /**< The transfer failed because due to excessive errors (e.g. no response or CRC error) */
USB_TRANSFER_STATUS_TIMED_OUT, /**< The transfer failed due to a time out */
USB_TRANSFER_STATUS_CANCELLED, /**< The transfer was canceled */
USB_TRANSFER_STATUS_STALL, /**< The transfer was stalled */
USB_TRANSFER_STATUS_NO_DEVICE, /**< The transfer failed because the device is no longer valid (e.g., disconnected */
USB_TRANSFER_STATUS_OVERFLOW, /**< The transfer as more data was sent than was requested */
} usb_transfer_status_t;
/**
* @brief Isochronous packet descriptor
*
* If the number of bytes in an IRP (I/O Request Packet, see USB2.0 Spec) is
* larger than the MPS of the endpoint, the IRP is split over multiple packets
* (one packet per bInterval of the endpoint). An array of Isochronous packet
* descriptors describes how an IRP should be split over multiple packets.
*/
typedef struct {
int length; /**< Number of bytes to transmit/receive in the packet */
int actual_length; /**< Actual number of bytes transmitted/received in the packet */
usb_transfer_status_t status; /**< Status of the packet */
} usb_iso_packet_desc_t;
/**
* @brief USB IRP (I/O Request Packet). See USB2.0 Spec
*
* An IRP is used to represent data transfer request form a software client to and endpoint over the USB bus. The same
* IRP object type is used at each layer of the USB stack. This minimizes copying/conversion across the different layers
* of the stack as each layer will pass a pointer to this type of object.
*
* See 10.5.3.1 os USB2.0 specification
* Bulk: Represents a single bulk transfer which a pipe will transparently split into multiple MPS transactions (until
* the last)
* Control: Represents a single control transfer with the setup packet at the first 8 bytes of the buffer.
* Interrupt: Represents a single interrupt transaction
* Isochronous: Represents a buffer of a stream of bytes which the pipe will transparently transfer the stream of bytes
* one or more service periods
*
* @note The tailq_entry and reserved variables are used by the USB Host stack internally. Users should not modify those fields.
* @note Once an IRP is submitted, users should not modify the IRP as the Host stack takes ownership of the IRP.
*/
struct usb_irp_obj {
//Internal members
TAILQ_ENTRY(usb_irp_obj) tailq_entry; /**< TAILQ entry that allows this object to be added to linked lists. Users should NOT modify this field */
void *reserved_ptr; /**< Reserved pointer variable for internal use in the stack. Users should set this to NULL on allocation and NOT modify this afterwards */
uint32_t reserved_flags; /**< Reserved variable for flags used internally in the stack. Users should set this to 0 on allocation and NOT modify this afterwards */
//Public members
uint8_t *data_buffer; /**< Pointer to data buffer. Must be DMA capable memory */
int num_bytes; /**< Number of bytes in IRP. Control should exclude size of setup. IN should be integer multiple of MPS */
int actual_num_bytes; /**< Actual number of bytes transmitted/receives in the IRP */
usb_transfer_status_t status; /**< Status of the transfer */
uint32_t timeout; /**< Timeout (in milliseconds) of the packet */
void *context; /**< Context variable used to associate the IRP object with another object */
int num_iso_packets; /**< Only relevant to Isochronous. Number of service periods to transfer data buffer over. Set to 0 for non-iso transfers */
usb_iso_packet_desc_t iso_packet_desc[0]; /**< Descriptors for each ISO packet */
};
typedef struct usb_irp_obj usb_irp_t;
// ---------------------------------------------------- Chapter 9 ------------------------------------------------------
// ------------------- Control Request ---------------------
/**
* @brief Size of a USB control transfer setup packet in bytes
*/
#define USB_CTRL_REQ_SIZE 8
/**
* @brief Structure representing a USB control transfer setup packet
*/
typedef union {
struct {
uint8_t bRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} USB_CTRL_REQ_ATTR;
uint8_t val[USB_CTRL_REQ_SIZE];
} usb_ctrl_req_t;
_Static_assert(sizeof(usb_ctrl_req_t) == USB_CTRL_REQ_SIZE, "Size of usb_ctrl_req_t incorrect");
/**
* @brief Bit masks belonging to the bRequestType field of a setup packet
*/
#define USB_B_REQUEST_TYPE_DIR_OUT (0X00 << 7)
#define USB_B_REQUEST_TYPE_DIR_IN (0x01 << 7)
#define USB_B_REQUEST_TYPE_TYPE_STANDARD (0x00 << 5)
#define USB_B_REQUEST_TYPE_TYPE_CLASS (0x01 << 5)
#define USB_B_REQUEST_TYPE_TYPE_VENDOR (0x02 << 5)
#define USB_B_REQUEST_TYPE_TYPE_RESERVED (0x03 << 5)
#define USB_B_REQUEST_TYPE_TYPE_MASK (0x03 << 5)
#define USB_B_REQUEST_TYPE_RECIP_DEVICE (0x00 << 0)
#define USB_B_REQUEST_TYPE_RECIP_INTERFACE (0x01 << 0)
#define USB_B_REQUEST_TYPE_RECIP_ENDPOINT (0x02 << 0)
#define USB_B_REQUEST_TYPE_RECIP_OTHER (0x03 << 0)
#define USB_B_REQUEST_TYPE_RECIP_MASK (0x1f << 0)
/**
* @brief Bit masks belonging to the bRequest field of a setup packet
*/
#define USB_B_REQUEST_GET_STATUS 0x00
#define USB_B_REQUEST_CLEAR_FEATURE 0x01
#define USB_B_REQUEST_SET_FEATURE 0x03
#define USB_B_REQUEST_SET_ADDRESS 0x05
#define USB_B_REQUEST_GET_DESCRIPTOR 0x06
#define USB_B_REQUEST_SET_DESCRIPTOR 0x07
#define USB_B_REQUEST_GET_CONFIGURATION 0x08
#define USB_B_REQUEST_SET_CONFIGURATION 0x09
#define USB_B_REQUEST_GET_INTERFACE 0x0A
#define USB_B_REQUEST_SET_INTERFACE 0x0B
#define USB_B_REQUEST_SYNCH_FRAME 0x0C
/**
* @brief Bit masks belonging to the wValue field of a setup packet
*/
#define USB_W_VALUE_DT_DEVICE 0x01
#define USB_W_VALUE_DT_CONFIG 0x02
#define USB_W_VALUE_DT_STRING 0x03
#define USB_W_VALUE_DT_INTERFACE 0x04
#define USB_W_VALUE_DT_ENDPOINT 0x05
#define USB_W_VALUE_DT_DEVICE_QUALIFIER 0x06
#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG 0x07
#define USB_W_VALUE_DT_INTERFACE_POWER 0x08
/**
* @brief Initializer for a SET_ADDRESS request
*
* Sets the address of a connected device
*/
#define USB_CTRL_REQ_INIT_SET_ADDR(ctrl_req_ptr, addr) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD |USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_ADDRESS; \
(ctrl_req_ptr)->wValue = (addr); \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = 0; \
})
/**
* @brief Initializer for a request to get a device's device descriptor
*/
#define USB_CTRL_REQ_INIT_GET_DEVC_DESC(ctrl_req_ptr) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \
(ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_DEVICE << 8); \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = 18; \
})
/**
* @brief Initializer for a request to get a device's current configuration number
*/
#define USB_CTRL_REQ_INIT_GET_CONFIG(ctrl_req_ptr) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_CONFIGURATION; \
(ctrl_req_ptr)->wValue = 0; \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = 1; \
})
/**
* @brief Initializer for a request to get one of the device's current configuration descriptor
*
* - desc_index indicates the configuration's index number
* - Number of bytes of the configuration descriptor to get
*/
#define USB_CTRL_REQ_INIT_GET_CFG_DESC(ctrl_req_ptr, desc_index, desc_len) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \
(ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_CONFIG << 8) | ((desc_index) & 0xFF); \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = (desc_len); \
})
/**
* @brief Initializer for a request to set a device's current configuration number
*/
#define USB_CTRL_REQ_INIT_SET_CONFIG(ctrl_req_ptr, config_num) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_CONFIGURATION; \
(ctrl_req_ptr)->wValue = (config_num); \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = 0; \
})
// ------------------ Device Descriptor --------------------
/**
* @brief Size of a USB device descriptor in bytes
*/
#define USB_DESC_DEV_SIZE 18
/**
* @brief Structure representing a USB device descriptor
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} USB_DESC_ATTR;
uint8_t val[USB_DESC_DEV_SIZE];
} usb_desc_devc_t;
_Static_assert(sizeof(usb_desc_devc_t) == USB_DESC_DEV_SIZE, "Size of usb_desc_devc_t incorrect");
/**
* @brief Possible base class values of the bDeviceClass field of a USB device descriptor
*/
#define USB_CLASS_PER_INTERFACE 0x00
#define USB_CLASS_AUDIO 0x01
#define USB_CLASS_COMM 0x02
#define USB_CLASS_HID 0x03
#define USB_CLASS_PHYSICAL 0x05
#define USB_CLASS_STILL_IMAGE 0x06
#define USB_CLASS_PRINTER 0x07
#define USB_CLASS_MASS_STORAGE 0x08
#define USB_CLASS_HUB 0x09
#define USB_CLASS_CDC_DATA 0x0a
#define USB_CLASS_CSCID 0x0b
#define USB_CLASS_CONTENT_SEC 0x0d
#define USB_CLASS_VIDEO 0x0e
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
#define USB_CLASS_PERSONAL_HEALTHCARE 0x0f
#define USB_CLASS_AUDIO_VIDEO 0x10
#define USB_CLASS_BILLBOARD 0x11
#define USB_CLASS_USB_TYPE_C_BRIDGE 0x12
#define USB_CLASS_MISC 0xef
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
/**
* @brief Vendor specific subclass code
*/
#define USB_SUBCLASS_VENDOR_SPEC 0xff
// -------------- Configuration Descriptor -----------------
/**
* @brief Size of a short USB configuration descriptor in bytes
*
* @note The size of a full USB configuration includes all the interface and endpoint
* descriptors of that configuration.
*/
#define USB_DESC_CFG_SIZE 9
/**
* @brief Structure representing a short USB configuration descriptor
*
* @note The full USB configuration includes all the interface and endpoint
* descriptors of that configuration.
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} USB_DESC_ATTR;
uint8_t val[USB_DESC_CFG_SIZE];
} usb_desc_cfg_t;
_Static_assert(sizeof(usb_desc_cfg_t) == USB_DESC_CFG_SIZE, "Size of usb_desc_cfg_t incorrect");
/**
* @brief Bit masks belonging to the bmAttributes field of a configuration descriptor
*/
#define USB_BM_ATTRIBUTES_ONE (1 << 7) //Must be set
#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) //Self powered
#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) //Can wake-up
#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) //Battery powered
// ---------------- Interface Descriptor -------------------
/**
* @brief Size of a USB interface descriptor in bytes
*/
#define USB_DESC_INTF_SIZE 9
/**
* @brief Structure representing a USB interface descriptor
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} USB_DESC_ATTR;
uint8_t val[USB_DESC_INTF_SIZE];
} usb_desc_intf_t;
_Static_assert(sizeof(usb_desc_intf_t) == USB_DESC_INTF_SIZE, "Size of usb_desc_intf_t incorrect");
// ----------------- Endpoint Descriptor -------------------
/**
* @brief Size of a USB endpoint descriptor in bytes
*/
#define USB_DESC_EP_SIZE 7
/**
* @brief Structure representing a USB endpoint descriptor
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} USB_DESC_ATTR;
uint8_t val[USB_DESC_EP_SIZE];
} usb_desc_ep_t;
_Static_assert(sizeof(usb_desc_ep_t) == USB_DESC_EP_SIZE, "Size of usb_desc_ep_t incorrect");
/**
* @brief Bit masks belonging to the bEndpointAddress field of an endpoint descriptor
*/
#define USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK 0x0f
#define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK 0x80
/**
* @brief Bit masks belonging to the bmAttributes field of an endpoint descriptor
*/
#define USB_BM_ATTRIBUTES_XFERTYPE_MASK 0x03
#define USB_BM_ATTRIBUTES_XFER_CONTROL (0 << 0)
#define USB_BM_ATTRIBUTES_XFER_ISOC (1 << 0)
#define USB_BM_ATTRIBUTES_XFER_BULK (2 << 0)
#define USB_BM_ATTRIBUTES_XFER_INT (3 << 0)
#define USB_BM_ATTRIBUTES_SYNCTYPE_MASK 0x0C /* in bmAttributes */
#define USB_BM_ATTRIBUTES_SYNC_NONE (0 << 2)
#define USB_BM_ATTRIBUTES_SYNC_ASYNC (1 << 2)
#define USB_BM_ATTRIBUTES_SYNC_ADAPTIVE (2 << 2)
#define USB_BM_ATTRIBUTES_SYNC_SYNC (3 << 2)
#define USB_BM_ATTRIBUTES_USAGETYPE_MASK 0x30
#define USB_BM_ATTRIBUTES_USAGE_DATA (0 << 4)
#define USB_BM_ATTRIBUTES_USAGE_FEEDBACK (1 << 4)
#define USB_BM_ATTRIBUTES_USAGE_IMPLICIT_FB (2 << 4)
/**
* @brief Macro helpers to get information about an endpoint from its descriptor
*/
#define USB_DESC_EP_GET_XFERTYPE(desc_ptr) ((usb_transfer_type_t) ((desc_ptr)->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK))
#define USB_DESC_EP_GET_EP_NUM(desc_ptr) ((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK)
#define USB_DESC_EP_GET_EP_DIR(desc_ptr) (((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) ? 1 : 0)
#define USB_DESC_EP_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & 0x7FF)
// ------------------ String Descriptor --------------------
/**
* @brief Size of a short USB string descriptor in bytes
*/
#define USB_DESC_STR_SIZE 4
/**
* @brief Structure representing a USB string descriptor
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wData[1]; /* UTF-16LE encoded */
} USB_DESC_ATTR;
uint8_t val[USB_DESC_STR_SIZE];
} usb_desc_str_t;
_Static_assert(sizeof(usb_desc_str_t) == USB_DESC_STR_SIZE, "Size of usb_desc_str_t incorrect");
#ifdef __cplusplus
}
#endif