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