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_OTHER_SPEED_CONFIG 0x07
|
||||||
#define USB_DT_DEBUG 0x0A
|
#define USB_DT_DEBUG 0x0A
|
||||||
#define USB_DT_INTERFACE_ASSOC 0x0B
|
#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_INTERFACE 0x24
|
||||||
#define USB_DT_CS_ENDPOINT 0x25
|
#define USB_DT_CS_ENDPOINT 0x25
|
||||||
#define USB_DT_ENDPOINT_COMPANION 0x30
|
#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_CONTROL 0
|
||||||
#define USB_ENDPOINT_XFER_ISOC 1
|
#define USB_ENDPOINT_XFER_ISOC 1
|
||||||
#define USB_ENDPOINT_XFER_BULK 2
|
#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;
|
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)
|
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);
|
trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
|
||||||
break;
|
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:
|
case USB_DT_DEBUG:
|
||||||
/* ignore silently */
|
/* ignore silently */
|
||||||
|
@ -69,6 +69,31 @@ typedef struct USBDescriptor {
|
|||||||
uint8_t wBytesPerInterval_lo;
|
uint8_t wBytesPerInterval_lo;
|
||||||
uint8_t wBytesPerInterval_hi;
|
uint8_t wBytesPerInterval_hi;
|
||||||
} super_endpoint;
|
} 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;
|
} u;
|
||||||
} QEMU_PACKED USBDescriptor;
|
} 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_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_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_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_addr(int addr) "dev %d"
|
||||||
usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %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"
|
usb_set_interface(int addr, int iface, int alt, int ret) "dev %d, interface %d, altsetting %d, ret %d"
|
||||||
|
Loading…
Reference in New Issue
Block a user