usb network: use new descriptor infrastructure.

Switch the usb network driver over to the
new descriptor infrastructure.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2010-11-26 10:25:06 +01:00
parent 4a1e1bc416
commit 30c7d32a0a

View file

@ -25,6 +25,7 @@
#include "qemu-common.h"
#include "usb.h"
#include "usb-desc.h"
#include "net.h"
#include "qemu-queue.h"
#include "sysemu.h"
@ -89,182 +90,209 @@ enum usbstring_idx {
#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
/*
* mostly the same descriptor as the linux gadget rndis driver
*/
static const uint8_t qemu_net_dev_descriptor[] = {
0x12, /* u8 bLength; */
USB_DT_DEVICE, /* u8 bDescriptorType; Device */
0x00, 0x02, /* u16 bcdUSB; v2.0 */
USB_CLASS_COMM, /* u8 bDeviceClass; */
0x00, /* u8 bDeviceSubClass; */
0x00, /* u8 bDeviceProtocol; [ low/full only ] */
0x40, /* u8 bMaxPacketSize0 */
RNDIS_VENDOR_NUM & 0xff, RNDIS_VENDOR_NUM >> 8, /* u16 idVendor; */
RNDIS_PRODUCT_NUM & 0xff, RNDIS_PRODUCT_NUM >> 8, /* u16 idProduct; */
0x00, 0x00, /* u16 bcdDevice */
STRING_MANUFACTURER, /* u8 iManufacturer; */
STRING_PRODUCT, /* u8 iProduct; */
STRING_SERIALNUMBER, /* u8 iSerialNumber; */
0x02, /* u8 bNumConfigurations; */
static const USBDescStrings usb_net_stringtable = {
[STRING_MANUFACTURER] = "QEMU",
[STRING_PRODUCT] = "RNDIS/QEMU USB Network Device",
[STRING_ETHADDR] = "400102030405",
[STRING_DATA] = "QEMU USB Net Data Interface",
[STRING_CONTROL] = "QEMU USB Net Control Interface",
[STRING_RNDIS_CONTROL] = "QEMU USB Net RNDIS Control Interface",
[STRING_CDC] = "QEMU USB Net CDC",
[STRING_SUBSET] = "QEMU USB Net Subset",
[STRING_RNDIS] = "QEMU USB Net RNDIS",
[STRING_SERIALNUMBER] = "1",
};
static const uint8_t qemu_net_rndis_config_descriptor[] = {
/* Configuration Descriptor */
0x09, /* u8 bLength */
USB_DT_CONFIG, /* u8 bDescriptorType */
0x43, 0x00, /* le16 wTotalLength */
0x02, /* u8 bNumInterfaces */
DEV_RNDIS_CONFIG_VALUE, /* u8 bConfigurationValue */
STRING_RNDIS, /* u8 iConfiguration */
0xc0, /* u8 bmAttributes */
0x32, /* u8 bMaxPower */
/* RNDIS Control Interface */
0x09, /* u8 bLength */
USB_DT_INTERFACE, /* u8 bDescriptorType */
0x00, /* u8 bInterfaceNumber */
0x00, /* u8 bAlternateSetting */
0x01, /* u8 bNumEndpoints */
USB_CLASS_COMM, /* u8 bInterfaceClass */
USB_CDC_SUBCLASS_ACM, /* u8 bInterfaceSubClass */
USB_CDC_ACM_PROTO_VENDOR, /* u8 bInterfaceProtocol */
STRING_RNDIS_CONTROL, /* u8 iInterface */
/* Header Descriptor */
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
0x10, 0x01, /* le16 bcdCDC */
/* Call Management Descriptor */
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_CALL_MANAGEMENT_TYPE, /* u8 bDescriptorSubType */
0x00, /* u8 bmCapabilities */
0x01, /* u8 bDataInterface */
/* ACM Descriptor */
0x04, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_ACM_TYPE, /* u8 bDescriptorSubType */
0x00, /* u8 bmCapabilities */
/* Union Descriptor */
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
0x00, /* u8 bMasterInterface0 */
0x01, /* u8 bSlaveInterface0 */
/* Status Descriptor */
0x07, /* u8 bLength */
USB_DT_ENDPOINT, /* u8 bDescriptorType */
USB_DIR_IN | 1, /* u8 bEndpointAddress */
USB_ENDPOINT_XFER_INT, /* u8 bmAttributes */
STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /* le16 wMaxPacketSize */
1 << LOG2_STATUS_INTERVAL_MSEC, /* u8 bInterval */
/* RNDIS Data Interface */
0x09, /* u8 bLength */
USB_DT_INTERFACE, /* u8 bDescriptorType */
0x01, /* u8 bInterfaceNumber */
0x00, /* u8 bAlternateSetting */
0x02, /* u8 bNumEndpoints */
USB_CLASS_CDC_DATA, /* u8 bInterfaceClass */
0x00, /* u8 bInterfaceSubClass */
0x00, /* u8 bInterfaceProtocol */
STRING_DATA, /* u8 iInterface */
/* Source Endpoint */
0x07, /* u8 bLength */
USB_DT_ENDPOINT, /* u8 bDescriptorType */
USB_DIR_IN | 2, /* u8 bEndpointAddress */
USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
0x40, 0x00, /* le16 wMaxPacketSize */
0x00, /* u8 bInterval */
/* Sink Endpoint */
0x07, /* u8 bLength */
USB_DT_ENDPOINT, /* u8 bDescriptorType */
USB_DIR_OUT | 2, /* u8 bEndpointAddress */
USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
0x40, 0x00, /* le16 wMaxPacketSize */
0x00 /* u8 bInterval */
static const USBDescIface desc_iface_rndis[] = {
{
/* RNDIS Control Interface */
.bInterfaceNumber = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_COMM,
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
.bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR,
.iInterface = STRING_RNDIS_CONTROL,
.ndesc = 4,
.descs = (USBDescOther[]) {
{
/* Header Descriptor */
.data = (uint8_t[]) {
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
0x10, 0x01, /* le16 bcdCDC */
},
},{
/* Call Management Descriptor */
.data = (uint8_t[]) {
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_CALL_MANAGEMENT_TYPE, /* u8 bDescriptorSubType */
0x00, /* u8 bmCapabilities */
0x01, /* u8 bDataInterface */
},
},{
/* ACM Descriptor */
.data = (uint8_t[]) {
0x04, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_ACM_TYPE, /* u8 bDescriptorSubType */
0x00, /* u8 bmCapabilities */
},
},{
/* Union Descriptor */
.data = (uint8_t[]) {
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
0x00, /* u8 bMasterInterface0 */
0x01, /* u8 bSlaveInterface0 */
},
},
},
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_IN | 0x01,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = STATUS_BYTECOUNT,
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
},
}
},{
/* RNDIS Data Interface */
.bInterfaceNumber = 1,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_CDC_DATA,
.iInterface = STRING_DATA,
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_IN | 0x02,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 0x40,
},{
.bEndpointAddress = USB_DIR_OUT | 0x02,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 0x40,
}
}
}
};
static const uint8_t qemu_net_cdc_config_descriptor[] = {
/* Configuration Descriptor */
0x09, /* u8 bLength */
USB_DT_CONFIG, /* u8 bDescriptorType */
0x50, 0x00, /* le16 wTotalLength */
0x02, /* u8 bNumInterfaces */
DEV_CONFIG_VALUE, /* u8 bConfigurationValue */
STRING_CDC, /* u8 iConfiguration */
0xc0, /* u8 bmAttributes */
0x32, /* u8 bMaxPower */
/* CDC Control Interface */
0x09, /* u8 bLength */
USB_DT_INTERFACE, /* u8 bDescriptorType */
0x00, /* u8 bInterfaceNumber */
0x00, /* u8 bAlternateSetting */
0x01, /* u8 bNumEndpoints */
USB_CLASS_COMM, /* u8 bInterfaceClass */
USB_CDC_SUBCLASS_ETHERNET, /* u8 bInterfaceSubClass */
USB_CDC_PROTO_NONE, /* u8 bInterfaceProtocol */
STRING_CONTROL, /* u8 iInterface */
/* Header Descriptor */
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
0x10, 0x01, /* le16 bcdCDC */
/* Union Descriptor */
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
0x00, /* u8 bMasterInterface0 */
0x01, /* u8 bSlaveInterface0 */
/* Ethernet Descriptor */
0x0d, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_ETHERNET_TYPE, /* u8 bDescriptorSubType */
STRING_ETHADDR, /* u8 iMACAddress */
0x00, 0x00, 0x00, 0x00, /* le32 bmEthernetStatistics */
ETH_FRAME_LEN & 0xff, ETH_FRAME_LEN >> 8, /* le16 wMaxSegmentSize */
0x00, 0x00, /* le16 wNumberMCFilters */
0x00, /* u8 bNumberPowerFilters */
/* Status Descriptor */
0x07, /* u8 bLength */
USB_DT_ENDPOINT, /* u8 bDescriptorType */
USB_DIR_IN | 1, /* u8 bEndpointAddress */
USB_ENDPOINT_XFER_INT, /* u8 bmAttributes */
STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /* le16 wMaxPacketSize */
1 << LOG2_STATUS_INTERVAL_MSEC, /* u8 bInterval */
/* CDC Data (nop) Interface */
0x09, /* u8 bLength */
USB_DT_INTERFACE, /* u8 bDescriptorType */
0x01, /* u8 bInterfaceNumber */
0x00, /* u8 bAlternateSetting */
0x00, /* u8 bNumEndpoints */
USB_CLASS_CDC_DATA, /* u8 bInterfaceClass */
0x00, /* u8 bInterfaceSubClass */
0x00, /* u8 bInterfaceProtocol */
0x00, /* u8 iInterface */
/* CDC Data Interface */
0x09, /* u8 bLength */
USB_DT_INTERFACE, /* u8 bDescriptorType */
0x01, /* u8 bInterfaceNumber */
0x01, /* u8 bAlternateSetting */
0x02, /* u8 bNumEndpoints */
USB_CLASS_CDC_DATA, /* u8 bInterfaceClass */
0x00, /* u8 bInterfaceSubClass */
0x00, /* u8 bInterfaceProtocol */
STRING_DATA, /* u8 iInterface */
/* Source Endpoint */
0x07, /* u8 bLength */
USB_DT_ENDPOINT, /* u8 bDescriptorType */
USB_DIR_IN | 2, /* u8 bEndpointAddress */
USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
0x40, 0x00, /* le16 wMaxPacketSize */
0x00, /* u8 bInterval */
/* Sink Endpoint */
0x07, /* u8 bLength */
USB_DT_ENDPOINT, /* u8 bDescriptorType */
USB_DIR_OUT | 2, /* u8 bEndpointAddress */
USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
0x40, 0x00, /* le16 wMaxPacketSize */
0x00 /* u8 bInterval */
static const USBDescIface desc_iface_cdc[] = {
{
/* CDC Control Interface */
.bInterfaceNumber = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_COMM,
.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
.bInterfaceProtocol = USB_CDC_PROTO_NONE,
.iInterface = STRING_CONTROL,
.ndesc = 3,
.descs = (USBDescOther[]) {
{
/* Header Descriptor */
.data = (uint8_t[]) {
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
0x10, 0x01, /* le16 bcdCDC */
},
},{
/* Union Descriptor */
.data = (uint8_t[]) {
0x05, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
0x00, /* u8 bMasterInterface0 */
0x01, /* u8 bSlaveInterface0 */
},
},{
/* Ethernet Descriptor */
.data = (uint8_t[]) {
0x0d, /* u8 bLength */
USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
USB_CDC_ETHERNET_TYPE, /* u8 bDescriptorSubType */
STRING_ETHADDR, /* u8 iMACAddress */
0x00, 0x00, 0x00, 0x00, /* le32 bmEthernetStatistics */
ETH_FRAME_LEN & 0xff,
ETH_FRAME_LEN >> 8, /* le16 wMaxSegmentSize */
0x00, 0x00, /* le16 wNumberMCFilters */
0x00, /* u8 bNumberPowerFilters */
},
},
},
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_IN | 0x01,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = STATUS_BYTECOUNT,
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
},
}
},{
/* CDC Data Interface (off) */
.bInterfaceNumber = 1,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_CDC_DATA,
},{
/* CDC Data Interface */
.bInterfaceNumber = 1,
.bAlternateSetting = 1,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_CDC_DATA,
.iInterface = STRING_DATA,
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_IN | 0x02,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 0x40,
},{
.bEndpointAddress = USB_DIR_OUT | 0x02,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 0x40,
}
}
}
};
static const USBDescDevice desc_device_net = {
.bcdUSB = 0x0200,
.bDeviceClass = USB_CLASS_COMM,
.bMaxPacketSize0 = 0x40,
.bNumConfigurations = 2,
.confs = (USBDescConfig[]) {
{
.bNumInterfaces = 2,
.bConfigurationValue = DEV_RNDIS_CONFIG_VALUE,
.iConfiguration = STRING_RNDIS,
.bmAttributes = 0xc0,
.bMaxPower = 0x32,
.nif = ARRAY_SIZE(desc_iface_rndis),
.ifs = desc_iface_rndis,
},{
.bNumInterfaces = 2,
.bConfigurationValue = DEV_CONFIG_VALUE,
.iConfiguration = STRING_CDC,
.bmAttributes = 0xc0,
.bMaxPower = 0x32,
.nif = ARRAY_SIZE(desc_iface_cdc),
.ifs = desc_iface_cdc,
}
},
};
static const USBDesc desc_net = {
.id = {
.idVendor = RNDIS_VENDOR_NUM,
.idProduct = RNDIS_PRODUCT_NUM,
.bcdDevice = 0,
.iManufacturer = STRING_MANUFACTURER,
.iProduct = STRING_PRODUCT,
.iSerialNumber = STRING_SERIALNUMBER,
},
.full = &desc_device_net,
.str = usb_net_stringtable,
};
/*
@ -1010,25 +1038,18 @@ static void usb_net_handle_reset(USBDevice *dev)
{
}
static const char * const usb_net_stringtable[] = {
[STRING_MANUFACTURER] = "QEMU",
[STRING_PRODUCT] = "RNDIS/QEMU USB Network Device",
[STRING_ETHADDR] = "400102030405",
[STRING_DATA] = "QEMU USB Net Data Interface",
[STRING_CONTROL] = "QEMU USB Net Control Interface",
[STRING_RNDIS_CONTROL] = "QEMU USB Net RNDIS Control Interface",
[STRING_CDC] = "QEMU USB Net CDC",
[STRING_SUBSET] = "QEMU USB Net Subset",
[STRING_RNDIS] = "QEMU USB Net RNDIS",
[STRING_SERIALNUMBER] = "1",
};
static int usb_net_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
USBNetState *s = (USBNetState *) dev;
int ret = 0;
int ret;
ret = usb_desc_handle_control(dev, request, value, index, length, data);
if (ret >= 0) {
return ret;
}
ret = 0;
switch(request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@ -1100,64 +1121,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
#endif
break;
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
switch(value >> 8) {
case USB_DT_DEVICE:
ret = sizeof(qemu_net_dev_descriptor);
memcpy(data, qemu_net_dev_descriptor, ret);
break;
case USB_DT_CONFIG:
switch (value & 0xff) {
case 0:
ret = sizeof(qemu_net_rndis_config_descriptor);
memcpy(data, qemu_net_rndis_config_descriptor, ret);
break;
case 1:
ret = sizeof(qemu_net_cdc_config_descriptor);
memcpy(data, qemu_net_cdc_config_descriptor, ret);
break;
default:
goto fail;
}
data[2] = ret & 0xff;
data[3] = ret >> 8;
break;
case USB_DT_STRING:
switch (value & 0xff) {
case 0:
/* language ids */
data[0] = 4;
data[1] = 3;
data[2] = 0x09;
data[3] = 0x04;
ret = 4;
break;
case STRING_ETHADDR:
ret = set_usb_string(data, s->usbstring_mac);
break;
default:
if (ARRAY_SIZE(usb_net_stringtable) > (value & 0xff)) {
ret = set_usb_string(data,
usb_net_stringtable[value & 0xff]);
break;
}
goto fail;
}
break;
default:
goto fail;
}
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;
ret = 1;
@ -1463,6 +1426,7 @@ static int usb_net_initfn(USBDevice *dev)
s->conf.macaddr.a[3],
s->conf.macaddr.a[4],
s->conf.macaddr.a[5]);
usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac);
add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0");
return 0;
@ -1500,6 +1464,7 @@ static struct USBDeviceInfo net_info = {
.qdev.name = "usb-net",
.qdev.fw_name = "network",
.qdev.size = sizeof(USBNetState),
.usb_desc = &desc_net,
.init = usb_net_initfn,
.handle_packet = usb_generic_handle_packet,
.handle_reset = usb_net_handle_reset,