mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 01:43:39 +00:00
usb3: bos decriptor
Add support for creating BOS descriptor and device cappability descriptors. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
b43a285176
commit
2077469b58
6
hw/usb.h
6
hw/usb.h
|
@ -135,10 +135,16 @@
|
|||
#define USB_DT_OTHER_SPEED_CONFIG 0x07
|
||||
#define USB_DT_DEBUG 0x0A
|
||||
#define USB_DT_INTERFACE_ASSOC 0x0B
|
||||
#define USB_DT_BOS 0x0F
|
||||
#define USB_DT_DEVICE_CAPABILITY 0x10
|
||||
#define USB_DT_CS_INTERFACE 0x24
|
||||
#define USB_DT_CS_ENDPOINT 0x25
|
||||
#define USB_DT_ENDPOINT_COMPANION 0x30
|
||||
|
||||
#define USB_DEV_CAP_WIRELESS 0x01
|
||||
#define USB_DEV_CAP_USB2_EXT 0x02
|
||||
#define USB_DEV_CAP_SUPERSPEED 0x03
|
||||
|
||||
#define USB_ENDPOINT_XFER_CONTROL 0
|
||||
#define USB_ENDPOINT_XFER_ISOC 1
|
||||
#define USB_ENDPOINT_XFER_BULK 2
|
||||
|
|
109
hw/usb/desc.c
109
hw/usb/desc.c
|
@ -258,6 +258,111 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
|
|||
return bLength;
|
||||
}
|
||||
|
||||
static int usb_desc_cap_usb2_ext(const USBDesc *desc, uint8_t *dest, size_t len)
|
||||
{
|
||||
uint8_t bLength = 0x07;
|
||||
USBDescriptor *d = (void *)dest;
|
||||
|
||||
if (len < bLength) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
d->bLength = bLength;
|
||||
d->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
|
||||
d->u.cap.bDevCapabilityType = USB_DEV_CAP_USB2_EXT;
|
||||
|
||||
d->u.cap.u.usb2_ext.bmAttributes_1 = (1 << 1); /* LPM */
|
||||
d->u.cap.u.usb2_ext.bmAttributes_2 = 0;
|
||||
d->u.cap.u.usb2_ext.bmAttributes_3 = 0;
|
||||
d->u.cap.u.usb2_ext.bmAttributes_4 = 0;
|
||||
|
||||
return bLength;
|
||||
}
|
||||
|
||||
static int usb_desc_cap_super(const USBDesc *desc, uint8_t *dest, size_t len)
|
||||
{
|
||||
uint8_t bLength = 0x0a;
|
||||
USBDescriptor *d = (void *)dest;
|
||||
|
||||
if (len < bLength) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
d->bLength = bLength;
|
||||
d->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
|
||||
d->u.cap.bDevCapabilityType = USB_DEV_CAP_SUPERSPEED;
|
||||
|
||||
d->u.cap.u.super.bmAttributes = 0;
|
||||
d->u.cap.u.super.wSpeedsSupported_lo = 0;
|
||||
d->u.cap.u.super.wSpeedsSupported_hi = 0;
|
||||
d->u.cap.u.super.bFunctionalitySupport = 0;
|
||||
d->u.cap.u.super.bU1DevExitLat = 0x0a;
|
||||
d->u.cap.u.super.wU2DevExitLat_lo = 0x20;
|
||||
d->u.cap.u.super.wU2DevExitLat_hi = 0;
|
||||
|
||||
if (desc->full) {
|
||||
d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 1);
|
||||
d->u.cap.u.super.bFunctionalitySupport = 1;
|
||||
}
|
||||
if (desc->high) {
|
||||
d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 2);
|
||||
if (!d->u.cap.u.super.bFunctionalitySupport) {
|
||||
d->u.cap.u.super.bFunctionalitySupport = 2;
|
||||
}
|
||||
}
|
||||
if (desc->super) {
|
||||
d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 3);
|
||||
if (!d->u.cap.u.super.bFunctionalitySupport) {
|
||||
d->u.cap.u.super.bFunctionalitySupport = 3;
|
||||
}
|
||||
}
|
||||
|
||||
return bLength;
|
||||
}
|
||||
|
||||
static int usb_desc_bos(const USBDesc *desc, uint8_t *dest, size_t len)
|
||||
{
|
||||
uint8_t bLength = 0x05;
|
||||
uint16_t wTotalLength = 0;
|
||||
uint8_t bNumDeviceCaps = 0;
|
||||
USBDescriptor *d = (void *)dest;
|
||||
int rc;
|
||||
|
||||
if (len < bLength) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
d->bLength = bLength;
|
||||
d->bDescriptorType = USB_DT_BOS;
|
||||
|
||||
wTotalLength += bLength;
|
||||
|
||||
if (desc->high != NULL) {
|
||||
rc = usb_desc_cap_usb2_ext(desc, dest + wTotalLength,
|
||||
len - wTotalLength);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
wTotalLength += rc;
|
||||
bNumDeviceCaps++;
|
||||
}
|
||||
|
||||
if (desc->super != NULL) {
|
||||
rc = usb_desc_cap_super(desc, dest + wTotalLength,
|
||||
len - wTotalLength);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
wTotalLength += rc;
|
||||
bNumDeviceCaps++;
|
||||
}
|
||||
|
||||
d->u.bos.wTotalLength_lo = usb_lo(wTotalLength);
|
||||
d->u.bos.wTotalLength_hi = usb_hi(wTotalLength);
|
||||
d->u.bos.bNumDeviceCaps = bNumDeviceCaps;
|
||||
return wTotalLength;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static void usb_desc_ep_init(USBDevice *dev)
|
||||
|
@ -571,6 +676,10 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
|
|||
}
|
||||
trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
|
||||
break;
|
||||
case USB_DT_BOS:
|
||||
ret = usb_desc_bos(desc, buf, sizeof(buf));
|
||||
trace_usb_desc_bos(dev->addr, len, ret);
|
||||
break;
|
||||
|
||||
case USB_DT_DEBUG:
|
||||
/* ignore silently */
|
||||
|
|
|
@ -69,6 +69,31 @@ typedef struct USBDescriptor {
|
|||
uint8_t wBytesPerInterval_lo;
|
||||
uint8_t wBytesPerInterval_hi;
|
||||
} super_endpoint;
|
||||
struct {
|
||||
uint8_t wTotalLength_lo;
|
||||
uint8_t wTotalLength_hi;
|
||||
uint8_t bNumDeviceCaps;
|
||||
} bos;
|
||||
struct {
|
||||
uint8_t bDevCapabilityType;
|
||||
union {
|
||||
struct {
|
||||
uint8_t bmAttributes_1;
|
||||
uint8_t bmAttributes_2;
|
||||
uint8_t bmAttributes_3;
|
||||
uint8_t bmAttributes_4;
|
||||
} usb2_ext;
|
||||
struct {
|
||||
uint8_t bmAttributes;
|
||||
uint8_t wSpeedsSupported_lo;
|
||||
uint8_t wSpeedsSupported_hi;
|
||||
uint8_t bFunctionalitySupport;
|
||||
uint8_t bU1DevExitLat;
|
||||
uint8_t wU2DevExitLat_lo;
|
||||
uint8_t wU2DevExitLat_hi;
|
||||
} super;
|
||||
} u;
|
||||
} cap;
|
||||
} u;
|
||||
} QEMU_PACKED USBDescriptor;
|
||||
|
||||
|
|
|
@ -340,6 +340,7 @@ usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device quali
|
|||
usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
|
||||
usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
|
||||
usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
|
||||
usb_desc_bos(int addr, int len, int ret) "dev %d bos, len %d, ret %d"
|
||||
usb_set_addr(int addr) "dev %d"
|
||||
usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
|
||||
usb_set_interface(int addr, int iface, int alt, int ret) "dev %d, interface %d, altsetting %d, ret %d"
|
||||
|
|
Loading…
Reference in a new issue