[libvirt] [RFC 06/12] Add USB companion controllers support

Marc-André Lureau marcandre.lureau at gmail.com
Sun Aug 21 19:01:17 UTC 2011


Companion controllers take an extra 'master' attribute to associate
them.
---
 docs/formatdomain.html.in                          |   20 +++++++++
 docs/schemas/domain.rng                            |   15 +++++++
 src/conf/domain_conf.c                             |   44 ++++++++++++++++++++
 src/conf/domain_conf.h                             |   18 ++++++++
 src/qemu/qemu_command.c                            |    7 +++
 .../qemuxml2argv-usb-ich9-companion.args           |    6 +++
 .../qemuxml2argv-usb-ich9-companion.xml            |   30 +++++++++++++
 tests/qemuxml2argvtest.c                           |    5 ++
 8 files changed, 145 insertions(+), 0 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 0a383f6..5c232fa 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1243,6 +1243,26 @@
       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.
+    </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='1' model='ich9-uhci1'>
+      <master bus='0' 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 cc0bbca..6a2e71a 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -922,6 +922,9 @@
         </attribute>
       </optional>
       <optional>
+        <ref name="usbmaster"/>
+      </optional>
+      <optional>
         <ref name="address"/>
       </optional>
     </element>
@@ -2377,6 +2380,18 @@
     </element>
   </define>
 
+  <define name="usbmaster">
+    <element name="master">
+      <attribute name="bus">
+        <ref name="usbAddr"/>
+      </attribute>
+      <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 00345a3..837e657 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1829,6 +1829,40 @@ cleanup:
     return ret;
 }
 
+static int
+virDomainDeviceUSBMasterParseXML(xmlNodePtr node,
+                                 virDomainDeviceUSBMasterPtr master)
+{
+    char *bus, *startport;
+    int ret = -1;
+
+    memset(master, 0, sizeof(*master));
+
+    bus = virXMLPropString(node, "bus");
+    startport = virXMLPropString(node, "startport");
+
+    if (bus &&
+        virStrToLong_ui(bus, NULL, 10, &master->bus) < 0) {
+        virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                             _("Cannot parse <master> 'bus' attribute"));
+        goto cleanup;
+    }
+
+    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(bus);
+    VIR_FREE(startport);
+    return ret;
+}
+
 /* Parse the XML definition for a device address
  * @param node XML nodeset to parse for device address definition
  */
@@ -1839,6 +1873,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
 {
     xmlNodePtr cur;
     xmlNodePtr address = NULL;
+    xmlNodePtr master = NULL;
     xmlNodePtr alias = NULL;
     char *type = NULL;
     int ret = -1;
@@ -1855,6 +1890,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;
@@ -1863,6 +1901,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 f231725..0f51d47 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 280b7ae..8deae23 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1754,6 +1754,13 @@ qemuBuildUSBControllerDevStr(virDomainControllerDefPtr def,
     }
 
     virBufferAsprintf(buf, "%s,id=usb%d", smodel, def->idx);
+
+    if (def->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
+        virBufferAsprintf(buf, ",masterbus=usb%d.0,firstport=%d",
+                          def->info.master.usb.bus, def->info.master.usb.startport);
+    }
+
+
     return 0;
 }
 
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
new file mode 100644
index 0000000..d5a2e08
--- /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,id=usb1,masterbus=usb0.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4.0x0 \
+-device ich9-usb-uhci2,id=usb2,masterbus=usb0.0,firstport=2,bus=pci.0,multifunction=on,addr=0x4.0x1 \
+-device ich9-usb-uhci3,id=usb3,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..fe02514
--- /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='1' model='ich9-uhci1'>
+      <master bus='0' startport='0'/>
+      <address type='pci' domain='0' bus='0' slot='4' function='0'/>
+    </controller>
+    <controller type='usb' index='2' model='ich9-uhci2'>
+      <master bus='0' startport='2'/>
+      <address type='pci' domain='0' bus='0' slot='4' function='1'/>
+    </controller>
+    <controller type='usb' index='3' model='ich9-uhci3'>
+      <master bus='0' 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..c938034 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -495,6 +495,11 @@ 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,
+            QEMU_CAPS_ICH9_USB_UHCI1, QEMU_CAPS_ICH9_USB_UHCI2,
+            QEMU_CAPS_ICH9_USB_UHCI3);
 
     DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);
 
-- 
1.7.6




More information about the libvir-list mailing list