Skip to content

Commit 5b5e226

Browse files
committed
usb: device_next: USB 3 support
Introduce definitions to enable USB3 device controllers to be written. So far, USB 3 support got added to the subsystem, UDC common code, the Loopback class, and the CDC-ACM class. Signed-off-by: Josuah Demangeon <me@josuah.net>
1 parent fee8edd commit 5b5e226

File tree

23 files changed

+710
-27
lines changed

23 files changed

+710
-27
lines changed

drivers/usb/udc/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,19 @@ menuconfig UDC_DRIVER
1111

1212
if UDC_DRIVER
1313

14+
config UDC_DRIVER_HAS_SUPER_SPEED_SUPPORT
15+
bool
16+
1417
config UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT
1518
bool
1619

20+
config UDC_DRIVER_SUPER_SPEED_SUPPORT_ENABLED
21+
bool "Allow Super-Speed operation"
22+
default y if UDC_DRIVER_HAS_SUPER_SPEED_SUPPORT
23+
help
24+
Allow Super-Speed capable device to operate at Super-Speed. Disable this
25+
option to force USB 2 only operation.
26+
1727
config UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED
1828
bool "Allow High-Speed chirp"
1929
default y if UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT

drivers/usb/udc/udc_virtual.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,8 @@ static enum udc_bus_speed udc_vrt_device_speed(const struct device *dev)
474474
struct udc_data *data = dev->data;
475475

476476
/* FIXME: get actual device speed */
477-
return data->caps.hs ? UDC_BUS_SPEED_HS : UDC_BUS_SPEED_FS;
477+
return data->caps.ss ? UDC_BUS_SPEED_SS :
478+
data->caps.hs ? UDC_BUS_SPEED_HS : UDC_BUS_SPEED_FS;
478479
}
479480

480481
static int udc_vrt_enable(const struct device *dev)
@@ -559,10 +560,13 @@ static int udc_vrt_driver_preinit(const struct device *dev)
559560

560561
data->caps.rwup = true;
561562
data->caps.mps0 = UDC_MPS0_64;
562-
if (config->speed_idx == 2) {
563+
if (config->speed_idx >= 2) {
563564
data->caps.hs = true;
564565
mps = 1024;
565566
}
567+
if (config->speed_idx >= 3) {
568+
data->caps.ss = true;
569+
}
566570

567571
for (int i = 0; i < config->num_of_eps; i++) {
568572
config->ep_cfg_out[i].caps.out = 1;

include/zephyr/drivers/usb/udc.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enum udc_mps0 {
2626
UDC_MPS0_16,
2727
UDC_MPS0_32,
2828
UDC_MPS0_64,
29+
UDC_MPS0_512,
2930
};
3031

3132
/**
@@ -36,6 +37,8 @@ enum udc_mps0 {
3637
struct udc_device_caps {
3738
/** USB high speed capable controller */
3839
uint32_t hs : 1;
40+
/** USB super speed capable controller */
41+
uint32_t ss : 1;
3942
/** Controller supports USB remote wakeup */
4043
uint32_t rwup : 1;
4144
/** Controller performs status OUT stage automatically */
@@ -45,7 +48,7 @@ struct udc_device_caps {
4548
/** Controller can detect the state change of USB supply VBUS.*/
4649
uint32_t can_detect_vbus : 1;
4750
/** Maximum packet size for control endpoint */
48-
enum udc_mps0 mps0 : 2;
51+
enum udc_mps0 mps0 : 3;
4952
};
5053

5154
/**
@@ -221,7 +224,7 @@ typedef int (*udc_event_cb_t)(const struct device *dev,
221224
* @brief UDC driver API
222225
* This is the mandatory API any USB device controller driver needs to expose
223226
* with exception of:
224-
* device_speed(), test_mode() are only required for HS controllers
227+
* device_speed(), test_mode() are only required for HS and SS controllers
225228
*/
226229
struct udc_api {
227230
enum udc_bus_speed (*device_speed)(const struct device *dev);
@@ -243,6 +246,8 @@ struct udc_api {
243246
int (*host_wakeup)(const struct device *dev);
244247
int (*set_address)(const struct device *dev,
245248
const uint8_t addr);
249+
int (*set_system_exit_latency)(const struct device *dev,
250+
const struct usb_system_exit_latency *sel);
246251
int (*test_mode)(const struct device *dev,
247252
const uint8_t mode, const bool dryrun);
248253
int (*enable)(const struct device *dev);
@@ -407,7 +412,7 @@ int udc_shutdown(const struct device *dev);
407412
* @brief Get USB device controller capabilities
408413
*
409414
* Obtain the capabilities of the controller
410-
* such as full speed (FS), high speed (HS), and more.
415+
* such as full speed (FS), high speed (HS), super speed (SS), and more.
411416
*
412417
* @param[in] dev Pointer to device struct of the driver instance
413418
*
@@ -495,6 +500,40 @@ static inline int udc_test_mode(const struct device *dev,
495500
return ret;
496501
}
497502

503+
/**
504+
* @brief Set USB3 U1/P1 U2/P2 link latency.
505+
*
506+
* USB3 defines link latencies values, and the host is expected to configure
507+
* these parameters for the device through a SET_SEL command, defined in
508+
* USB 3.2 R1 document (section 9.4.12).
509+
*
510+
* @param[in] dev Pointer to device struct of the driver instance
511+
* @param[in] ll Pointer to struct with the latency values from the host
512+
*
513+
* @return 0 on success, all other values should be treated as error.
514+
* @retval -EPERM controller is not enabled (or not initialized)
515+
*/
516+
static inline int udc_set_system_exit_latency(const struct device *dev,
517+
const struct usb_system_exit_latency *sel)
518+
{
519+
const struct udc_api *api = dev->api;
520+
int ret;
521+
522+
if (!udc_is_enabled(dev)) {
523+
return -EPERM;
524+
}
525+
526+
if (api->set_system_exit_latency != NULL) {
527+
api->lock(dev);
528+
ret = api->set_system_exit_latency(dev, sel);
529+
api->unlock(dev);
530+
} else {
531+
ret = -ENOTSUP;
532+
}
533+
534+
return ret;
535+
}
536+
498537
/**
499538
* @brief Initiate host wakeup procedure.
500539
*

include/zephyr/usb/bos.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ struct usb_bos_descriptor {
3030
/** Device capability type codes */
3131
enum usb_bos_capability_types {
3232
USB_BOS_CAPABILITY_EXTENSION = 0x02,
33+
USB_BOS_CAPABILITY_SUPERSPEED_USB = 0x03,
3334
USB_BOS_CAPABILITY_PLATFORM = 0x05,
35+
USB_BOS_CAPABILITY_SUPERSPEED_PLUS = 0x0a,
36+
USB_BOS_CAPABILITY_PRECISION_TIME_MEASUREMENT = 0x0b,
3437
};
3538

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

47+
/** Fields for @ref usb_bos_capability_lpm bmAttributes */
48+
enum usb_bos_attributes {
49+
USB_BOS_ATTRIBUTES_LPM = BIT(1),
50+
USB_BOS_ATTRIBUTES_BESL = BIT(2),
51+
};
52+
4453
/** BOS platform capability descriptor */
4554
struct usb_bos_platform_descriptor {
4655
uint8_t bLength;
@@ -50,6 +59,51 @@ struct usb_bos_platform_descriptor {
5059
uint8_t PlatformCapabilityUUID[16];
5160
} __packed;
5261

62+
/** BOS SuperSpeed device capability descriptor */
63+
struct usb_bos_capability_superspeed_usb {
64+
uint8_t bLength;
65+
uint8_t bDescriptorType;
66+
uint8_t bDevCapabilityType;
67+
uint8_t bmAttributes;
68+
uint16_t wSpeedsSupported;
69+
uint8_t bFunctionnalSupport;
70+
uint8_t bU1DevExitLat;
71+
uint16_t wU2DevExitLat;
72+
} __packed;
73+
74+
/** Fields for @ref usb_bos_capability_superspeed_usb bmAttributes */
75+
enum usb_bos_attributes_superspeed_usb {
76+
USB_BOS_ATTRIBUTES_SUPERSPEED_LTM = BIT(1),
77+
};
78+
79+
/** BOS SuperSpeedPlus device capability descriptor */
80+
struct usb_bos_capability_superspeedplus {
81+
uint8_t bLength;
82+
uint8_t bDescriptorType;
83+
uint8_t bDevCapabilityType;
84+
uint8_t bReserved;
85+
uint16_t bmAttributes;
86+
uint16_t bFunctionnalSupport;
87+
/* Variable size depending on the SSAC value in bmAttributes */
88+
uint32_t bmSublinkSpeedAttr[1];
89+
} __packed;
90+
91+
/** BOS Precision Time Measurement device capability descriptor */
92+
struct usb_bos_capability_precision_time_measurement {
93+
uint8_t bLength;
94+
uint8_t bDescriptorType;
95+
uint8_t bDevCapabilityType;
96+
};
97+
98+
/** BOS description of different speeds supported by the device */
99+
enum usb_bos_speed {
100+
USB_BOS_SPEED_LOWSPEED = BIT(0),
101+
USB_BOS_SPEED_FULLSPEED = BIT(1),
102+
USB_BOS_SPEED_HIGHSPEED = BIT(2),
103+
USB_BOS_SPEED_SUPERSPEED_GEN1 = BIT(3),
104+
USB_BOS_SPEED_SUPERSPEED_GEN2 = BIT(4),
105+
};
106+
53107
/** WebUSB specific part of platform capability descriptor */
54108
struct usb_bos_capability_webusb {
55109
uint16_t bcdVersion;

include/zephyr/usb/usb_ch9.h

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,20 @@ static inline bool usb_reqtype_is_to_device(const struct usb_setup_packet *setup
105105
#define USB_SREQ_GET_INTERFACE 0x0A
106106
#define USB_SREQ_SET_INTERFACE 0x0B
107107
#define USB_SREQ_SYNCH_FRAME 0x0C
108+
/** Additional Request Codes defined in USB 3.2 spec. Table 9-5 */
109+
#define USB_SREQ_SET_ENCRYPTION 0x0D
110+
#define USB_SREQ_GET_ENCRYPTION 0x0E
111+
#define USB_SREQ_SET_HANDSHAKE 0x0F
112+
#define USB_SREQ_GET_HANDSHAKE 0x10
113+
#define USB_SREQ_SET_CONNECTION 0x11
114+
#define USB_SREQ_SET_SECURITY_DATA 0x12
115+
#define USB_SREQ_GET_SECURITY_DATA 0x13
116+
#define USB_SREQ_SET_WUSB_DATA 0x14
117+
#define USB_SREQ_LOOPBACK_DATA_WRITE 0x15
118+
#define USB_SREQ_LOOPBACK_DATA_READ 0x16
119+
#define USB_SREQ_SET_INTERFACE_DS 0x17
120+
#define USB_SREQ_SET_SEL 0x30
121+
#define USB_SREQ_SET_ISOCH_DELAY 0x31
108122

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

125141
/** Class-Specific Descriptor Types as defined by
126142
* USB Common Class Specification
@@ -255,6 +271,23 @@ struct usb_association_descriptor {
255271
uint8_t iFunction;
256272
} __packed;
257273

274+
/** USB Endpoint Companion Descriptor defined in USB3 spec. Table 9-27. */
275+
struct usb_ss_endpoint_companion_descriptor {
276+
uint8_t bLength;
277+
uint8_t bDescriptorType;
278+
uint8_t bMaxBurst;
279+
uint8_t bmAttributes;
280+
uint16_t wBytesPerInterval;
281+
} __packed;
282+
283+
/** USB3 SET_SEL command payload from the host. Section 9.4.12. */
284+
struct usb_system_exit_latency {
285+
uint8_t u1sel;
286+
uint8_t u1pel;
287+
uint16_t u2sel;
288+
uint16_t u2pel;
289+
} __packed;
290+
258291
/** USB Standard Configuration Descriptor Characteristics from Table 9-10 */
259292
#define USB_SCD_RESERVED BIT(7)
260293
#define USB_SCD_SELF_POWERED BIT(6)
@@ -277,7 +310,9 @@ struct usb_association_descriptor {
277310
#define USB_SRN_2_0 0x0200
278311
#define USB_SRN_2_0_1 0x0201
279312
#define USB_SRN_2_1 0x0210
280-
313+
#define USB_SRN_3_0 0x0300
314+
#define USB_SRN_3_1 0x0310
315+
#define USB_SRN_3_2 0x0320
281316
#define USB_DEC_TO_BCD(dec) ((((dec) / 10) << 4) | ((dec) % 10))
282317

283318
/** USB Device release number (bcdDevice Descriptor field) */
@@ -354,12 +389,18 @@ struct usb_association_descriptor {
354389
/** Calculate high speed interrupt endpoint bInterval from a value in microseconds */
355390
#define USB_HS_INT_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U)
356391

357-
/** Calculate high speed isochronous endpoint bInterval from a value in microseconds */
392+
/** Calculate super speed interrupt endpoint bInterval from a value in microseconds */
393+
#define USB_SS_INT_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U)
394+
395+
/** Calculate full speed isochronous endpoint bInterval from a value in microseconds */
358396
#define USB_FS_ISO_EP_INTERVAL(us) CLAMP(((us) / 1000U), 1U, 16U)
359397

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

401+
/** Calculate super speed isochronous endpoint bInterval from a value in microseconds */
402+
#define USB_SS_ISO_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U)
403+
363404
/** Get endpoint size field from Max Packet Size value */
364405
#define USB_MPS_EP_SIZE(mps) ((mps) & BIT_MASK(11))
365406

include/zephyr/usb/usbd.h

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,17 @@ extern "C" {
3737
* @{
3838
*/
3939

40+
/* 1 if USB device stack is compiled with Super-Speed support */
41+
#define USBD_SUPPORTS_SUPER_SPEED IS_EQ(CONFIG_USBD_MAX_SPEED, 2)
42+
4043
/* 1 if USB device stack is compiled with High-Speed support */
41-
#define USBD_SUPPORTS_HIGH_SPEED IS_EQ(CONFIG_USBD_MAX_SPEED, 1)
44+
#define USBD_SUPPORTS_HIGH_SPEED \
45+
UTIL_OR(IS_EQ(CONFIG_USBD_MAX_SPEED, 1), USBD_SUPPORTS_SUPER_SPEED)
4246

4347
/* Maximum bulk max packet size the stack supports */
44-
#define USBD_MAX_BULK_MPS COND_CODE_1(USBD_SUPPORTS_HIGH_SPEED, (512), (64))
48+
#define USBD_MAX_BULK_MPS \
49+
COND_CODE_1(USBD_SUPPORTS_SUPER_SPEED, (1024), \
50+
(COND_CODE_1(USBD_SUPPORTS_HIGH_SPEED, (512), (64))))
4551

4652
/*
4753
* The USB Unicode bString is encoded in UTF16LE, which means it takes up
@@ -303,6 +309,8 @@ struct usbd_context {
303309
sys_slist_t fs_configs;
304310
/** slist to manage High-Speed device configurations */
305311
sys_slist_t hs_configs;
312+
/** slist to manage Super-Speed device configurations */
313+
sys_slist_t ss_configs;
306314
/** dlist to manage vendor requests with recipient device */
307315
sys_dlist_t vreqs;
308316
/** Status of the USB device support */
@@ -311,6 +319,8 @@ struct usbd_context {
311319
void *fs_desc;
312320
/** Pointer to High-Speed device descriptor */
313321
void *hs_desc;
322+
/** Pointer to Super-Speed device descriptor */
323+
void *ss_desc;
314324
};
315325

316326
/**
@@ -510,11 +520,29 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c
510520
.iSerialNumber = 0, \
511521
.bNumConfigurations = 0, \
512522
}; \
523+
static struct usb_device_descriptor \
524+
ss_desc_##device_name = { \
525+
.bLength = sizeof(struct usb_device_descriptor), \
526+
.bDescriptorType = USB_DESC_DEVICE, \
527+
.bcdUSB = sys_cpu_to_le16(USB_SRN_3_2), \
528+
.bDeviceClass = USB_BCC_MISCELLANEOUS, \
529+
.bDeviceSubClass = 2, \
530+
.bDeviceProtocol = 1, \
531+
.bMaxPacketSize0 = 9, \
532+
.idVendor = vid, \
533+
.idProduct = pid, \
534+
.bcdDevice = sys_cpu_to_le16(USB_BCD_DRN), \
535+
.iManufacturer = 0, \
536+
.iProduct = 0, \
537+
.iSerialNumber = 0, \
538+
.bNumConfigurations = 0, \
539+
}; \
513540
static STRUCT_SECTION_ITERABLE(usbd_context, device_name) = { \
514541
.name = STRINGIFY(device_name), \
515542
.dev = udc_dev, \
516543
.fs_desc = &fs_desc_##device_name, \
517544
.hs_desc = &hs_desc_##device_name, \
545+
.ss_desc = &ss_desc_##device_name, \
518546
}
519547

520548
/**
@@ -749,6 +777,10 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c
749777
static STRUCT_SECTION_ITERABLE_ALTERNATE( \
750778
usbd_class_hs, usbd_class_node, class_name##_hs) = { \
751779
.c_data = &class_name, \
780+
}; \
781+
static STRUCT_SECTION_ITERABLE_ALTERNATE( \
782+
usbd_class_ss, usbd_class_node, class_name##_ss) = { \
783+
.c_data = &class_name, \
752784
}
753785

754786
/** @brief Helper to declare request table of usbd_cctx_vendor_req

0 commit comments

Comments
 (0)