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 |
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 --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) \
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(-)