[libvirt] [v2 04/13] Add a new controller type 'usb' with optionnal 'model'

Marc-André Lureau marcandre.lureau at gmail.com
Thu Aug 25 22:44:20 UTC 2011


The model by default is piix3-uchi.

Example:
<controller type='usb' index='0' model='ich9-ehci'/>
---
 docs/formatdomain.html.in                          |   17 ++-
 docs/schemas/domain.rng                            |    1 +
 src/conf/domain_conf.c                             |    7 +-
 src/conf/domain_conf.h                             |    1 +
 src/qemu/qemu_command.c                            |  117 ++++++++++++++++++--
 src/qemu/qemu_command.h                            |    3 +-
 src/qemu/qemu_hotplug.c                            |   10 ++-
 .../qemuxml2argv-usb-controller.args               |    1 +
 .../qemuxml2argv-usb-controller.xml                |   16 +++
 .../qemuxml2argv-usb-piix3-controller.args         |    1 +
 .../qemuxml2argv-usb-piix3-controller.xml          |   16 +++
 tests/qemuxml2argvtest.c                           |    7 +
 12 files changed, 179 insertions(+), 18 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb-controller.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb-controller.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index f46771d..5552fbc 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1217,17 +1217,22 @@
 
     <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>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 04c9b61..82a4339 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -877,6 +877,7 @@
                 <value>scsi</value>
                 <value>sata</value>
                 <value>ccid</value>
+                <value>usb</value>
               </choice>
             </attribute>
           </optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0361065..10bc130 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -193,7 +193,8 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
               "scsi",
               "sata",
               "virtio-serial",
-              "ccid")
+              "ccid",
+              "usb")
 
 VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
               "auto",
@@ -2472,6 +2473,8 @@ virDomainControllerModelTypeFromString(const virDomainControllerDefPtr def,
 {
     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;
 }
@@ -8760,6 +8763,8 @@ virDomainControllerModelTypeToString(virDomainControllerDefPtr def,
 {
     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;
 }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e378a9c..0f5e974 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -252,6 +252,7 @@ enum virDomainControllerType {
     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
 };
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index dbfc7d9..2f32e37 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -83,6 +83,30 @@ VIR_ENUM_IMPL(qemuVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
               "", /* don't support vbox */
               "qxl");
 
+VIR_ENUM_DECL(qemuControllerModelSCSI)
+
+VIR_ENUM_IMPL(qemuControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
+              "", /* auto */
+              "", /* buslogic don't support */
+              "", /* lsilogic don't support */
+              "", /* lsisas don't support */
+              "", /* vmpvscsi don't support */
+              );
+
+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)
 {
@@ -1684,9 +1708,60 @@ error:
 }
 
 
+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;
 
@@ -1718,6 +1793,15 @@ qemuBuildControllerDevStr(virDomainControllerDefPtr def,
         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:
@@ -2885,7 +2969,8 @@ qemuBuildCommandLine(virConnectPtr conn,
     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)
@@ -3404,14 +3489,26 @@ qemuBuildCommandLine(virConnectPtr conn,
                 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);
+            }
         }
     }
 
@@ -4116,7 +4213,9 @@ qemuBuildCommandLine(virConnectPtr conn,
         }
     }
 
-    virCommandAddArg(cmd, "-usb");
+    if (usbcontroller == 0)
+        virCommandAddArg(cmd, "-usb");
+
     for (i = 0 ; i < def->ninputs ; i++) {
         virDomainInputDefPtr input = def->inputs[i];
 
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 87660f2..099d683 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -89,7 +89,8 @@ char * qemuBuildFSDevStr(virDomainFSDefPtr fs,
                          virBitmapPtr qemuCaps);
 /* Current, best practice */
 char * qemuBuildControllerDevStr(virDomainControllerDefPtr def,
-                                 virBitmapPtr qemuCaps);
+                                 virBitmapPtr qemuCaps,
+                                 int *nusbcontroller);
 
 char * qemuBuildWatchdogDevStr(virDomainWatchdogDefPtr dev,
                                virBitmapPtr qemuCaps);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index b7fdfa0..b2da6d0 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -286,7 +286,15 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver,
         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;
         }
     }
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-controller.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-controller.args
new file mode 100644
index 0000000..f21efc7
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-controller.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-controller.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb-controller.xml
new file mode 100644
index 0000000..82b503e
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-controller.xml
@@ -0,0 +1,16 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219136</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.args
new file mode 100644
index 0000000..799b75f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device piix3-usb-uhci,id=usb0,bus=pci.0,addr=0x3 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.xml
new file mode 100644
index 0000000..1996d20
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.xml
@@ -0,0 +1,16 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219136</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0' model='piix3-uhci'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 6e8da5e..692a02b 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -484,6 +484,13 @@ mymain(void)
             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);
-- 
1.7.6




More information about the libvir-list mailing list