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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list