[libvirt] [v2 06/13] USB devices gain a new USB address child element
Daniel P. Berrange
berrange at redhat.com
Thu Sep 1 10:57:03 UTC 2011
On Fri, Aug 26, 2011 at 01:44:22AM +0300, Marc-André Lureau wrote:
> ---
> docs/schemas/domain.rng | 14 +++++
> src/conf/domain_conf.c | 62 +++++++++++++++++++-
> src/conf/domain_conf.h | 10 +++
> src/qemu/qemu_command.c | 40 ++++++++++---
> src/qemu/qemu_command.h | 6 +-
> src/qemu/qemu_hotplug.c | 2 +-
> .../qemuxml2argv-input-usbmouse-addr.args | 1 +
> .../qemuxml2argv-input-usbmouse-addr.xml | 27 +++++++++
> tests/qemuxml2argvtest.c | 2 +
> 9 files changed, 149 insertions(+), 15 deletions(-)
> create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.args
> create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.xml
>
> diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
> index 82a4339..632e029 100644
> --- a/docs/schemas/domain.rng
> +++ b/docs/schemas/domain.rng
> @@ -2029,6 +2029,14 @@
> </attribute>
> </element>
> </define>
> + <define name="usbportaddress">
> + <attribute name="bus">
> + <ref name="usbAddr"/>
> + </attribute>
> + <attribute name="port">
> + <ref name="usbAddr"/>
> + </attribute>
> + </define>
> <define name="pciaddress">
> <optional>
> <attribute name="domain">
> @@ -2360,6 +2368,12 @@
> </attribute>
> <ref name="ccidaddress"/>
> </group>
> + <group>
> + <attribute name="type">
> + <value>usb</value>
> + </attribute>
> + <ref name="usbportaddress"/>
> + </group>
> </choice>
> </element>
> </define>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 10bc130..5487e0e 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -133,7 +133,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
> "pci",
> "drive",
> "virtio-serial",
> - "ccid")
> + "ccid",
> + "usb")
>
> VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
> "block",
> @@ -1398,6 +1399,9 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
>
> case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
> return virDomainDeviceDriveAddressIsValid(&info->addr.drive);
> +
> + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
> + return virDomainDeviceUSBAddressIsValid(&info->addr.usb);
> }
>
> return 0;
> @@ -1419,6 +1423,13 @@ int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr ATTRI
> return 1; /* 0 is valid for all fields, so any successfully parsed addr is valid */
> }
>
> +int virDomainDeviceUSBAddressIsValid(virDomainDeviceUSBAddressPtr addr)
> +{
> + if (addr->port >= 128) /* FIXME: is this correct */
> + return 0;
> +
> + return 1;
> +}
>
> int virDomainDeviceVirtioSerialAddressIsValid(
> virDomainDeviceVirtioSerialAddressPtr addr ATTRIBUTE_UNUSED)
> @@ -1787,6 +1798,40 @@ cleanup:
> return ret;
> }
>
> +static int
> +virDomainDeviceUSBAddressParseXML(xmlNodePtr node,
> + virDomainDeviceUSBAddressPtr addr)
> +{
> + char *port, *bus;
> + int ret = -1;
> +
> + memset(addr, 0, sizeof(*addr));
> +
> + port = virXMLPropString(node, "port");
> + bus = virXMLPropString(node, "bus");
> +
> + if (port &&
> + virStrToLong_ui(port, NULL, 10, &addr->port) < 0) {
> + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Cannot parse <address> 'port' attribute"));
> + goto cleanup;
> + }
> +
> + if (bus &&
> + virStrToLong_ui(bus, NULL, 10, &addr->bus) < 0) {
> + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Cannot parse <address> 'bus' attribute"));
> + goto cleanup;
> + }
> +
> + ret = 0;
> +
> +cleanup:
> + VIR_FREE(bus);
> + VIR_FREE(port);
> + return ret;
> +}
> +
> /* Parse the XML definition for a device address
> * @param node XML nodeset to parse for device address definition
> */
> @@ -1860,6 +1905,11 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
> goto cleanup;
> break;
>
> + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
> + if (virDomainDeviceUSBAddressParseXML(address, &info->addr.usb) < 0)
> + goto cleanup;
> + break;
> +
> default:
> /* Should not happen */
> virDomainReportError(VIR_ERR_INTERNAL_ERROR,
> @@ -3806,7 +3856,7 @@ error:
> goto cleanup;
> }
>
> -/* Parse the XML definition for a network interface */
> +/* Parse the XML definition for an input device */
> static virDomainInputDefPtr
> virDomainInputDefParseXML(const char *ostype,
> xmlNodePtr node,
> @@ -3884,6 +3934,14 @@ virDomainInputDefParseXML(const char *ostype,
> if (virDomainDeviceInfoParseXML(node, &def->info, flags) < 0)
> goto error;
>
> + if (def->bus == VIR_DOMAIN_INPUT_BUS_USB &&
> + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
> + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
> + virDomainReportError(VIR_ERR_XML_ERROR, "%s",
> + _("Invalid address for a USB device"));
> + goto error;
> + }
> +
> cleanup:
> VIR_FREE(type);
> VIR_FREE(bus);
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 0f5e974..1ad8071 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -69,6 +69,7 @@ enum virDomainDeviceAddressType {
> VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE,
> VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL,
> VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID,
> + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB,
>
> VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST
> };
> @@ -105,6 +106,13 @@ struct _virDomainDeviceCcidAddress {
> unsigned int slot;
> };
>
> +typedef struct _virDomainDeviceUSBAddress virDomainDeviceUSBAddress;
> +typedef virDomainDeviceUSBAddress *virDomainDeviceUSBAddressPtr;
> +struct _virDomainDeviceUSBAddress {
> + unsigned int bus;
> + unsigned int port;
> +};
> +
> typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
> typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
> struct _virDomainDeviceInfo {
> @@ -115,6 +123,7 @@ struct _virDomainDeviceInfo {
> virDomainDeviceDriveAddress drive;
> virDomainDeviceVirtioSerialAddress vioserial;
> virDomainDeviceCcidAddress ccid;
> + virDomainDeviceUSBAddress usb;
> } addr;
> };
>
> @@ -1437,6 +1446,7 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
> int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr);
> int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr);
> int virDomainDeviceVirtioSerialAddressIsValid(virDomainDeviceVirtioSerialAddressPtr addr);
> +int virDomainDeviceUSBAddressIsValid(virDomainDeviceUSBAddressPtr addr);
> void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
> void virDomainDefClearPCIAddresses(virDomainDefPtr def);
> void virDomainDefClearDeviceAliases(virDomainDefPtr def);
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 2f32e37..91d8124 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -1327,7 +1327,11 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
> info->addr.pci.slot, info->addr.pci.function);
> else
> virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot);
> + } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
> + virBufferAsprintf(buf, ",bus=usb%d.0", info->addr.usb.bus);
> + virBufferAsprintf(buf, ",port=%d", info->addr.usb.port);
> }
> +
> return 0;
> }
>
> @@ -2089,7 +2093,8 @@ error:
>
>
> char *
> -qemuBuildUSBInputDevStr(virDomainInputDefPtr dev)
> +qemuBuildUSBInputDevStr(virDomainInputDefPtr dev,
> + virBitmapPtr qemuCaps)
> {
> virBuffer buf = VIR_BUFFER_INITIALIZER;
>
> @@ -2097,6 +2102,9 @@ qemuBuildUSBInputDevStr(virDomainInputDefPtr dev)
> dev->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
> "usb-mouse" : "usb-tablet", dev->info.alias);
>
> + if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
> + goto error;
> +
> if (virBufferError(&buf)) {
> virReportOOMError();
> goto error;
> @@ -2285,9 +2293,10 @@ qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev)
>
>
> char *
> -qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev)
> +qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev,
> + virBitmapPtr qemuCaps)
> {
> - char *ret = NULL;
> + virBuffer buf = VIR_BUFFER_INITIALIZER;
>
> if (!dev->source.subsys.u.usb.bus &&
> !dev->source.subsys.u.usb.device) {
> @@ -2296,13 +2305,24 @@ qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev)
> return NULL;
> }
>
> - if (virAsprintf(&ret, "usb-host,hostbus=%d,hostaddr=%d,id=%s",
> - dev->source.subsys.u.usb.bus,
> - dev->source.subsys.u.usb.device,
> - dev->info.alias) < 0)
> + virBufferAsprintf(&buf, "usb-host,hostbus=%d,hostaddr=%d,id=%s",
> + dev->source.subsys.u.usb.bus,
> + dev->source.subsys.u.usb.device,
> + dev->info.alias);
> +
> + if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
> + goto error;
> +
> + if (virBufferError(&buf)) {
> virReportOOMError();
> + goto error;
> + }
>
> - return ret;
> + return virBufferContentAndReset(&buf);
> +
> +error:
> + virBufferFreeAndReset(&buf);
> + return NULL;
> }
>
>
> @@ -4223,7 +4243,7 @@ qemuBuildCommandLine(virConnectPtr conn,
> if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
> char *optstr;
> virCommandAddArg(cmd, "-device");
> - if (!(optstr = qemuBuildUSBInputDevStr(input)))
> + if (!(optstr = qemuBuildUSBInputDevStr(input, qemuCaps)))
> goto error;
> virCommandAddArg(cmd, optstr);
> VIR_FREE(optstr);
> @@ -4741,7 +4761,7 @@ qemuBuildCommandLine(virConnectPtr conn,
>
> if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
> virCommandAddArg(cmd, "-device");
> - if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev)))
> + if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev, qemuCaps)))
> goto error;
> virCommandAddArg(cmd, devstr);
> VIR_FREE(devstr);
> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
> index 099d683..de09577 100644
> --- a/src/qemu/qemu_command.h
> +++ b/src/qemu/qemu_command.h
> @@ -98,7 +98,8 @@ char * qemuBuildWatchdogDevStr(virDomainWatchdogDefPtr dev,
> char * qemuBuildMemballoonDevStr(virDomainMemballoonDefPtr dev,
> virBitmapPtr qemuCaps);
>
> -char * qemuBuildUSBInputDevStr(virDomainInputDefPtr dev);
> +char * qemuBuildUSBInputDevStr(virDomainInputDefPtr dev,
> + virBitmapPtr qemuCaps);
>
> char * qemuBuildSoundDevStr(virDomainSoundDefPtr sound,
> virBitmapPtr qemuCaps);
> @@ -115,7 +116,8 @@ int qemuOpenPCIConfig(virDomainHostdevDefPtr dev);
> /* Legacy, pre device support */
> char * qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev);
> /* Current, best practice */
> -char * qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev);
> +char * qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev,
> + virBitmapPtr qemuCaps);
>
>
>
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index b2da6d0..60cd241 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -922,7 +922,7 @@ int qemuDomainAttachHostUsbDevice(struct qemud_driver *driver,
> if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
> if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
> goto error;
> - if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev)))
> + if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev, priv->qemuCaps)))
> goto error;
> }
>
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.args b/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.args
> new file mode 100644
> index 0000000..b6dc0d3
> --- /dev/null
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.args
> @@ -0,0 +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
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.xml b/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.xml
> new file mode 100644
> index 0000000..a2fa8e3
> --- /dev/null
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-input-usbmouse-addr.xml
> @@ -0,0 +1,27 @@
> +<domain type='qemu'>
> + <name>QEMUGuest1</name>
> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
> + <memory>219136</memory>
> + <currentMemory>219136</currentMemory>
> + <vcpu>1</vcpu>
> + <os>
> + <type arch='i686' machine='pc'>hvm</type>
> + <boot dev='hd'/>
> + </os>
> + <clock offset='utc'/>
> + <on_poweroff>destroy</on_poweroff>
> + <on_reboot>restart</on_reboot>
> + <on_crash>destroy</on_crash>
> + <devices>
> + <emulator>/usr/bin/qemu</emulator>
> + <disk type='block' device='disk'>
> + <source dev='/dev/HostVG/QEMUGuest1'/>
> + <target dev='hda' bus='ide'/>
> + <address type='drive' controller='0' bus='0' unit='0'/>
> + </disk>
> + <controller type='ide' index='0'/>
> + <input type='mouse' bus='usb'>
> + <address type='usb' bus='0' port='4'/>
> + </input>
> + </devices>
> +</domain>
> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
> index f3abc24..b573380 100644
> --- a/tests/qemuxml2argvtest.c
> +++ b/tests/qemuxml2argvtest.c
> @@ -493,6 +493,8 @@ mymain(void)
> DO_TEST("usb-ich9-ehci-addr", false,
> QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
> QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
> + DO_TEST("input-usbmouse-addr", false,
> + QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
>
> DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);
>
ACK
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list