[libvirt] [v2 07/13] Add USB companion controllers support

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


Companion controllers take an extra 'master' attribute to associate
them.

Changes since v1:
- use the same bus index for companion controllers
- removed the master bus attribute, redundant with controller index
---
 docs/formatdomain.html.in                          |   22 ++++++++++++
 docs/schemas/domain.rng                            |   12 +++++++
 src/conf/domain_conf.c                             |   35 ++++++++++++++++++++
 src/conf/domain_conf.h                             |   18 ++++++++++
 src/qemu/qemu_command.c                            |   11 ++++++-
 .../qemuxml2argv-input-usbmouse-addr.args          |    2 +-
 .../qemuxml2argv-usb-ich9-companion.args           |    6 +++
 .../qemuxml2argv-usb-ich9-companion.xml            |   30 +++++++++++++++++
 tests/qemuxml2argvtest.c                           |    3 ++
 9 files changed, 137 insertions(+), 2 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 5552fbc..633cea1 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1243,6 +1243,28 @@
       sub-element.
     </p>
 
+    <p>
+      USB companion controllers have an optional
+      sub-element <code><master></code> to specify the exact
+      relationship of the companion to its master controller.
+      A companion controller is on the same bus as its master, so
+      the companion <code>index</code> value should be equal.
+    </p>
+
+<pre>
+  ...
+  <devices>
+    <controller type='usb' index='0' model='ich9-ehci1'>
+      <address type='pci' domain='0' bus='0' slot='4' function='7'/>
+    </controller>
+    <controller type='usb' index='0' model='ich9-uhci1'>
+      <master startport='0'/>
+      <address type='pci' domain='0' bus='0' slot='4' function='0'/>
+    </controller>
+    ...
+  </devices>
+  ...</pre>
+
     <h4><a name="elementsLease">Device leases</a></h4>
 
     <p>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 632e029..455f57d 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -923,6 +923,9 @@
         </attribute>
       </optional>
       <optional>
+        <ref name="usbmaster"/>
+      </optional>
+      <optional>
         <ref name="address"/>
       </optional>
     </element>
@@ -2378,6 +2381,15 @@
     </element>
   </define>
 
+  <define name="usbmaster">
+    <element name="master">
+      <attribute name="startport">
+        <ref name="usbAddr"/>
+      </attribute>
+      <empty/>
+    </element>
+  </define>
+
   <define name="filterref-node-attributes">
     <attribute name="filter">
       <data type="NCName"/>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5487e0e..5ef062a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1832,6 +1832,31 @@ cleanup:
     return ret;
 }
 
+static int
+virDomainDeviceUSBMasterParseXML(xmlNodePtr node,
+                                 virDomainDeviceUSBMasterPtr master)
+{
+    char *startport;
+    int ret = -1;
+
+    memset(master, 0, sizeof(*master));
+
+    startport = virXMLPropString(node, "startport");
+
+    if (startport &&
+        virStrToLong_ui(startport, NULL, 10, &master->startport) < 0) {
+        virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                             _("Cannot parse <master> 'startport' attribute"));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(startport);
+    return ret;
+}
+
 /* Parse the XML definition for a device address
  * @param node XML nodeset to parse for device address definition
  */
@@ -1842,6 +1867,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
 {
     xmlNodePtr cur;
     xmlNodePtr address = NULL;
+    xmlNodePtr master = NULL;
     xmlNodePtr alias = NULL;
     char *type = NULL;
     int ret = -1;
@@ -1858,6 +1884,9 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
             } else if (address == NULL &&
                        xmlStrEqual(cur->name, BAD_CAST "address")) {
                 address = cur;
+            } else if (master == NULL &&
+                       xmlStrEqual(cur->name, BAD_CAST "master")) {
+                master = cur;
             }
         }
         cur = cur->next;
@@ -1866,6 +1895,12 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
     if (alias)
         info->alias = virXMLPropString(alias, "name");
 
+    if (master) {
+        info->mastertype = VIR_DOMAIN_CONTROLLER_MASTER_USB;
+        if (virDomainDeviceUSBMasterParseXML(master, &info->master.usb) < 0)
+            goto cleanup;
+    }
+
     if (!address)
         return 0;
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1ad8071..07d60a4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -113,6 +113,20 @@ struct _virDomainDeviceUSBAddress {
     unsigned int port;
 };
 
+enum virDomainControllerMaster {
+    VIR_DOMAIN_CONTROLLER_MASTER_NONE,
+    VIR_DOMAIN_CONTROLLER_MASTER_USB,
+
+    VIR_DOMAIN_CONTROLLER_MASTER_LAST
+};
+
+typedef struct _virDomainDeviceUSBMaster virDomainDeviceUSBMaster;
+typedef virDomainDeviceUSBMaster *virDomainDeviceUSBMasterPtr;
+struct _virDomainDeviceUSBMaster {
+    unsigned int bus;
+    unsigned int startport;
+};
+
 typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
 typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
 struct _virDomainDeviceInfo {
@@ -125,6 +139,10 @@ struct _virDomainDeviceInfo {
         virDomainDeviceCcidAddress ccid;
         virDomainDeviceUSBAddress usb;
     } addr;
+    int mastertype;
+    union {
+        virDomainDeviceUSBMaster usb;
+    } master;
 };
 
 typedef struct _virDomainLeaseDef virDomainLeaseDef;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 91d8124..835d06f 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1758,7 +1758,16 @@ qemuBuildUSBControllerDevStr(virDomainControllerDefPtr def,
         return -1;
     }
 
-    virBufferAsprintf(buf, "%s,id=usb%d", smodel, def->idx);
+    virBufferAsprintf(buf, "%s", smodel);
+
+    if (def->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
+        virBufferAsprintf(buf, ",masterbus=usb%d.0", def->idx);
+        virBufferAsprintf(buf, ",firstport=%d", def->info.master.usb.startport);
+    } else {
+        virBufferAsprintf(buf, ",id=usb%d", def->idx);
+    }
+
+
     return 0;
 }
 
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.args b/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.args
index b6dc0d3..d784960 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.args
@@ -1 +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 -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -usb -device usb-mouse,id=input0,bus=usb.0,port=4 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
+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 -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -usb -device usb-mouse,id=input0,bus=usb0.0,port=4 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
new file mode 100644
index 0000000..b37dbf6
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
@@ -0,0 +1,6 @@
+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 ich9-usb-ehci1,id=usb0,bus=pci.0,multifunction=on,addr=0x4.0x7 \
+-device ich9-usb-uhci1,masterbus=usb0.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4.0x0 \
+-device ich9-usb-uhci2,masterbus=usb0.0,firstport=2,bus=pci.0,multifunction=on,addr=0x4.0x1 \
+-device ich9-usb-uhci3,masterbus=usb0.0,firstport=4,bus=pci.0,multifunction=on,addr=0x4.0x2 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
new file mode 100644
index 0000000..05a6adf
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
@@ -0,0 +1,30 @@
+<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='ich9-ehci1'>
+      <address type='pci' domain='0' bus='0' slot='4' function='7'/>
+    </controller>
+    <controller type='usb' index='0' model='ich9-uhci1'>
+      <master startport='0'/>
+      <address type='pci' domain='0' bus='0' slot='4' function='0'/>
+    </controller>
+    <controller type='usb' index='0' model='ich9-uhci2'>
+      <master startport='2'/>
+      <address type='pci' domain='0' bus='0' slot='4' function='1'/>
+    </controller>
+    <controller type='usb' index='0' model='ich9-uhci3'>
+      <master startport='4'/>
+      <address type='pci' domain='0' bus='0' slot='4' function='2'/>
+    </controller>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index b573380..33588d0 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -495,6 +495,9 @@ mymain(void)
             QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
     DO_TEST("input-usbmouse-addr", false,
             QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
+    DO_TEST("usb-ich9-companion", false,
+            QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
+            QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
 
     DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);
 
-- 
1.7.6




More information about the libvir-list mailing list