[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