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>
</choice>
</attribute>
</optional>
+ <optional>
+ <ref name="usbmaster"/>
+ </optional>
<optional>
<ref name="address"/>
</optional>
</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"/>
virBufferAsprintf(buf, " <alias name='%s'/>\n", info->alias);
}
+ if (info->mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
+ virBufferAsprintf(buf, " <master startport='%d'/>\n",
+ info->master.usb.startport);
+ }
+
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
return 0;
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
*/
{
xmlNodePtr cur;
xmlNodePtr address = NULL;
+ xmlNodePtr master = NULL;
xmlNodePtr alias = NULL;
char *type = NULL;
int ret = -1;
} 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;
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;
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 startport;
+};
+
typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
struct _virDomainDeviceInfo {
virDomainDeviceCcidAddress ccid;
virDomainDeviceUSBAddress usb;
} addr;
+ int mastertype;
+ union {
+ virDomainDeviceUSBMaster usb;
+ } master;
};
typedef struct _virDomainLeaseDef virDomainLeaseDef;
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;
}
--- /dev/null
+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
--- /dev/null
+<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>
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);