Messages in this thread | | | Subject | Re: [PATCH v1] xen/input: add multi-touch support | From | Oleksandr Andrushchenko <> | Date | Thu, 29 Jun 2017 08:52:03 +0300 |
| |
ping
On 06/23/2017 09:09 AM, Oleksandr Andrushchenko wrote: > From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> > > Extend xen_kbdfront to provide multi-touch support > to unprivileged domains. > > Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> > > --- > Changes since initial: > - use input_set_capability instead of setting flags directly > - input_mt_init_slots: let userspace better chance of figuring > how to handle the device: use INPUT_MT_DIRECT, > drop INPUT_MT_DROP_UNUSED > - add error handling for input_mt_init_slots > - remove module paramters > - remove odd unlikely > --- > drivers/input/misc/xen-kbdfront.c | 135 +++++++++++++++++++++++++++++++++++++- > 1 file changed, 133 insertions(+), 2 deletions(-) > > diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c > index eb770613a9bd..9fa005038773 100644 > --- a/drivers/input/misc/xen-kbdfront.c > +++ b/drivers/input/misc/xen-kbdfront.c > @@ -17,6 +17,7 @@ > #include <linux/errno.h> > #include <linux/module.h> > #include <linux/input.h> > +#include <linux/input/mt.h> > #include <linux/slab.h> > > #include <asm/xen/hypervisor.h> > @@ -34,11 +35,14 @@ > struct xenkbd_info { > struct input_dev *kbd; > struct input_dev *ptr; > + struct input_dev *mtouch; > struct xenkbd_page *page; > int gref; > int irq; > struct xenbus_device *xbdev; > char phys[32]; > + /* current MT slot/contact ID we are injecting events in */ > + int mtouch_cur_contact_id; > }; > > enum { KPARAM_X, KPARAM_Y, KPARAM_CNT }; > @@ -100,6 +104,60 @@ static irqreturn_t input_handler(int rq, void *dev_id) > input_report_rel(dev, REL_WHEEL, > -event->pos.rel_z); > break; > + case XENKBD_TYPE_MTOUCH: > + dev = info->mtouch; > + if (unlikely(!dev)) > + break; > + if (event->mtouch.contact_id != > + info->mtouch_cur_contact_id) { > + info->mtouch_cur_contact_id = > + event->mtouch.contact_id; > + input_mt_slot(dev, event->mtouch.contact_id); > + } > + switch (event->mtouch.event_type) { > + case XENKBD_MT_EV_DOWN: > + input_mt_report_slot_state(dev, MT_TOOL_FINGER, > + true); > + input_event(dev, EV_ABS, ABS_MT_POSITION_X, > + event->mtouch.u.pos.abs_x); > + input_event(dev, EV_ABS, ABS_MT_POSITION_Y, > + event->mtouch.u.pos.abs_y); > + input_event(dev, EV_ABS, ABS_X, > + event->mtouch.u.pos.abs_x); > + input_event(dev, EV_ABS, ABS_Y, > + event->mtouch.u.pos.abs_y); > + break; > + case XENKBD_MT_EV_UP: > + input_mt_report_slot_state(dev, MT_TOOL_FINGER, > + false); > + break; > + case XENKBD_MT_EV_MOTION: > + input_event(dev, EV_ABS, ABS_MT_POSITION_X, > + event->mtouch.u.pos.abs_x); > + input_event(dev, EV_ABS, ABS_MT_POSITION_Y, > + event->mtouch.u.pos.abs_y); > + input_event(dev, EV_ABS, ABS_X, > + event->mtouch.u.pos.abs_x); > + input_event(dev, EV_ABS, ABS_Y, > + event->mtouch.u.pos.abs_y); > + break; > + case XENKBD_MT_EV_SYN: > + input_mt_sync_frame(dev); > + break; > + case XENKBD_MT_EV_SHAPE: > + input_event(dev, EV_ABS, ABS_MT_TOUCH_MAJOR, > + event->mtouch.u.shape.major); > + input_event(dev, EV_ABS, ABS_MT_TOUCH_MINOR, > + event->mtouch.u.shape.minor); > + break; > + case XENKBD_MT_EV_ORIENT: > + input_event(dev, EV_ABS, ABS_MT_ORIENTATION, > + event->mtouch.u.orientation); > + break; > + } > + /* only report syn when requested */ > + if (event->mtouch.event_type != XENKBD_MT_EV_SYN) > + dev = NULL; > } > if (dev) > input_sync(dev); > @@ -115,9 +173,9 @@ static int xenkbd_probe(struct xenbus_device *dev, > const struct xenbus_device_id *id) > { > int ret, i; > - unsigned int abs; > + unsigned int abs, touch; > struct xenkbd_info *info; > - struct input_dev *kbd, *ptr; > + struct input_dev *kbd, *ptr, *mtouch; > > info = kzalloc(sizeof(*info), GFP_KERNEL); > if (!info) { > @@ -152,6 +210,17 @@ static int xenkbd_probe(struct xenbus_device *dev, > } > } > > + touch = xenbus_read_unsigned(dev->nodename, > + XENKBD_FIELD_FEAT_MTOUCH, 0); > + if (touch) { > + ret = xenbus_write(XBT_NIL, dev->nodename, > + XENKBD_FIELD_REQ_MTOUCH, "1"); > + if (ret) { > + pr_warning("xenkbd: can't request multi-touch"); > + touch = 0; > + } > + } > + > /* keyboard */ > kbd = input_allocate_device(); > if (!kbd) > @@ -208,6 +277,66 @@ static int xenkbd_probe(struct xenbus_device *dev, > } > info->ptr = ptr; > > + /* multi-touch device */ > + if (touch) { > + int num_cont, width, height; > + > + mtouch = input_allocate_device(); > + if (!mtouch) > + goto error_nomem; > + > + num_cont = xenbus_read_unsigned(info->xbdev->nodename, > + XENKBD_FIELD_MT_NUM_CONTACTS, > + 1); > + width = xenbus_read_unsigned(info->xbdev->nodename, > + XENKBD_FIELD_MT_WIDTH, > + XENFB_WIDTH); > + height = xenbus_read_unsigned(info->xbdev->nodename, > + XENKBD_FIELD_MT_HEIGHT, > + XENFB_HEIGHT); > + > + mtouch->name = "Xen Virtual Multi-touch"; > + mtouch->phys = info->phys; > + mtouch->id.bustype = BUS_PCI; > + mtouch->id.vendor = 0x5853; > + mtouch->id.product = 0xfffd; > + > + input_set_capability(mtouch, EV_KEY, BTN_TOUCH); > + input_set_abs_params(mtouch, ABS_X, > + 0, width, 0, 0); > + input_set_abs_params(mtouch, ABS_Y, > + 0, height, 0, 0); > + input_set_abs_params(mtouch, ABS_PRESSURE, > + 0, 255, 0, 0); > + > + input_set_abs_params(mtouch, ABS_MT_TOUCH_MAJOR, > + 0, 255, 0, 0); > + input_set_abs_params(mtouch, ABS_MT_POSITION_X, > + 0, width, 0, 0); > + input_set_abs_params(mtouch, ABS_MT_POSITION_Y, > + 0, height, 0, 0); > + input_set_abs_params(mtouch, ABS_MT_PRESSURE, > + 0, 255, 0, 0); > + > + ret = input_mt_init_slots(mtouch, num_cont, INPUT_MT_DIRECT); > + if (ret) { > + input_free_device(mtouch); > + xenbus_dev_fatal(info->xbdev, ret, > + "input_mt_init_slots"); > + goto error; > + } > + > + ret = input_register_device(mtouch); > + if (ret) { > + input_free_device(mtouch); > + xenbus_dev_fatal(info->xbdev, ret, > + "input_register_device(mtouch)"); > + goto error; > + } > + info->mtouch_cur_contact_id = -1; > + info->mtouch = mtouch; > + } > + > ret = xenkbd_connect_backend(dev, info); > if (ret < 0) > goto error; > @@ -240,6 +369,8 @@ static int xenkbd_remove(struct xenbus_device *dev) > input_unregister_device(info->kbd); > if (info->ptr) > input_unregister_device(info->ptr); > + if (info->mtouch) > + input_unregister_device(info->mtouch); > free_page((unsigned long)info->page); > kfree(info); > return 0;
| |