Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions drivers/usb/udc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,19 @@ menuconfig UDC_DRIVER

if UDC_DRIVER

config UDC_DRIVER_HAS_SUPER_SPEED_SUPPORT
bool

config UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT
bool

config UDC_DRIVER_SUPER_SPEED_SUPPORT_ENABLED
bool "Allow Super-Speed operation"
default y if UDC_DRIVER_HAS_SUPER_SPEED_SUPPORT
help
Allow Super-Speed capable device to operate at Super-Speed. Disable this
option to force USB 2 only operation.

config UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED
bool "Allow High-Speed chirp"
default y if UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT
Expand Down
8 changes: 6 additions & 2 deletions drivers/usb/udc/udc_virtual.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,8 @@ static enum udc_bus_speed udc_vrt_device_speed(const struct device *dev)
struct udc_data *data = dev->data;

/* FIXME: get actual device speed */
return data->caps.hs ? UDC_BUS_SPEED_HS : UDC_BUS_SPEED_FS;
return data->caps.ss ? UDC_BUS_SPEED_SS :
data->caps.hs ? UDC_BUS_SPEED_HS : UDC_BUS_SPEED_FS;
}

static int udc_vrt_enable(const struct device *dev)
Expand Down Expand Up @@ -576,10 +577,13 @@ static int udc_vrt_driver_preinit(const struct device *dev)

data->caps.rwup = true;
data->caps.mps0 = UDC_MPS0_64;
if (config->speed_idx == 2) {
if (config->speed_idx >= 2) {
data->caps.hs = true;
mps = 1024;
}
if (config->speed_idx >= 3) {
data->caps.ss = true;
}

for (int i = 0; i < config->num_of_eps; i++) {
config->ep_cfg_out[i].caps.out = 1;
Expand Down
45 changes: 42 additions & 3 deletions include/zephyr/drivers/usb/udc.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum udc_mps0 {
UDC_MPS0_16,
UDC_MPS0_32,
UDC_MPS0_64,
UDC_MPS0_512,
};

/**
Expand All @@ -36,6 +37,8 @@ enum udc_mps0 {
struct udc_device_caps {
/** USB high speed capable controller */
uint32_t hs : 1;
/** USB super speed capable controller */
uint32_t ss : 1;
/** Controller supports USB remote wakeup */
uint32_t rwup : 1;
/** Controller performs status OUT stage automatically */
Expand All @@ -45,7 +48,7 @@ struct udc_device_caps {
/** Controller can detect the state change of USB supply VBUS.*/
uint32_t can_detect_vbus : 1;
/** Maximum packet size for control endpoint */
enum udc_mps0 mps0 : 2;
enum udc_mps0 mps0 : 3;
};

/**
Expand Down Expand Up @@ -221,7 +224,7 @@ typedef int (*udc_event_cb_t)(const struct device *dev,
* @brief UDC driver API
* This is the mandatory API any USB device controller driver needs to expose
* with exception of:
* device_speed(), test_mode() are only required for HS controllers
* device_speed(), test_mode() are only required for HS and SS controllers
*/
struct udc_api {
enum udc_bus_speed (*device_speed)(const struct device *dev);
Expand All @@ -243,6 +246,8 @@ struct udc_api {
int (*host_wakeup)(const struct device *dev);
int (*set_address)(const struct device *dev,
const uint8_t addr);
int (*set_system_exit_latency)(const struct device *dev,
const struct usb_system_exit_latency *sel);
int (*test_mode)(const struct device *dev,
const uint8_t mode, const bool dryrun);
int (*enable)(const struct device *dev);
Expand Down Expand Up @@ -407,7 +412,7 @@ int udc_shutdown(const struct device *dev);
* @brief Get USB device controller capabilities
*
* Obtain the capabilities of the controller
* such as full speed (FS), high speed (HS), and more.
* such as full speed (FS), high speed (HS), super speed (SS), and more.
*
* @param[in] dev Pointer to device struct of the driver instance
*
Expand Down Expand Up @@ -495,6 +500,40 @@ static inline int udc_test_mode(const struct device *dev,
return ret;
}

/**
* @brief Set USB3 U1/P1 U2/P2 link latency.
*
* USB3 defines link latencies values, and the host is expected to configure
* these parameters for the device through a SET_SEL command, defined in
* USB 3.2 R1 document (section 9.4.12).
*
* @param[in] dev Pointer to device struct of the driver instance
* @param[in] sel Pointer to struct with the latency values from the host
*
* @return 0 on success, all other values should be treated as error.
* @retval -EPERM controller is not enabled (or not initialized)
*/
static inline int udc_set_system_exit_latency(const struct device *dev,
const struct usb_system_exit_latency *sel)
{
const struct udc_api *api = dev->api;
int ret;

if (!udc_is_enabled(dev)) {
return -EPERM;
}

if (api->set_system_exit_latency != NULL) {
api->lock(dev);
ret = api->set_system_exit_latency(dev, sel);
api->unlock(dev);
} else {
ret = -ENOTSUP;
}

return ret;
}

/**
* @brief Initiate host wakeup procedure.
*
Expand Down
54 changes: 54 additions & 0 deletions include/zephyr/usb/bos.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ struct usb_bos_descriptor {
/** Device capability type codes */
enum usb_bos_capability_types {
USB_BOS_CAPABILITY_EXTENSION = 0x02,
USB_BOS_CAPABILITY_SUPERSPEED_USB = 0x03,
USB_BOS_CAPABILITY_PLATFORM = 0x05,
USB_BOS_CAPABILITY_SUPERSPEED_PLUS = 0x0a,
USB_BOS_CAPABILITY_PRECISION_TIME_MEASUREMENT = 0x0b,
};

/** BOS USB 2.0 extension capability descriptor */
Expand All @@ -41,6 +44,12 @@ struct usb_bos_capability_lpm {
uint32_t bmAttributes;
} __packed;

/** Fields for @ref usb_bos_capability_lpm bmAttributes */
enum usb_bos_attributes {
USB_BOS_ATTRIBUTES_LPM = BIT(1),
USB_BOS_ATTRIBUTES_BESL = BIT(2),
};

/** BOS platform capability descriptor */
struct usb_bos_platform_descriptor {
uint8_t bLength;
Expand All @@ -50,6 +59,51 @@ struct usb_bos_platform_descriptor {
uint8_t PlatformCapabilityUUID[16];
} __packed;

/** BOS SuperSpeed device capability descriptor */
struct usb_bos_capability_superspeed_usb {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDevCapabilityType;
uint8_t bmAttributes;
uint16_t wSpeedsSupported;
uint8_t bFunctionnalSupport;
uint8_t bU1DevExitLat;
uint16_t wU2DevExitLat;
} __packed;

/** Fields for @ref usb_bos_capability_superspeed_usb bmAttributes */
enum usb_bos_attributes_superspeed_usb {
USB_BOS_ATTRIBUTES_SUPERSPEED_LTM = BIT(1),
};

/** BOS SuperSpeedPlus device capability descriptor */
struct usb_bos_capability_superspeedplus {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDevCapabilityType;
uint8_t bReserved;
uint16_t bmAttributes;
uint16_t bFunctionnalSupport;
/* Variable size depending on the SSAC value in bmAttributes */
uint32_t bmSublinkSpeedAttr[1];
} __packed;

/** BOS Precision Time Measurement device capability descriptor */
struct usb_bos_capability_precision_time_measurement {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDevCapabilityType;
};

/** BOS description of different speeds supported by the device */
enum usb_bos_speed {
USB_BOS_SPEED_LOWSPEED = BIT(0),
USB_BOS_SPEED_FULLSPEED = BIT(1),
USB_BOS_SPEED_HIGHSPEED = BIT(2),
USB_BOS_SPEED_SUPERSPEED_GEN1 = BIT(3),
USB_BOS_SPEED_SUPERSPEED_GEN2 = BIT(4),
};

/** WebUSB specific part of platform capability descriptor */
struct usb_bos_capability_webusb {
uint16_t bcdVersion;
Expand Down
43 changes: 42 additions & 1 deletion include/zephyr/usb/usb_ch9.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ static inline bool usb_reqtype_is_to_device(const struct usb_setup_packet *setup
#define USB_SREQ_GET_INTERFACE 0x0A
#define USB_SREQ_SET_INTERFACE 0x0B
#define USB_SREQ_SYNCH_FRAME 0x0C
/** Additional Request Codes defined in USB 3.2 spec. Table 9-5 */
#define USB_SREQ_SET_ENCRYPTION 0x0D
#define USB_SREQ_GET_ENCRYPTION 0x0E
#define USB_SREQ_SET_HANDSHAKE 0x0F
#define USB_SREQ_GET_HANDSHAKE 0x10
#define USB_SREQ_SET_CONNECTION 0x11
#define USB_SREQ_SET_SECURITY_DATA 0x12
#define USB_SREQ_GET_SECURITY_DATA 0x13
#define USB_SREQ_SET_WUSB_DATA 0x14
#define USB_SREQ_LOOPBACK_DATA_WRITE 0x15
#define USB_SREQ_LOOPBACK_DATA_READ 0x16
#define USB_SREQ_SET_INTERFACE_DS 0x17
#define USB_SREQ_SET_SEL 0x30
#define USB_SREQ_SET_ISOCH_DELAY 0x31

/** Descriptor Types defined in spec. Table 9-5 */
#define USB_DESC_DEVICE 1
Expand All @@ -121,6 +135,8 @@ static inline bool usb_reqtype_is_to_device(const struct usb_setup_packet *setup
#define USB_DESC_INTERFACE_ASSOC 11
#define USB_DESC_BOS 15
#define USB_DESC_DEVICE_CAPABILITY 16
#define USB_DESC_ENDPOINT_COMPANION 48
#define USB_DESC_ISO_ENDPOINT_COMPANION 49

/** Class-Specific Descriptor Types as defined by
* USB Common Class Specification
Expand Down Expand Up @@ -255,6 +271,23 @@ struct usb_association_descriptor {
uint8_t iFunction;
} __packed;

/** USB Endpoint Companion Descriptor defined in USB3 spec. Table 9-27. */
struct usb_ss_endpoint_companion_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bMaxBurst;
uint8_t bmAttributes;
uint16_t wBytesPerInterval;
} __packed;

/** USB3 SET_SEL command payload from the host. Section 9.4.12. */
struct usb_system_exit_latency {
uint8_t u1sel;
uint8_t u1pel;
uint16_t u2sel;
uint16_t u2pel;
} __packed;

/** USB Standard Configuration Descriptor Characteristics from Table 9-10 */
#define USB_SCD_RESERVED BIT(7)
#define USB_SCD_SELF_POWERED BIT(6)
Expand All @@ -277,7 +310,9 @@ struct usb_association_descriptor {
#define USB_SRN_2_0 0x0200
#define USB_SRN_2_0_1 0x0201
#define USB_SRN_2_1 0x0210

#define USB_SRN_3_0 0x0300
#define USB_SRN_3_1 0x0310
#define USB_SRN_3_2 0x0320
#define USB_DEC_TO_BCD(dec) ((((dec) / 10) << 4) | ((dec) % 10))

/** USB Device release number (bcdDevice Descriptor field) */
Expand Down Expand Up @@ -357,9 +392,15 @@ struct usb_association_descriptor {
/** Calculate full speed isochronous endpoint bInterval from a value in microseconds */
#define USB_FS_ISO_EP_INTERVAL(us) CLAMP((ilog2((us) / 1000U) + 1U), 1U, 16U)

/** Calculate super speed interrupt endpoint bInterval from a value in microseconds */
#define USB_SS_INT_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U)

/** Calculate high speed isochronous endpoint bInterval from a value in microseconds */
#define USB_HS_ISO_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U)

/** Calculate super speed isochronous endpoint bInterval from a value in microseconds */
#define USB_SS_ISO_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U)

/** Get endpoint size field from Max Packet Size value */
#define USB_MPS_EP_SIZE(mps) ((mps) & BIT_MASK(11))

Expand Down
44 changes: 41 additions & 3 deletions include/zephyr/usb/usbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,17 @@ extern "C" {
* @{
*/

/* 1 if USB device stack is compiled with Super-Speed support */
#define USBD_SUPPORTS_SUPER_SPEED IS_EQ(CONFIG_USBD_MAX_SPEED, 2)

/* 1 if USB device stack is compiled with High-Speed support */
#define USBD_SUPPORTS_HIGH_SPEED IS_EQ(CONFIG_USBD_MAX_SPEED, 1)
#define USBD_SUPPORTS_HIGH_SPEED \
UTIL_OR(IS_EQ(CONFIG_USBD_MAX_SPEED, 1), USBD_SUPPORTS_SUPER_SPEED)

/* Maximum bulk max packet size the stack supports */
#define USBD_MAX_BULK_MPS COND_CODE_1(USBD_SUPPORTS_HIGH_SPEED, (512), (64))
#define USBD_MAX_BULK_MPS \
COND_CODE_1(USBD_SUPPORTS_SUPER_SPEED, (1024), \
(COND_CODE_1(USBD_SUPPORTS_HIGH_SPEED, (512), (64))))

/*
* The length of the string descriptor (bLength) is calculated from the
Expand Down Expand Up @@ -295,6 +301,8 @@ struct usbd_context {
sys_slist_t fs_configs;
/** slist to manage High-Speed device configurations */
sys_slist_t hs_configs;
/** slist to manage Super-Speed device configurations */
sys_slist_t ss_configs;
/** dlist to manage vendor requests with recipient device */
sys_dlist_t vreqs;
/** Status of the USB device support */
Expand All @@ -303,6 +311,8 @@ struct usbd_context {
void *fs_desc;
/** Pointer to High-Speed device descriptor */
void *hs_desc;
/** Pointer to Super-Speed device descriptor */
void *ss_desc;
};

/**
Expand Down Expand Up @@ -504,13 +514,35 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c
.bNumConfigurations = 0, \
}; \
)) \
IF_ENABLED(USBD_SUPPORTS_SUPER_SPEED, ( \
static struct usb_device_descriptor \
ss_desc_##device_name = { \
.bLength = sizeof(struct usb_device_descriptor), \
.bDescriptorType = USB_DESC_DEVICE, \
.bcdUSB = sys_cpu_to_le16(USB_SRN_3_2), \
.bDeviceClass = USB_BCC_MISCELLANEOUS, \
.bDeviceSubClass = 2, \
.bDeviceProtocol = 1, \
.bMaxPacketSize0 = 9, \
.idVendor = vid, \
.idProduct = pid, \
.bcdDevice = sys_cpu_to_le16(USB_BCD_DRN), \
.iManufacturer = 0, \
.iProduct = 0, \
.iSerialNumber = 0, \
.bNumConfigurations = 0, \
}; \
)) \
static STRUCT_SECTION_ITERABLE(usbd_context, device_name) = { \
.name = STRINGIFY(device_name), \
.dev = udc_dev, \
.fs_desc = &fs_desc_##device_name, \
IF_ENABLED(USBD_SUPPORTS_HIGH_SPEED, ( \
.hs_desc = &hs_desc_##device_name, \
)) \
IF_ENABLED(USBD_SUPPORTS_SUPER_SPEED, ( \
.ss_desc = &ss_desc_##device_name, \
)) \
}

/**
Expand Down Expand Up @@ -762,7 +794,13 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c
static STRUCT_SECTION_ITERABLE_ALTERNATE( \
usbd_class_hs, usbd_class_node, class_name##_hs) = { \
.c_data = &class_name, \
} \
}; \
)) \
IF_ENABLED(USBD_SUPPORTS_SUPER_SPEED, ( \
static STRUCT_SECTION_ITERABLE_ALTERNATE( \
usbd_class_ss, usbd_class_node, class_name##_ss) = { \
.c_data = &class_name, \
}; \
))

/** @brief Helper to declare request table of usbd_cctx_vendor_req
Expand Down
Loading
Loading