The model by default is piix3-uchi.
Example:
<controller type='usb' index='0' model='ich9-ehci'/>
<p>
Each controller has a mandatory attribute <code>type</code>,
- which must be one of "ide", "fdc", "scsi", "sata", "ccid", or
- "virtio-serial", and a mandatory attribute <code>index</code>
- which is the decimal integer describing in which order the bus
- controller is encountered (for use in <code>controller</code>
- attributes of <code><address></code> elements). The
- "virtio-serial" controller has two additional optional
+ which must be one of "ide", "fdc", "scsi", "sata", "usb",
+ "ccid", or "virtio-serial", and a mandatory
+ attribute <code>index</code> which is the decimal integer
+ describing in which order the bus controller is encountered (for
+ use in <code>controller</code> attributes
+ of <code><address></code> elements). The "virtio-serial"
+ controller has two additional optional
attributes <code>ports</code> and <code>vectors</code>, which
control how many devices can be connected through the
controller. A "scsi" controller has an optional
attribute <code>model</code>, which is one of "auto",
"buslogic", "lsilogic", "lsias1068", or "vmpvscsi".
+ A "usb" controller has an optional attribute <code>model</code>,
+ which is one of "piix3-uhci", "piix4-uhci", "ehci",
+ "ich9-ehci1", "ich9-uhci1", "ich9-uhci2", "ich9-uhci3",
+ "vt82c686b-uhci" or "pci-ohci".
</p>
<p>
<value>scsi</value>
<value>sata</value>
<value>ccid</value>
+ <value>usb</value>
</choice>
</attribute>
</optional>
"scsi",
"sata",
"virtio-serial",
- "ccid")
+ "ccid",
+ "usb")
VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
"auto",
{
if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
return virDomainControllerModelSCSITypeFromString(model);
+ else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_USB)
+ return virDomainControllerModelUSBTypeFromString(model);
return -1;
}
{
if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
return virDomainControllerModelSCSITypeToString(model);
+ else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_USB)
+ return virDomainControllerModelUSBTypeToString(model);
return NULL;
}
VIR_DOMAIN_CONTROLLER_TYPE_SATA,
VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL,
VIR_DOMAIN_CONTROLLER_TYPE_CCID,
+ VIR_DOMAIN_CONTROLLER_TYPE_USB,
VIR_DOMAIN_CONTROLLER_TYPE_LAST
};
"", /* don't support vbox */
"qxl");
+VIR_ENUM_DECL(qemuControllerModelUSB)
+
+VIR_ENUM_IMPL(qemuControllerModelUSB, VIR_DOMAIN_CONTROLLER_MODEL_USB_LAST,
+ "piix3-usb-uhci",
+ "piix4-usb-uhci",
+ "usb-ehci",
+ "ich9-usb-ehci1",
+ "ich9-usb-uhci1",
+ "ich9-usb-uhci2",
+ "ich9-usb-uhci3",
+ "vt82c686b-usb-uhci",
+ "pci-ohci");
+
+
static void
uname_normalize (struct utsname *ut)
{
}
+static int
+qemuControllerModelUSBToCaps(int model)
+{
+ switch (model) {
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI:
+ return QEMU_CAPS_PIIX3_USB_UHCI;
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI:
+ return QEMU_CAPS_PIIX4_USB_UHCI;
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI:
+ return QEMU_CAPS_USB_EHCI;
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
+ return QEMU_CAPS_ICH9_USB_EHCI1;
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI:
+ return QEMU_CAPS_VT82C686B_USB_UHCI;
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI:
+ return QEMU_CAPS_PCI_OHCI;
+ default:
+ return -1;
+ }
+}
+
+
+static int
+qemuBuildUSBControllerDevStr(virDomainControllerDefPtr def,
+ virBitmapPtr qemuCaps,
+ virBuffer *buf)
+{
+ const char *smodel;
+ int model, caps;
+
+ model = def->model;
+ if (model == -1)
+ model = VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI;
+
+ smodel = qemuControllerModelUSBTypeToString(model);
+ caps = qemuControllerModelUSBToCaps(model);
+
+ if (caps == -1 || !qemuCapsGet(qemuCaps, caps)) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("%s not supported in this QEMU binary"), smodel);
+ return -1;
+ }
+
+ virBufferAsprintf(buf, "%s,id=usb%d", smodel, def->idx);
+ return 0;
+}
+
char *
qemuBuildControllerDevStr(virDomainControllerDefPtr def,
- virBitmapPtr qemuCaps)
+ virBitmapPtr qemuCaps,
+ int *nusbcontroller)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAsprintf(&buf, "usb-ccid,id=ccid%d", def->idx);
break;
+ case VIR_DOMAIN_CONTROLLER_TYPE_USB:
+ if (qemuBuildUSBControllerDevStr(def, qemuCaps, &buf) == -1)
+ goto error;
+
+ if (nusbcontroller)
+ *nusbcontroller += 1;
+
+ break;
+
/* We always get an IDE controller, whether we want it or not. */
case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
default:
bool has_rbd_hosts = false;
virBuffer rbd_hosts = VIR_BUFFER_INITIALIZER;
bool emitBootindex = false;
-
+ int usbcontroller = 0;
+ bool usblegacy = false;
uname_normalize(&ut);
if (qemuAssignDeviceAliases(def, qemuCaps) < 0)
goto error;
}
- virCommandAddArg(cmd, "-device");
+ if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
+ def->controllers[i]->model == -1 &&
+ !qemuCapsGet(qemuCaps, QEMU_CAPS_PIIX3_USB_UHCI)) {
+ if (usblegacy) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Multiple legacy USB controller not supported"));
+ goto error;
+ }
+ usblegacy = true;
+ } else {
+ virCommandAddArg(cmd, "-device");
- char *devstr;
- if (!(devstr = qemuBuildControllerDevStr(def->controllers[i], qemuCaps)))
- goto error;
+ char *devstr;
+ if (!(devstr = qemuBuildControllerDevStr(def->controllers[i], qemuCaps,
+ &usbcontroller)))
+ goto error;
- virCommandAddArg(cmd, devstr);
- VIR_FREE(devstr);
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
+ }
}
}
}
}
- virCommandAddArg(cmd, "-usb");
+ if (usbcontroller == 0)
+ virCommandAddArg(cmd, "-usb");
+
for (i = 0 ; i < def->ninputs ; i++) {
virDomainInputDefPtr input = def->inputs[i];
virBitmapPtr qemuCaps);
/* Current, best practice */
char * qemuBuildControllerDevStr(virDomainControllerDefPtr def,
- virBitmapPtr qemuCaps);
+ virBitmapPtr qemuCaps,
+ int *nusbcontroller);
char * qemuBuildWatchdogDevStr(virDomainWatchdogDefPtr dev,
virBitmapPtr qemuCaps);
if (qemuAssignDeviceControllerAlias(controller) < 0)
goto cleanup;
- if (!(devstr = qemuBuildControllerDevStr(controller, priv->qemuCaps))) {
+ if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
+ controller->model == -1 &&
+ !qemuCapsGet(priv->qemuCaps, QEMU_CAPS_PIIX3_USB_UHCI)) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("USB controller hotplug unsupported in this QEMU binary"));
+ goto cleanup;
+ }
+
+ if (!(devstr = qemuBuildControllerDevStr(controller, priv->qemuCaps, NULL))) {
goto cleanup;
}
}
QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE,
QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CCID_EMULATED);
+ DO_TEST("usb-controller", false,
+ QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE,
+ QEMU_CAPS_NODEFCONFIG);
+ DO_TEST("usb-piix3-controller", false,
+ QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_PIIX3_USB_UHCI,
+ QEMU_CAPS_NODEFCONFIG);
+
DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);
DO_TEST("watchdog", false, NONE);