[PATCH 2/3] conf: Parse/format XML input type 'linux'

Kristina Hanicova khanicov at redhat.com
Fri Apr 30 12:16:16 UTC 2021


Signed-off-by: Kristina Hanicova <khanicov at redhat.com>
---
 docs/formatdomain.rst                    | 30 +++++++-----
 docs/schemas/domaincommon.rng            | 20 ++++++++
 src/conf/domain_audit.c                  |  1 +
 src/conf/domain_conf.c                   | 61 ++++++++++++++++++++----
 src/conf/domain_conf.h                   | 12 +++++
 src/conf/domain_validate.c               |  8 ++++
 src/libvirt_private.syms                 |  2 +
 src/qemu/qemu_cgroup.c                   |  2 +
 src/qemu/qemu_command.c                  |  1 +
 src/qemu/qemu_domain_address.c           |  1 +
 src/qemu/qemu_hotplug.c                  |  1 +
 src/qemu/qemu_validate.c                 |  6 +++
 src/security/security_apparmor.c         |  1 +
 src/security/security_dac.c              |  2 +
 src/security/security_selinux.c          |  2 +
 src/security/virt-aa-helper.c            |  3 +-
 tests/qemuxml2argvdata/input-linux.xml   | 24 ++++++++++
 tests/qemuxml2xmloutdata/input-linux.xml |  1 +
 18 files changed, 157 insertions(+), 21 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/input-linux.xml
 create mode 120000 tests/qemuxml2xmloutdata/input-linux.xml

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 282176c4f4..337d07dbfb 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -5728,26 +5728,34 @@ to provide a graphics tablet for absolute cursor movement.
      <input type='passthrough' bus='virtio'>
        <source evdev='/dev/input/event1'/>
      </input>
+     <input type='linux'>
+       <source evdev='/dev/input/event1234' grab='all' repeat='on'/>
+     </input>
    </devices>
    ...
 
 ``input``
    The ``input`` element has one mandatory attribute, the ``type`` whose value
-   can be 'mouse', 'tablet', ( :since:`since 1.2.2` ) 'keyboard' or (
-   :since:`since 1.3.0` ) 'passthrough'. The tablet provides absolute cursor
-   movement, while the mouse uses relative movement. The optional ``bus``
-   attribute can be used to refine the exact device type. It takes values "xen"
-   (paravirtualized), "ps2" and "usb" or ( :since:`since 1.3.0` ) "virtio".
+   can be 'mouse', 'tablet', ( :since:`since 1.2.2` ) 'keyboard', (
+   :since:`since 1.3.0` ) 'passthrough' or ( :since:`since 7.4.0` ) 'linux'.
+   The tablet provides absolute cursor movement, while the mouse uses relative
+   movement. The optional ``bus`` attribute can be used to refine the exact
+   device type. It takes values "xen" (paravirtualized), "ps2" and "usb" or (
+   :since:`since 1.3.0` ) "virtio".
 
 The ``input`` element has an optional sub-element ``<address>`` which can tie
 the device to a particular PCI slot, `documented above <#elementsAddress>`__. On
 S390, ``address`` can be used to provide a CCW address for an input device (
-:since:`since 4.2.0` ). For type ``passthrough``, the mandatory sub-element
-``source`` must have an ``evdev`` attribute containing the absolute path to the
-event device passed through to guests. (KVM only) :since:`Since 5.2.0` , the
-``input`` element accepts a ``model`` attribute which has the values 'virtio',
-'virtio-transitional' and 'virtio-non-transitional'. See `Virtio transitional
-devices <#elementsVirtioTransitional>`__ for more details.
+:since:`since 4.2.0` ). For types ``passthrough`` and ``linux``, the mandatory
+sub-element ``source`` must have an ``evdev`` attribute containing the absolute
+path to the event device passed through to guests. For type ``linux``,
+``sorce`` can have two optional attributes ``grab`` with value 'all' which when
+enabled grabs all input devices instead of just one and ``repeat`` with value
+'on' to enable auto-repeat events ( :since:`Since 7.4.0` ) (KVM only)
+:since:`Since 5.2.0` , the ``input`` element accepts a ``model`` attribute
+which has the values 'virtio', 'virtio-transitional' and
+'virtio-non-transitional'. See `Virtio transitional devices
+<#elementsVirtioTransitional>`__ for more details.
 
 The subelement ``driver`` can be used to tune the virtio options of the device:
 `Virtio-specific options <#elementsVirtio>`__ can also be set. ( :since:`Since
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index a2e5c50c1d..80b1961b5e 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -5443,6 +5443,26 @@
               </attribute>
             </element>
           </group>
+          <group>
+            <attribute name="type">
+              <value>linux</value>
+            </attribute>
+            <element name="source">
+              <attribute name="evdev">
+                <ref name="absFilePath"/>
+              </attribute>
+              <optional>
+                <attribute name="grab">
+                  <value>all</value>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="repeat">
+                  <value>on</value>
+                </attribute>
+              </optional>
+            </element>
+          </group>
         </choice>
         <optional>
           <attribute name="model">
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index b1226fd5dc..ac8f59ec30 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -956,6 +956,7 @@ virDomainAuditInput(virDomainObj *vm,
         break;
 
     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
         VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
                   "virt=%s resrc=evdev reason=%s %s uuid=%s path=%s",
                   virt, reason, vmname, uuidstr, VIR_AUDIT_STR(input->source.evdev));
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9d98f487ea..5709f5506c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -864,6 +864,7 @@ VIR_ENUM_IMPL(virDomainInput,
               "tablet",
               "keyboard",
               "passthrough",
+              "linux",
 );
 
 VIR_ENUM_IMPL(virDomainInputBus,
@@ -873,6 +874,7 @@ VIR_ENUM_IMPL(virDomainInputBus,
               "xen",
               "parallels",
               "virtio",
+              "none",
 );
 
 VIR_ENUM_IMPL(virDomainInputModel,
@@ -883,6 +885,12 @@ VIR_ENUM_IMPL(virDomainInputModel,
               "virtio-non-transitional",
 );
 
+VIR_ENUM_IMPL(virDomainInputSourceGrab,
+              VIR_DOMAIN_INPUT_SOURCE_GRAB_LAST,
+              "default",
+              "all",
+);
+
 VIR_ENUM_IMPL(virDomainGraphics,
               VIR_DOMAIN_GRAPHICS_TYPE_LAST,
               "sdl",
@@ -1898,6 +1906,7 @@ const char *virDomainInputDefGetPath(virDomainInputDef *input)
         return NULL;
 
     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
         return input->source.evdev;
     }
     return NULL;
@@ -12136,10 +12145,10 @@ virDomainInputDefParseXML(virDomainXMLOption *xmlopt,
 {
     VIR_XPATH_NODE_AUTORESTORE(ctxt)
     virDomainInputDef *def;
-    g_autofree char *evdev = NULL;
     g_autofree char *type = NULL;
     g_autofree char *bus = NULL;
     g_autofree char *model = NULL;
+    xmlNodePtr source = NULL;
 
     def = g_new0(virDomainInputDef, 1);
 
@@ -12241,6 +12250,8 @@ virDomainInputDefParseXML(virDomainXMLOption *xmlopt,
             } else if (ARCH_IS_S390(dom->os.arch) ||
                        def->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH) {
                 def->bus = VIR_DOMAIN_INPUT_BUS_VIRTIO;
+            } else if (def->type == VIR_DOMAIN_INPUT_TYPE_LINUX) {
+                def->bus = VIR_DOMAIN_INPUT_BUS_NONE;
             } else {
                 def->bus = VIR_DOMAIN_INPUT_BUS_USB;
             }
@@ -12265,12 +12276,31 @@ virDomainInputDefParseXML(virDomainXMLOption *xmlopt,
         goto error;
     }
 
-    if ((evdev = virXPathString("string(./source/@evdev)", ctxt)))
-        def->source.evdev = virFileSanitizePath(evdev);
-    if (def->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH && !def->source.evdev) {
-        virReportError(VIR_ERR_XML_ERROR, "%s",
-                       _("Missing evdev path for input device passthrough"));
-        goto error;
+    if ((source = virXPathNode("./source", ctxt))) {
+        g_autofree char *evdev = virXMLPropString(source, "evdev");
+
+        if (evdev)
+            def->source.evdev = virFileSanitizePath(evdev);
+
+        if (def->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH ||
+            def->type == VIR_DOMAIN_INPUT_TYPE_LINUX) {
+            if (!def->source.evdev) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("Missing evdev path for input device"));
+                goto error;
+            }
+        }
+
+        if (def->type == VIR_DOMAIN_INPUT_TYPE_LINUX) {
+            if (virXMLPropEnum(source, "grab",
+                               virDomainInputSourceGrabTypeFromString,
+                               VIR_XML_PROP_NONZERO, &def->source.grab) < 0)
+                goto error;
+
+            if (virXMLPropTristateSwitch(source, "repeat",
+                                         VIR_XML_PROP_NONE, &def->source.repeat) < 0)
+                goto error;
+        }
     }
 
     if (virDomainVirtioOptionsParseXML(virXPathNode("./driver", ctxt),
@@ -26906,9 +26936,12 @@ virDomainInputDefFormat(virBuffer *buf,
 {
     const char *type = virDomainInputTypeToString(def->type);
     const char *bus = virDomainInputBusTypeToString(def->bus);
+    const char *grab = virDomainInputSourceGrabTypeToString(def->source.grab);
+    const char *repeat = virTristateSwitchTypeToString(def->source.repeat);
     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
     g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER;
+    g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER;
 
     /* don't format keyboard into migratable XML for backward compatibility */
     if (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE &&
@@ -26928,7 +26961,9 @@ virDomainInputDefFormat(virBuffer *buf,
         return -1;
     }
 
-    virBufferAsprintf(&attrBuf, " type='%s' bus='%s'", type, bus);
+    virBufferAsprintf(&attrBuf, " type='%s'", type);
+    if (def->bus != VIR_DOMAIN_INPUT_BUS_NONE)
+        virBufferAsprintf(&attrBuf, " bus='%s'", bus);
 
     if (def->model) {
         const char *model = virDomainInputModelTypeToString(def->model);
@@ -26946,7 +26981,15 @@ virDomainInputDefFormat(virBuffer *buf,
 
     virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL);
 
-    virBufferEscapeString(&childBuf, "<source evdev='%s'/>\n", def->source.evdev);
+    virBufferEscapeString(&sourceAttrBuf, " evdev='%s'", def->source.evdev);
+
+    if (def->source.grab)
+        virBufferAsprintf(&sourceAttrBuf, " grab='%s'", grab);
+    if (def->source.repeat)
+        virBufferAsprintf(&sourceAttrBuf, " repeat='%s'", repeat);
+
+    virXMLFormatElement(&childBuf, "source", &sourceAttrBuf, NULL);
+
     virDomainDeviceInfoFormat(&childBuf, &def->info, flags);
 
     virXMLFormatElement(buf, "input", &attrBuf, &childBuf);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 85c318d027..5107f0f3a1 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1388,6 +1388,7 @@ typedef enum {
     VIR_DOMAIN_INPUT_TYPE_TABLET,
     VIR_DOMAIN_INPUT_TYPE_KBD,
     VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH,
+    VIR_DOMAIN_INPUT_TYPE_LINUX,
 
     VIR_DOMAIN_INPUT_TYPE_LAST
 } virDomainInputType;
@@ -1398,6 +1399,7 @@ typedef enum {
     VIR_DOMAIN_INPUT_BUS_XEN,
     VIR_DOMAIN_INPUT_BUS_PARALLELS, /* pseudo device for VNC in containers */
     VIR_DOMAIN_INPUT_BUS_VIRTIO,
+    VIR_DOMAIN_INPUT_BUS_NONE,
 
     VIR_DOMAIN_INPUT_BUS_LAST
 } virDomainInputBus;
@@ -1411,12 +1413,21 @@ typedef enum {
     VIR_DOMAIN_INPUT_MODEL_LAST
 } virDomainInputModel;
 
+typedef enum {
+    VIR_DOMAIN_INPUT_SOURCE_GRAB_DEFAULT,
+    VIR_DOMAIN_INPUT_SOURCE_GRAB_ALL,
+
+    VIR_DOMAIN_INPUT_SOURCE_GRAB_LAST
+} virDomainInputSourceGrab;
+
 struct _virDomainInputDef {
     int type;
     int bus;
     int model; /* virDomainInputModel */
     struct {
         char *evdev;
+        virDomainInputSourceGrab grab;
+        virTristateSwitch repeat;
     } source;
     virDomainDeviceInfo info;
     virDomainVirtioOptions *virtio;
@@ -3843,6 +3854,7 @@ VIR_ENUM_DECL(virDomainRedirdevBus);
 VIR_ENUM_DECL(virDomainInput);
 VIR_ENUM_DECL(virDomainInputBus);
 VIR_ENUM_DECL(virDomainInputModel);
+VIR_ENUM_DECL(virDomainInputSourceGrab);
 VIR_ENUM_DECL(virDomainGraphics);
 VIR_ENUM_DECL(virDomainGraphicsListen);
 VIR_ENUM_DECL(virDomainGraphicsAuthConnected);
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 686b9e8d16..05286e91d6 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -1961,6 +1961,14 @@ virDomainInputDefValidate(const virDomainInputDef *input)
             }
             break;
 
+        case VIR_DOMAIN_INPUT_TYPE_LINUX:
+            if (input->bus != VIR_DOMAIN_INPUT_BUS_NONE) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("input linux doesn't support bus element"));
+                return -1;
+            }
+            break;
+
         case VIR_DOMAIN_INPUT_TYPE_LAST:
         default:
             virReportEnumRangeError(virDomainInputType, input->type);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9f761c2c00..044f95494e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -475,6 +475,8 @@ virDomainInputBusTypeToString;
 virDomainInputDefFind;
 virDomainInputDefFree;
 virDomainInputDefGetPath;
+virDomainInputSourceGrabTypeFromString;
+virDomainInputSourceGrabTypeToString;
 virDomainInputTypeToString;
 virDomainIOMMUModelTypeFromString;
 virDomainIOMMUModelTypeToString;
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 0e8835fb86..7845d74376 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -362,6 +362,7 @@ qemuSetupInputCgroup(virDomainObj *vm,
 
     switch (dev->type) {
     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
         VIR_DEBUG("Process path '%s' for input device", dev->source.evdev);
         ret = virCgroupAllowDevicePath(priv->cgroup, dev->source.evdev,
                                        VIR_CGROUP_DEVICE_RW, false);
@@ -385,6 +386,7 @@ qemuTeardownInputCgroup(virDomainObj *vm,
 
     switch (dev->type) {
     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
         VIR_DEBUG("Process path '%s' for input device", dev->source.evdev);
         ret = virCgroupDenyDevicePath(priv->cgroup, dev->source.evdev,
                                       VIR_CGROUP_DEVICE_RWM, false);
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d7f1c715b6..1ca330b840 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4018,6 +4018,7 @@ qemuBuildVirtioInputDevStr(const virDomainDef *def,
             return NULL;
         }
         break;
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
     case VIR_DOMAIN_INPUT_TYPE_LAST:
     default:
         virReportEnumRangeError(virDomainInputType, dev->type);
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index e66efb3d1f..5f76120943 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -973,6 +973,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev,
         case VIR_DOMAIN_INPUT_BUS_USB:
         case VIR_DOMAIN_INPUT_BUS_XEN:
         case VIR_DOMAIN_INPUT_BUS_PARALLELS:
+        case VIR_DOMAIN_INPUT_BUS_NONE:
         case VIR_DOMAIN_INPUT_BUS_LAST:
             return 0;
         }
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 4344edc75b..860a9deb40 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -5805,6 +5805,7 @@ qemuDomainDetachPrepInput(virDomainObj *vm,
     case VIR_DOMAIN_INPUT_BUS_LAST:
     case VIR_DOMAIN_INPUT_BUS_USB:
     case VIR_DOMAIN_INPUT_BUS_VIRTIO:
+    case VIR_DOMAIN_INPUT_BUS_NONE:
         break;
     }
 
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 774426bceb..5229dff1a7 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -4605,6 +4605,7 @@ qemuValidateDomainDeviceDefInput(const virDomainInputDef *input,
         case VIR_DOMAIN_INPUT_TYPE_MOUSE:
         case VIR_DOMAIN_INPUT_TYPE_TABLET:
         case VIR_DOMAIN_INPUT_TYPE_KBD:
+        case VIR_DOMAIN_INPUT_TYPE_LINUX:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("virtio (non-)transitional models are not "
                              "supported for input type=%s"),
@@ -4650,6 +4651,11 @@ qemuValidateDomainDeviceDefInput(const virDomainInputDef *input,
         cap = QEMU_CAPS_VIRTIO_INPUT_HOST;
         ccwCap = QEMU_CAPS_LAST;
         break;
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
+        baseName = "input-linux";
+        cap = QEMU_CAPS_INPUT_LINUX;
+        ccwCap = QEMU_CAPS_LAST;
+        break;
     case VIR_DOMAIN_INPUT_TYPE_LAST:
     default:
         virReportEnumRangeError(virDomainInputType,
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index a2a8435fe4..80176837ce 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -720,6 +720,7 @@ AppArmorSetInputLabel(virSecurityManager *mgr,
 
     switch ((virDomainInputType)input->type) {
     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
         if (input->source.evdev == NULL) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("%s: passthrough input device has no source"),
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index e973964735..8e82c7f78d 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1815,6 +1815,7 @@ virSecurityDACSetInputLabel(virSecurityManager *mgr,
 
     switch ((virDomainInputType)input->type) {
     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
         if (virSecurityDACGetIds(seclabel, priv, &user, &group, NULL, NULL) < 0)
             return -1;
 
@@ -1843,6 +1844,7 @@ virSecurityDACRestoreInputLabel(virSecurityManager *mgr,
 
     switch ((virDomainInputType)input->type) {
     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
         ret = virSecurityDACRestoreFileLabel(mgr, input->source.evdev);
         break;
 
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 29628d8953..42de0d5a98 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -1513,6 +1513,7 @@ virSecuritySELinuxSetInputLabel(virSecurityManager *mgr,
 
     switch ((virDomainInputType)input->type) {
     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
         if (virSecuritySELinuxSetFilecon(mgr, input->source.evdev,
                                          seclabel->imagelabel, true) < 0)
             return -1;
@@ -1543,6 +1544,7 @@ virSecuritySELinuxRestoreInputLabel(virSecurityManager *mgr,
 
     switch ((virDomainInputType)input->type) {
     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_INPUT_TYPE_LINUX:
         rc = virSecuritySELinuxRestoreFileLabel(mgr, input->source.evdev, true);
         break;
 
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 2331cc6648..aa1e2cdacc 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -1149,7 +1149,8 @@ get_files(vahControl * ctl)
 
     for (i = 0; i < ctl->def->ninputs; i++) {
         if (ctl->def->inputs[i] &&
-                ctl->def->inputs[i]->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH) {
+                ctl->def->inputs[i]->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH ||
+                ctl->def->inputs[i]->type == VIR_DOMAIN_INPUT_TYPE_LINUX) {
             if (vah_add_file(&buf, ctl->def->inputs[i]->source.evdev, "rw") != 0)
                 goto cleanup;
         }
diff --git a/tests/qemuxml2argvdata/input-linux.xml b/tests/qemuxml2argvdata/input-linux.xml
new file mode 100644
index 0000000000..053557c19e
--- /dev/null
+++ b/tests/qemuxml2argvdata/input-linux.xml
@@ -0,0 +1,24 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>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-system-i386</emulator>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='linux'>
+      <source evdev='/dev/input/event1234' grab='all' repeat='on'/>
+    </input>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/input-linux.xml b/tests/qemuxml2xmloutdata/input-linux.xml
new file mode 120000
index 0000000000..84e1e79b51
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/input-linux.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/input-linux.xml
\ No newline at end of file
-- 
2.30.2




More information about the libvir-list mailing list