Currently, libvirt could not tell what usb specification a certain USB
device is running on or what kind of usb spec a USB controller
supports. For example,
USB controller:
piix3-usb-uhci, piix4-usb-uhci, ohci only support USB 1.1
usb-ehci and ich9-usb-ehci1 only support USB 2.0
ich9-usb-ehci1 + ich9-usb-uhci{1|2|3} supports both USB 1.1 and USB 2.0
nec-usb-xhci supports USB 1.1, 2.0, 3.0
USB device:
Most of them only support USB 1.1
usb-tablet Supports USB 1.1 and 2.0(in qemu 1.3 & older 1.1 only)
usb-uas is USB 2.0 or above device.
usb-storage supports USB1.1, 2.0 and 3.0
The usb spec may change over time for USB device, for USB constrollers it
is fixed(From Gerd Hoffmann).
So this patch tries to record usb spec infomation and port number supported
by usb constrollers. Based on these info, we can simply check whether a usb
device goes with right controller.
---
src/conf/domain_conf.c | 32 ++++++++++++++++----------------
src/conf/domain_conf.h | 24 +++++++++++++++++++++++-
src/qemu/qemu_command.c | 8 ++++----
3 files changed, 43 insertions(+), 21 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6feded4..646baab 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4507,30 +4507,30 @@ virDomainControllerDefParseXML(xmlNodePtr node,
char *ports = virXMLPropString(node, "ports");
if (ports) {
int r = virStrToLong_i(ports, NULL, 10,
- &def->opts.vioserial.ports);
- if (r != 0 || def->opts.vioserial.ports < 0) {
+ &def->data.vioserial.ports);
+ if (r != 0 || def->data.vioserial.ports < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Invalid ports: %s"), ports);
VIR_FREE(ports);
goto error;
}
} else {
- def->opts.vioserial.ports = -1;
+ def->data.vioserial.ports = -1;
}
VIR_FREE(ports);
char *vectors = virXMLPropString(node, "vectors");
if (vectors) {
int r = virStrToLong_i(vectors, NULL, 10,
- &def->opts.vioserial.vectors);
- if (r != 0 || def->opts.vioserial.vectors < 0) {
+ &def->data.vioserial.vectors);
+ if (r != 0 || def->data.vioserial.vectors < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Invalid vectors: %s"), vectors);
VIR_FREE(vectors);
goto error;
}
} else {
- def->opts.vioserial.vectors = -1;
+ def->data.vioserial.vectors = -1;
}
VIR_FREE(vectors);
break;
@@ -8818,8 +8818,8 @@ static int virDomainDefMaybeAddController(virDomainDefPtr def,
cont->model = -1;
if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL) {
- cont->opts.vioserial.ports = -1;
- cont->opts.vioserial.vectors = -1;
+ cont->data.vioserial.ports = -1;
+ cont->data.vioserial.vectors = -1;
}
@@ -10895,17 +10895,17 @@ static bool
virDomainControllerDefCheckABIStability(virDomainControllerDefPtr sr
}
if (src->type == VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL) {
- if (src->opts.vioserial.ports != dst->opts.vioserial.ports) {
+ if (src->data.vioserial.ports != dst->data.vioserial.ports) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target controller ports %d does not match source
%d"),
- dst->opts.vioserial.ports, src->opts.vioserial.ports);
+ dst->data.vioserial.ports, src->data.vioserial.ports);
goto cleanup;
}
- if (src->opts.vioserial.vectors != dst->opts.vioserial.vectors) {
+ if (src->data.vioserial.vectors != dst->data.vioserial.vectors) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target controller vectors %d does not match source
%d"),
- dst->opts.vioserial.vectors,
src->opts.vioserial.vectors);
+ dst->data.vioserial.vectors,
src->data.vioserial.vectors);
goto cleanup;
}
}
@@ -12497,13 +12497,13 @@ virDomainControllerDefFormat(virBufferPtr buf,
switch (def->type) {
case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
- if (def->opts.vioserial.ports != -1) {
+ if (def->data.vioserial.ports != -1) {
virBufferAsprintf(buf, " ports='%d'",
- def->opts.vioserial.ports);
+ def->data.vioserial.ports);
}
- if (def->opts.vioserial.vectors != -1) {
+ if (def->data.vioserial.vectors != -1) {
virBufferAsprintf(buf, " vectors='%d'",
- def->opts.vioserial.vectors);
+ def->data.vioserial.vectors);
}
break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 2ac338c..67143a5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -701,6 +701,27 @@ struct _virDomainVirtioSerialOpts {
int vectors; /* -1 == undef */
};
+enum virDomainUSBSpec {
+ VIR_DOMAIN_USB_SPEC_NONE = 0,
+ VIR_DOMAIN_USB_SEPC_1_1 = 1 << 0,
+ VIR_DOMAIN_USB_SPEC_2_0 = 1 << 1,
+ VIR_DOMAIN_USB_SPEC_3_0 = 1 << 2,
+};
+
+enum virDomainUSBControllerPortNumber {
+ VIR_DOMAIN_USB_CONTROLLER_UHCI_PORTN_2 = 2,
+ VIR_DOMAIN_USB_CONTROLLER_OHCI_PORTN_3 = 3,
+ VIR_DOMAIN_USB_CONTROLLER_XHCI_PORTN_4 = 4,
+ VIR_DOMAIN_USB_CONTROLLER_EHCI_PORTN_6 = 6,
+};
+
+typedef struct _virDomainUSBControllerData virDomainUSBControllerData;
+typedef virDomainUSBControllerData *virDomainUSBControllerDataPtr;
+struct _virDomainUSBControllerData {
+ unsigned int spec;
+ size_t nports;
+};
+
/* Stores the virtual disk controller configuration */
struct _virDomainControllerDef {
int type;
@@ -708,7 +729,8 @@ struct _virDomainControllerDef {
int model; /* -1 == undef */
union {
virDomainVirtioSerialOpts vioserial;
- } opts;
+ virDomainUSBControllerData usb;
+ } data;
virDomainDeviceInfo info;
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 981c692..71e69f3 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3083,13 +3083,13 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
}
virBufferAsprintf(&buf, ",id=" QEMU_VIRTIO_SERIAL_PREFIX
"%d",
def->idx);
- if (def->opts.vioserial.ports != -1) {
+ if (def->data.vioserial.ports != -1) {
virBufferAsprintf(&buf, ",max_ports=%d",
- def->opts.vioserial.ports);
+ def->data.vioserial.ports);
}
- if (def->opts.vioserial.vectors != -1) {
+ if (def->data.vioserial.vectors != -1) {
virBufferAsprintf(&buf, ",vectors=%d",
- def->opts.vioserial.vectors);
+ def->data.vioserial.vectors);
}
break;
--
1.7.11.4