[Qemu-devel] [PATCH] virtio-input: send rel-wheel events for wheel buttons

Gerd Hoffmann posted 1 patch 6 years, 7 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20170823135113.25769-1-kraxel@redhat.com
Test FreeBSD passed
Test checkpatch passed
Test docker passed
Test s390x passed
There is a newer version of this series
include/hw/virtio/virtio-input.h |   1 +
hw/input/virtio-input-hid.c      | 119 +++++++++++++++++++++++++++++++++++++--
2 files changed, 115 insertions(+), 5 deletions(-)
[Qemu-devel] [PATCH] virtio-input: send rel-wheel events for wheel buttons
Posted by Gerd Hoffmann 6 years, 7 months ago
qemu uses wheel-up/down button events for mouse wheel input, however
linux applications typically want REL_WHEEL events.

This fixes wheel with linux guests. Tested with X11/wayland, and
windows virtio-input driver.

Based on a patch from Marc.
Added property to enable/disable wheel axis.
TODO: add compat properties for old machine types.

Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/hw/virtio/virtio-input.h |   1 +
 hw/input/virtio-input-hid.c      | 119 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h
index 91df57eca4..054c38836f 100644
--- a/include/hw/virtio/virtio-input.h
+++ b/include/hw/virtio/virtio-input.h
@@ -89,6 +89,7 @@ struct VirtIOInputHID {
     QemuInputHandler                  *handler;
     QemuInputHandlerState             *hs;
     int                               ledstate;
+    bool                              wheel_axis;
 };
 
 struct VirtIOInputHost {
diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index 46c038110c..79ab92e89f 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -190,6 +190,7 @@ static void virtio_input_key_config(VirtIOInput *vinput,
 static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
                                       InputEvent *evt)
 {
+    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
     VirtIOInput *vinput = VIRTIO_INPUT(dev);
     virtio_input_event event;
     int qcode;
@@ -215,7 +216,14 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
         break;
     case INPUT_EVENT_KIND_BTN:
         btn = evt->u.btn.data;
-        if (keymap_button[btn->button]) {
+        if (vhid->wheel_axis && (btn->button == INPUT_BUTTON_WHEEL_UP ||
+                                 btn->button == INPUT_BUTTON_WHEEL_DOWN)) {
+            event.type  = cpu_to_le16(EV_REL);
+            event.code  = cpu_to_le16(REL_WHEEL);
+            event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP
+                                      ? 1 : -1);
+            virtio_input_send(vinput, &event);
+        } else if (keymap_button[btn->button]) {
             event.type  = cpu_to_le16(EV_KEY);
             event.code  = cpu_to_le16(keymap_button[btn->button]);
             event.value = cpu_to_le32(btn->down ? 1 : 0);
@@ -407,7 +415,7 @@ static QemuInputHandler virtio_mouse_handler = {
     .sync  = virtio_input_handle_sync,
 };
 
-static struct virtio_input_config virtio_mouse_config[] = {
+static struct virtio_input_config virtio_mouse_config_v1[] = {
     {
         .select    = VIRTIO_INPUT_CFG_ID_NAME,
         .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
@@ -432,13 +440,53 @@ static struct virtio_input_config virtio_mouse_config[] = {
     { /* end of list */ },
 };
 
+static struct virtio_input_config virtio_mouse_config_v2[] = {
+    {
+        .select    = VIRTIO_INPUT_CFG_ID_NAME,
+        .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
+        .u.string  = VIRTIO_ID_NAME_MOUSE,
+    },{
+        .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
+        .size      = sizeof(struct virtio_input_devids),
+        .u.ids     = {
+            .bustype = const_le16(BUS_VIRTUAL),
+            .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
+            .product = const_le16(0x0002),
+            .version = const_le16(0x0002),
+        },
+    },{
+        .select    = VIRTIO_INPUT_CFG_EV_BITS,
+        .subsel    = EV_REL,
+        .size      = 2,
+        .u.bitmap  = {
+            (1 << REL_X) | (1 << REL_Y),
+            (1 << (REL_WHEEL - 8))
+        },
+    },
+    { /* end of list */ },
+};
+
+static Property virtio_mouse_properties[] = {
+    DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_mouse_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props  = virtio_mouse_properties;
+}
+
 static void virtio_mouse_init(Object *obj)
 {
     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
     VirtIOInput *vinput = VIRTIO_INPUT(obj);
 
     vhid->handler = &virtio_mouse_handler;
-    virtio_input_init_config(vinput, virtio_mouse_config);
+    virtio_input_init_config(vinput, vhid->wheel_axis
+                             ? virtio_mouse_config_v2
+                             : virtio_mouse_config_v1);
     virtio_input_key_config(vinput, keymap_button,
                             ARRAY_SIZE(keymap_button));
 }
@@ -448,6 +496,7 @@ static const TypeInfo virtio_mouse_info = {
     .parent        = TYPE_VIRTIO_INPUT_HID,
     .instance_size = sizeof(VirtIOInputHID),
     .instance_init = virtio_mouse_init,
+    .class_init    = virtio_mouse_class_init,
 };
 
 /* ----------------------------------------------------------------- */
@@ -459,7 +508,7 @@ static QemuInputHandler virtio_tablet_handler = {
     .sync  = virtio_input_handle_sync,
 };
 
-static struct virtio_input_config virtio_tablet_config[] = {
+static struct virtio_input_config virtio_tablet_config_v1[] = {
     {
         .select    = VIRTIO_INPUT_CFG_ID_NAME,
         .size      = sizeof(VIRTIO_ID_NAME_TABLET),
@@ -496,13 +545,72 @@ static struct virtio_input_config virtio_tablet_config[] = {
     { /* end of list */ },
 };
 
+static struct virtio_input_config virtio_tablet_config_v2[] = {
+    {
+        .select    = VIRTIO_INPUT_CFG_ID_NAME,
+        .size      = sizeof(VIRTIO_ID_NAME_TABLET),
+        .u.string  = VIRTIO_ID_NAME_TABLET,
+    },{
+        .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
+        .size      = sizeof(struct virtio_input_devids),
+        .u.ids     = {
+            .bustype = const_le16(BUS_VIRTUAL),
+            .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
+            .product = const_le16(0x0003),
+            .version = const_le16(0x0002),
+        },
+    },{
+        .select    = VIRTIO_INPUT_CFG_EV_BITS,
+        .subsel    = EV_ABS,
+        .size      = 1,
+        .u.bitmap  = {
+            (1 << ABS_X) | (1 << ABS_Y),
+        },
+    },{
+        .select    = VIRTIO_INPUT_CFG_EV_BITS,
+        .subsel    = EV_REL,
+        .size      = 2,
+        .u.bitmap  = {
+            0,
+            (1 << (REL_WHEEL - 8))
+        },
+    },{
+        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
+        .subsel    = ABS_X,
+        .size      = sizeof(virtio_input_absinfo),
+        .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
+        .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
+    },{
+        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
+        .subsel    = ABS_Y,
+        .size      = sizeof(virtio_input_absinfo),
+        .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
+        .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
+    },
+    { /* end of list */ },
+};
+
+static Property virtio_tablet_properties[] = {
+    DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_tablet_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props  = virtio_tablet_properties;
+}
+
 static void virtio_tablet_init(Object *obj)
 {
     VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
     VirtIOInput *vinput = VIRTIO_INPUT(obj);
 
     vhid->handler = &virtio_tablet_handler;
-    virtio_input_init_config(vinput, virtio_tablet_config);
+    virtio_input_init_config(vinput, vhid->wheel_axis
+                             ? virtio_tablet_config_v2
+                             : virtio_tablet_config_v1);
     virtio_input_key_config(vinput, keymap_button,
                             ARRAY_SIZE(keymap_button));
 }
@@ -512,6 +620,7 @@ static const TypeInfo virtio_tablet_info = {
     .parent        = TYPE_VIRTIO_INPUT_HID,
     .instance_size = sizeof(VirtIOInputHID),
     .instance_init = virtio_tablet_init,
+    .class_init    = virtio_tablet_class_init,
 };
 
 /* ----------------------------------------------------------------- */
-- 
2.9.3


Re: [Qemu-devel] [PATCH] virtio-input: send rel-wheel events for wheel buttons
Posted by Marc-André Lureau 6 years, 7 months ago
Hi

On Wed, Aug 23, 2017 at 3:52 PM Gerd Hoffmann <kraxel@redhat.com> wrote:

> qemu uses wheel-up/down button events for mouse wheel input, however
> linux applications typically want REL_WHEEL events.
>
> This fixes wheel with linux guests. Tested with X11/wayland, and
> windows virtio-input driver.
>
> Based on a patch from Marc.
> Added property to enable/disable wheel axis.
> TODO: add compat properties for old machine types.
>

I guess this patch isn't enough to handle migration? Why not modify
hw/compat.h with this patch?


> Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
>

Otherwise looks good to me

---
>  include/hw/virtio/virtio-input.h |   1 +
>  hw/input/virtio-input-hid.c      | 119
> +++++++++++++++++++++++++++++++++++++--
>  2 files changed, 115 insertions(+), 5 deletions(-)
>
> diff --git a/include/hw/virtio/virtio-input.h
> b/include/hw/virtio/virtio-input.h
> index 91df57eca4..054c38836f 100644
> --- a/include/hw/virtio/virtio-input.h
> +++ b/include/hw/virtio/virtio-input.h
> @@ -89,6 +89,7 @@ struct VirtIOInputHID {
>      QemuInputHandler                  *handler;
>      QemuInputHandlerState             *hs;
>      int                               ledstate;
> +    bool                              wheel_axis;
>  };
>
>  struct VirtIOInputHost {
> diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
> index 46c038110c..79ab92e89f 100644
> --- a/hw/input/virtio-input-hid.c
> +++ b/hw/input/virtio-input-hid.c
> @@ -190,6 +190,7 @@ static void virtio_input_key_config(VirtIOInput
> *vinput,
>  static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
>                                        InputEvent *evt)
>  {
> +    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
>      VirtIOInput *vinput = VIRTIO_INPUT(dev);
>      virtio_input_event event;
>      int qcode;
> @@ -215,7 +216,14 @@ static void virtio_input_handle_event(DeviceState
> *dev, QemuConsole *src,
>          break;
>      case INPUT_EVENT_KIND_BTN:
>          btn = evt->u.btn.data;
> -        if (keymap_button[btn->button]) {
> +        if (vhid->wheel_axis && (btn->button == INPUT_BUTTON_WHEEL_UP ||
> +                                 btn->button == INPUT_BUTTON_WHEEL_DOWN))
> {
> +            event.type  = cpu_to_le16(EV_REL);
> +            event.code  = cpu_to_le16(REL_WHEEL);
> +            event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP
> +                                      ? 1 : -1);
> +            virtio_input_send(vinput, &event);
> +        } else if (keymap_button[btn->button]) {
>              event.type  = cpu_to_le16(EV_KEY);
>              event.code  = cpu_to_le16(keymap_button[btn->button]);
>              event.value = cpu_to_le32(btn->down ? 1 : 0);
> @@ -407,7 +415,7 @@ static QemuInputHandler virtio_mouse_handler = {
>      .sync  = virtio_input_handle_sync,
>  };
>
> -static struct virtio_input_config virtio_mouse_config[] = {
> +static struct virtio_input_config virtio_mouse_config_v1[] = {
>      {
>          .select    = VIRTIO_INPUT_CFG_ID_NAME,
>          .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
> @@ -432,13 +440,53 @@ static struct virtio_input_config
> virtio_mouse_config[] = {
>      { /* end of list */ },
>  };
>
> +static struct virtio_input_config virtio_mouse_config_v2[] = {
> +    {
> +        .select    = VIRTIO_INPUT_CFG_ID_NAME,
> +        .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
> +        .u.string  = VIRTIO_ID_NAME_MOUSE,
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
> +        .size      = sizeof(struct virtio_input_devids),
> +        .u.ids     = {
> +            .bustype = const_le16(BUS_VIRTUAL),
> +            .vendor  = const_le16(0x0627), /* same we use for usb hid
> devices */
> +            .product = const_le16(0x0002),
> +            .version = const_le16(0x0002),
> +        },
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_EV_BITS,
> +        .subsel    = EV_REL,
> +        .size      = 2,
> +        .u.bitmap  = {
> +            (1 << REL_X) | (1 << REL_Y),
> +            (1 << (REL_WHEEL - 8))
> +        },
> +    },
> +    { /* end of list */ },
> +};
> +
> +static Property virtio_mouse_properties[] = {
> +    DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void virtio_mouse_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->props  = virtio_mouse_properties;
> +}
> +
>  static void virtio_mouse_init(Object *obj)
>  {
>      VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
>      VirtIOInput *vinput = VIRTIO_INPUT(obj);
>
>      vhid->handler = &virtio_mouse_handler;
> -    virtio_input_init_config(vinput, virtio_mouse_config);
> +    virtio_input_init_config(vinput, vhid->wheel_axis
> +                             ? virtio_mouse_config_v2
> +                             : virtio_mouse_config_v1);
>      virtio_input_key_config(vinput, keymap_button,
>                              ARRAY_SIZE(keymap_button));
>  }
> @@ -448,6 +496,7 @@ static const TypeInfo virtio_mouse_info = {
>      .parent        = TYPE_VIRTIO_INPUT_HID,
>      .instance_size = sizeof(VirtIOInputHID),
>      .instance_init = virtio_mouse_init,
> +    .class_init    = virtio_mouse_class_init,
>  };
>
>  /* ----------------------------------------------------------------- */
> @@ -459,7 +508,7 @@ static QemuInputHandler virtio_tablet_handler = {
>      .sync  = virtio_input_handle_sync,
>  };
>
> -static struct virtio_input_config virtio_tablet_config[] = {
> +static struct virtio_input_config virtio_tablet_config_v1[] = {
>      {
>          .select    = VIRTIO_INPUT_CFG_ID_NAME,
>          .size      = sizeof(VIRTIO_ID_NAME_TABLET),
> @@ -496,13 +545,72 @@ static struct virtio_input_config
> virtio_tablet_config[] = {
>      { /* end of list */ },
>  };
>
> +static struct virtio_input_config virtio_tablet_config_v2[] = {
> +    {
> +        .select    = VIRTIO_INPUT_CFG_ID_NAME,
> +        .size      = sizeof(VIRTIO_ID_NAME_TABLET),
> +        .u.string  = VIRTIO_ID_NAME_TABLET,
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
> +        .size      = sizeof(struct virtio_input_devids),
> +        .u.ids     = {
> +            .bustype = const_le16(BUS_VIRTUAL),
> +            .vendor  = const_le16(0x0627), /* same we use for usb hid
> devices */
> +            .product = const_le16(0x0003),
> +            .version = const_le16(0x0002),
> +        },
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_EV_BITS,
> +        .subsel    = EV_ABS,
> +        .size      = 1,
> +        .u.bitmap  = {
> +            (1 << ABS_X) | (1 << ABS_Y),
> +        },
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_EV_BITS,
> +        .subsel    = EV_REL,
> +        .size      = 2,
> +        .u.bitmap  = {
> +            0,
> +            (1 << (REL_WHEEL - 8))
> +        },
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
> +        .subsel    = ABS_X,
> +        .size      = sizeof(virtio_input_absinfo),
> +        .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
> +        .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
> +        .subsel    = ABS_Y,
> +        .size      = sizeof(virtio_input_absinfo),
> +        .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
> +        .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
> +    },
> +    { /* end of list */ },
> +};
> +
> +static Property virtio_tablet_properties[] = {
> +    DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void virtio_tablet_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->props  = virtio_tablet_properties;
> +}
> +
>  static void virtio_tablet_init(Object *obj)
>  {
>      VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
>      VirtIOInput *vinput = VIRTIO_INPUT(obj);
>
>      vhid->handler = &virtio_tablet_handler;
> -    virtio_input_init_config(vinput, virtio_tablet_config);
> +    virtio_input_init_config(vinput, vhid->wheel_axis
> +                             ? virtio_tablet_config_v2
> +                             : virtio_tablet_config_v1);
>      virtio_input_key_config(vinput, keymap_button,
>                              ARRAY_SIZE(keymap_button));
>  }
> @@ -512,6 +620,7 @@ static const TypeInfo virtio_tablet_info = {
>      .parent        = TYPE_VIRTIO_INPUT_HID,
>      .instance_size = sizeof(VirtIOInputHID),
>      .instance_init = virtio_tablet_init,
> +    .class_init    = virtio_tablet_class_init,
>  };
>
>  /* ----------------------------------------------------------------- */
> --
> 2.9.3
>
>
> --
Marc-André Lureau
Re: [Qemu-devel] [PATCH] virtio-input: send rel-wheel events for wheel buttons
Posted by Gerd Hoffmann 6 years, 7 months ago
On Wed, 2017-08-23 at 14:38 +0000, Marc-André Lureau wrote:
> Hi
> 
> On Wed, Aug 23, 2017 at 3:52 PM Gerd Hoffmann <kraxel@redhat.com>
> wrote:
> > qemu uses wheel-up/down button events for mouse wheel input,
> > however
> > linux applications typically want REL_WHEEL events.
> > 
> > This fixes wheel with linux guests. Tested with X11/wayland, and
> > windows virtio-input driver.
> > 
> > Based on a patch from Marc.
> > Added property to enable/disable wheel axis.
> > TODO: add compat properties for old machine types.
> 
> I guess this patch isn't enough to handle migration? Why not modify
> hw/compat.h with this patch?

Because we are in freeze right now.  Just waiting until 2.11 opens and
the 2.11 machine type patch (seen on the list already) is merged, then
I'll do a v2 with the compat fluff.  Meanwhile this one should be good
enough for testing.

cheers,
  Gerd


Re: [Qemu-devel] [PATCH] virtio-input: send rel-wheel events for wheel buttons
Posted by Ladi Prosek 6 years, 7 months ago
On Wed, Aug 23, 2017 at 3:51 PM, Gerd Hoffmann <kraxel@redhat.com> wrote:
> qemu uses wheel-up/down button events for mouse wheel input, however
> linux applications typically want REL_WHEEL events.
>
> This fixes wheel with linux guests. Tested with X11/wayland, and
> windows virtio-input driver.
>
> Based on a patch from Marc.
> Added property to enable/disable wheel axis.
> TODO: add compat properties for old machine types.
>
> Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

Verified that the Windows driver correctly handles axis-based wheel. Thanks!

Tested-by: Ladi Prosek <lprosek@redhat.com>