diff mbox series

[v2,3/6] virtio-input: add a virtio-mulitouch device

Message ID 20230316120624.46410-4-slp@redhat.com (mailing list archive)
State New, archived
Headers show
Series Implement virtio-multitouch and enable GTK3 to use it | expand

Commit Message

Sergio Lopez March 16, 2023, 12:06 p.m. UTC
Add a virtio-multitouch device to the family of devices emulated by
virtio-input implementing the Multi-touch protocol as descripted here:

https://www.kernel.org/doc/html/latest/input/multi-touch-protocol.html?highlight=multi+touch

This patch just add the device itself, without connecting it to any
backends. The following patches will add a PCI-based multitouch device,
some helpers in "ui" and will enable the GTK3 backend to transpose
multi-touch events from the host to the guest.

Signed-off-by: Sergio Lopez <slp@redhat.com>
---
 hw/input/virtio-input-hid.c      | 118 ++++++++++++++++++++++++++++++-
 include/hw/virtio/virtio-input.h |   9 +--
 2 files changed, 120 insertions(+), 7 deletions(-)

Comments

Marc-André Lureau March 17, 2023, 8:03 a.m. UTC | #1
On Thu, Mar 16, 2023 at 4:07 PM Sergio Lopez <slp@redhat.com> wrote:
>
> Add a virtio-multitouch device to the family of devices emulated by
> virtio-input implementing the Multi-touch protocol as descripted here:
>
> https://www.kernel.org/doc/html/latest/input/multi-touch-protocol.html?highlight=multi+touch
>
> This patch just add the device itself, without connecting it to any
> backends. The following patches will add a PCI-based multitouch device,
> some helpers in "ui" and will enable the GTK3 backend to transpose
> multi-touch events from the host to the guest.
>
> Signed-off-by: Sergio Lopez <slp@redhat.com>

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>



> ---
>  hw/input/virtio-input-hid.c      | 118 ++++++++++++++++++++++++++++++-
>  include/hw/virtio/virtio-input.h |   9 +--
>  2 files changed, 120 insertions(+), 7 deletions(-)
>
> diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
> index d28dab69ba..742235d3fa 100644
> --- a/hw/input/virtio-input-hid.c
> +++ b/hw/input/virtio-input-hid.c
> @@ -16,9 +16,10 @@
>
>  #include "standard-headers/linux/input.h"
>
> -#define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
> -#define VIRTIO_ID_NAME_MOUSE    "QEMU Virtio Mouse"
> -#define VIRTIO_ID_NAME_TABLET   "QEMU Virtio Tablet"
> +#define VIRTIO_ID_NAME_KEYBOARD     "QEMU Virtio Keyboard"
> +#define VIRTIO_ID_NAME_MOUSE        "QEMU Virtio Mouse"
> +#define VIRTIO_ID_NAME_TABLET       "QEMU Virtio Tablet"
> +#define VIRTIO_ID_NAME_MULTITOUCH   "QEMU Virtio Multitouch"
>
>  /* ----------------------------------------------------------------- */
>
> @@ -30,6 +31,7 @@ static const unsigned short keymap_button[INPUT_BUTTON__MAX] = {
>      [INPUT_BUTTON_WHEEL_DOWN]        = BTN_GEAR_DOWN,
>      [INPUT_BUTTON_SIDE]              = BTN_SIDE,
>      [INPUT_BUTTON_EXTRA]             = BTN_EXTRA,
> +    [INPUT_BUTTON_TOUCH]             = BTN_TOUCH,
>  };
>
>  static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
> @@ -42,6 +44,11 @@ static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
>      [INPUT_AXIS_Y]                   = ABS_Y,
>  };
>
> +static const unsigned short axismap_tch[INPUT_AXIS__MAX] = {
> +    [INPUT_AXIS_X]                   = ABS_MT_POSITION_X,
> +    [INPUT_AXIS_Y]                   = ABS_MT_POSITION_Y,
> +};
> +
>  /* ----------------------------------------------------------------- */
>
>  static void virtio_input_extend_config(VirtIOInput *vinput,
> @@ -81,6 +88,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
>      InputKeyEvent *key;
>      InputMoveEvent *move;
>      InputBtnEvent *btn;
> +    InputMultitouchEvent *mtt;
>
>      switch (evt->type) {
>      case INPUT_EVENT_KIND_KEY:
> @@ -137,6 +145,24 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
>          event.value = cpu_to_le32(move->value);
>          virtio_input_send(vinput, &event);
>          break;
> +    case INPUT_EVENT_KIND_MTT:
> +        mtt = evt->u.mtt.data;
> +        if (mtt->type == INPUT_MULTITOUCH_TYPE_DATA) {
> +            event.type  = cpu_to_le16(EV_ABS);
> +            event.code  = cpu_to_le16(axismap_tch[mtt->axis]);
> +            event.value = cpu_to_le32(mtt->value);
> +            virtio_input_send(vinput, &event);
> +        } else {
> +            event.type  = cpu_to_le16(EV_ABS);
> +            event.code  = cpu_to_le16(ABS_MT_SLOT);
> +            event.value = cpu_to_le32(mtt->slot);
> +            virtio_input_send(vinput, &event);
> +            event.type  = cpu_to_le16(EV_ABS);
> +            event.code  = cpu_to_le16(ABS_MT_TRACKING_ID);
> +            event.value = cpu_to_le32(mtt->tracking_id);
> +            virtio_input_send(vinput, &event);
> +        }
> +        break;
>      default:
>          /* keep gcc happy */
>          break;
> @@ -515,12 +541,98 @@ static const TypeInfo virtio_tablet_info = {
>
>  /* ----------------------------------------------------------------- */
>
> +static QemuInputHandler virtio_multitouch_handler = {
> +    .name  = VIRTIO_ID_NAME_MULTITOUCH,
> +    .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_MTT,
> +    .event = virtio_input_handle_event,
> +    .sync  = virtio_input_handle_sync,
> +};
> +
> +static struct virtio_input_config virtio_multitouch_config[] = {
> +    {
> +        .select    = VIRTIO_INPUT_CFG_ID_NAME,
> +        .size      = sizeof(VIRTIO_ID_NAME_MULTITOUCH),
> +        .u.string  = VIRTIO_ID_NAME_MULTITOUCH,
> +    },{
> +        .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(0x0001),
> +        },
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
> +        .subsel    = ABS_MT_SLOT,
> +        .size      = sizeof(virtio_input_absinfo),
> +        .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
> +        .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
> +        .subsel    = ABS_MT_TRACKING_ID,
> +        .size      = sizeof(virtio_input_absinfo),
> +        .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
> +        .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
> +    },{
> +        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
> +        .subsel    = ABS_MT_POSITION_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_MT_POSITION_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 void virtio_multitouch_init(Object *obj)
> +{
> +    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
> +    VirtIOInput *vinput = VIRTIO_INPUT(obj);
> +    unsigned short abs_props[] = {
> +        INPUT_PROP_DIRECT,
> +    };
> +    unsigned short abs_bits[] = {
> +        ABS_MT_SLOT,
> +        ABS_MT_TRACKING_ID,
> +        ABS_MT_POSITION_X,
> +        ABS_MT_POSITION_Y,
> +    };
> +
> +    vhid->handler = &virtio_multitouch_handler;
> +    virtio_input_init_config(vinput, virtio_multitouch_config);
> +    virtio_input_extend_config(vinput, keymap_button,
> +                               ARRAY_SIZE(keymap_button),
> +                               VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
> +    virtio_input_extend_config(vinput, abs_props,
> +                               ARRAY_SIZE(abs_props),
> +                               VIRTIO_INPUT_CFG_PROP_BITS, 0);
> +    virtio_input_extend_config(vinput, abs_bits,
> +                               ARRAY_SIZE(abs_bits),
> +                               VIRTIO_INPUT_CFG_EV_BITS, EV_ABS);
> +}
> +
> +static const TypeInfo virtio_multitouch_info = {
> +    .name          = TYPE_VIRTIO_MULTITOUCH,
> +    .parent        = TYPE_VIRTIO_INPUT_HID,
> +    .instance_size = sizeof(VirtIOInputHID),
> +    .instance_init = virtio_multitouch_init,
> +};
> +
> +/* ----------------------------------------------------------------- */
> +
>  static void virtio_register_types(void)
>  {
>      type_register_static(&virtio_input_hid_info);
>      type_register_static(&virtio_keyboard_info);
>      type_register_static(&virtio_mouse_info);
>      type_register_static(&virtio_tablet_info);
> +    type_register_static(&virtio_multitouch_info);
>  }
>
>  type_init(virtio_register_types)
> diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h
> index f2da63d309..08f1591424 100644
> --- a/include/hw/virtio/virtio-input.h
> +++ b/include/hw/virtio/virtio-input.h
> @@ -24,10 +24,11 @@ OBJECT_DECLARE_TYPE(VirtIOInput, VirtIOInputClass,
>  #define VIRTIO_INPUT_GET_PARENT_CLASS(obj) \
>          OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT)
>
> -#define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device"
> -#define TYPE_VIRTIO_KEYBOARD  "virtio-keyboard-device"
> -#define TYPE_VIRTIO_MOUSE     "virtio-mouse-device"
> -#define TYPE_VIRTIO_TABLET    "virtio-tablet-device"
> +#define TYPE_VIRTIO_INPUT_HID  "virtio-input-hid-device"
> +#define TYPE_VIRTIO_KEYBOARD   "virtio-keyboard-device"
> +#define TYPE_VIRTIO_MOUSE      "virtio-mouse-device"
> +#define TYPE_VIRTIO_TABLET     "virtio-tablet-device"
> +#define TYPE_VIRTIO_MULTITOUCH "virtio-multitouch-device"
>
>  OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHID, VIRTIO_INPUT_HID)
>  #define VIRTIO_INPUT_HID_GET_PARENT_CLASS(obj) \
> --
> 2.38.1
>
>


--
Marc-André Lureau
diff mbox series

Patch

diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index d28dab69ba..742235d3fa 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -16,9 +16,10 @@ 
 
 #include "standard-headers/linux/input.h"
 
-#define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
-#define VIRTIO_ID_NAME_MOUSE    "QEMU Virtio Mouse"
-#define VIRTIO_ID_NAME_TABLET   "QEMU Virtio Tablet"
+#define VIRTIO_ID_NAME_KEYBOARD     "QEMU Virtio Keyboard"
+#define VIRTIO_ID_NAME_MOUSE        "QEMU Virtio Mouse"
+#define VIRTIO_ID_NAME_TABLET       "QEMU Virtio Tablet"
+#define VIRTIO_ID_NAME_MULTITOUCH   "QEMU Virtio Multitouch"
 
 /* ----------------------------------------------------------------- */
 
@@ -30,6 +31,7 @@  static const unsigned short keymap_button[INPUT_BUTTON__MAX] = {
     [INPUT_BUTTON_WHEEL_DOWN]        = BTN_GEAR_DOWN,
     [INPUT_BUTTON_SIDE]              = BTN_SIDE,
     [INPUT_BUTTON_EXTRA]             = BTN_EXTRA,
+    [INPUT_BUTTON_TOUCH]             = BTN_TOUCH,
 };
 
 static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
@@ -42,6 +44,11 @@  static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
     [INPUT_AXIS_Y]                   = ABS_Y,
 };
 
+static const unsigned short axismap_tch[INPUT_AXIS__MAX] = {
+    [INPUT_AXIS_X]                   = ABS_MT_POSITION_X,
+    [INPUT_AXIS_Y]                   = ABS_MT_POSITION_Y,
+};
+
 /* ----------------------------------------------------------------- */
 
 static void virtio_input_extend_config(VirtIOInput *vinput,
@@ -81,6 +88,7 @@  static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
     InputKeyEvent *key;
     InputMoveEvent *move;
     InputBtnEvent *btn;
+    InputMultitouchEvent *mtt;
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_KEY:
@@ -137,6 +145,24 @@  static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
         event.value = cpu_to_le32(move->value);
         virtio_input_send(vinput, &event);
         break;
+    case INPUT_EVENT_KIND_MTT:
+        mtt = evt->u.mtt.data;
+        if (mtt->type == INPUT_MULTITOUCH_TYPE_DATA) {
+            event.type  = cpu_to_le16(EV_ABS);
+            event.code  = cpu_to_le16(axismap_tch[mtt->axis]);
+            event.value = cpu_to_le32(mtt->value);
+            virtio_input_send(vinput, &event);
+        } else {
+            event.type  = cpu_to_le16(EV_ABS);
+            event.code  = cpu_to_le16(ABS_MT_SLOT);
+            event.value = cpu_to_le32(mtt->slot);
+            virtio_input_send(vinput, &event);
+            event.type  = cpu_to_le16(EV_ABS);
+            event.code  = cpu_to_le16(ABS_MT_TRACKING_ID);
+            event.value = cpu_to_le32(mtt->tracking_id);
+            virtio_input_send(vinput, &event);
+        }
+        break;
     default:
         /* keep gcc happy */
         break;
@@ -515,12 +541,98 @@  static const TypeInfo virtio_tablet_info = {
 
 /* ----------------------------------------------------------------- */
 
+static QemuInputHandler virtio_multitouch_handler = {
+    .name  = VIRTIO_ID_NAME_MULTITOUCH,
+    .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_MTT,
+    .event = virtio_input_handle_event,
+    .sync  = virtio_input_handle_sync,
+};
+
+static struct virtio_input_config virtio_multitouch_config[] = {
+    {
+        .select    = VIRTIO_INPUT_CFG_ID_NAME,
+        .size      = sizeof(VIRTIO_ID_NAME_MULTITOUCH),
+        .u.string  = VIRTIO_ID_NAME_MULTITOUCH,
+    },{
+        .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(0x0001),
+        },
+    },{
+        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
+        .subsel    = ABS_MT_SLOT,
+        .size      = sizeof(virtio_input_absinfo),
+        .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
+        .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
+    },{
+        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
+        .subsel    = ABS_MT_TRACKING_ID,
+        .size      = sizeof(virtio_input_absinfo),
+        .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
+        .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
+    },{
+        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
+        .subsel    = ABS_MT_POSITION_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_MT_POSITION_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 void virtio_multitouch_init(Object *obj)
+{
+    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
+    VirtIOInput *vinput = VIRTIO_INPUT(obj);
+    unsigned short abs_props[] = {
+        INPUT_PROP_DIRECT,
+    };
+    unsigned short abs_bits[] = {
+        ABS_MT_SLOT,
+        ABS_MT_TRACKING_ID,
+        ABS_MT_POSITION_X,
+        ABS_MT_POSITION_Y,
+    };
+
+    vhid->handler = &virtio_multitouch_handler;
+    virtio_input_init_config(vinput, virtio_multitouch_config);
+    virtio_input_extend_config(vinput, keymap_button,
+                               ARRAY_SIZE(keymap_button),
+                               VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
+    virtio_input_extend_config(vinput, abs_props,
+                               ARRAY_SIZE(abs_props),
+                               VIRTIO_INPUT_CFG_PROP_BITS, 0);
+    virtio_input_extend_config(vinput, abs_bits,
+                               ARRAY_SIZE(abs_bits),
+                               VIRTIO_INPUT_CFG_EV_BITS, EV_ABS);
+}
+
+static const TypeInfo virtio_multitouch_info = {
+    .name          = TYPE_VIRTIO_MULTITOUCH,
+    .parent        = TYPE_VIRTIO_INPUT_HID,
+    .instance_size = sizeof(VirtIOInputHID),
+    .instance_init = virtio_multitouch_init,
+};
+
+/* ----------------------------------------------------------------- */
+
 static void virtio_register_types(void)
 {
     type_register_static(&virtio_input_hid_info);
     type_register_static(&virtio_keyboard_info);
     type_register_static(&virtio_mouse_info);
     type_register_static(&virtio_tablet_info);
+    type_register_static(&virtio_multitouch_info);
 }
 
 type_init(virtio_register_types)
diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h
index f2da63d309..08f1591424 100644
--- a/include/hw/virtio/virtio-input.h
+++ b/include/hw/virtio/virtio-input.h
@@ -24,10 +24,11 @@  OBJECT_DECLARE_TYPE(VirtIOInput, VirtIOInputClass,
 #define VIRTIO_INPUT_GET_PARENT_CLASS(obj) \
         OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT)
 
-#define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device"
-#define TYPE_VIRTIO_KEYBOARD  "virtio-keyboard-device"
-#define TYPE_VIRTIO_MOUSE     "virtio-mouse-device"
-#define TYPE_VIRTIO_TABLET    "virtio-tablet-device"
+#define TYPE_VIRTIO_INPUT_HID  "virtio-input-hid-device"
+#define TYPE_VIRTIO_KEYBOARD   "virtio-keyboard-device"
+#define TYPE_VIRTIO_MOUSE      "virtio-mouse-device"
+#define TYPE_VIRTIO_TABLET     "virtio-tablet-device"
+#define TYPE_VIRTIO_MULTITOUCH "virtio-multitouch-device"
 
 OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHID, VIRTIO_INPUT_HID)
 #define VIRTIO_INPUT_HID_GET_PARENT_CLASS(obj) \