Input: xen-kbdfront - fix mouse getting stuck after save/restore
[firefly-linux-kernel-4.4.55.git] / drivers / input / xen-kbdfront.c
1 /*
2  * Xen para-virtual input device
3  *
4  * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
5  * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
6  *
7  *  Based on linux/drivers/input/mouse/sermouse.c
8  *
9  *  This file is subject to the terms and conditions of the GNU General Public
10  *  License. See the file COPYING in the main directory of this archive for
11  *  more details.
12  */
13
14 /*
15  * TODO:
16  *
17  * Switch to grant tables together with xen-fbfront.c.
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/module.h>
23 #include <linux/input.h>
24 #include <asm/xen/hypervisor.h>
25 #include <xen/events.h>
26 #include <xen/page.h>
27 #include <xen/interface/io/fbif.h>
28 #include <xen/interface/io/kbdif.h>
29 #include <xen/xenbus.h>
30
31 struct xenkbd_info {
32         struct input_dev *kbd;
33         struct input_dev *ptr;
34         struct xenkbd_page *page;
35         int irq;
36         struct xenbus_device *xbdev;
37         char phys[32];
38 };
39
40 static int xenkbd_remove(struct xenbus_device *);
41 static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
42 static void xenkbd_disconnect_backend(struct xenkbd_info *);
43
44 /*
45  * Note: if you need to send out events, see xenfb_do_update() for how
46  * to do that.
47  */
48
49 static irqreturn_t input_handler(int rq, void *dev_id)
50 {
51         struct xenkbd_info *info = dev_id;
52         struct xenkbd_page *page = info->page;
53         __u32 cons, prod;
54
55         prod = page->in_prod;
56         if (prod == page->in_cons)
57                 return IRQ_HANDLED;
58         rmb();                  /* ensure we see ring contents up to prod */
59         for (cons = page->in_cons; cons != prod; cons++) {
60                 union xenkbd_in_event *event;
61                 struct input_dev *dev;
62                 event = &XENKBD_IN_RING_REF(page, cons);
63
64                 dev = info->ptr;
65                 switch (event->type) {
66                 case XENKBD_TYPE_MOTION:
67                         input_report_rel(dev, REL_X, event->motion.rel_x);
68                         input_report_rel(dev, REL_Y, event->motion.rel_y);
69                         if (event->motion.rel_z)
70                                 input_report_rel(dev, REL_WHEEL,
71                                                  -event->motion.rel_z);
72                         break;
73                 case XENKBD_TYPE_KEY:
74                         dev = NULL;
75                         if (test_bit(event->key.keycode, info->kbd->keybit))
76                                 dev = info->kbd;
77                         if (test_bit(event->key.keycode, info->ptr->keybit))
78                                 dev = info->ptr;
79                         if (dev)
80                                 input_report_key(dev, event->key.keycode,
81                                                  event->key.pressed);
82                         else
83                                 printk(KERN_WARNING
84                                        "xenkbd: unhandled keycode 0x%x\n",
85                                        event->key.keycode);
86                         break;
87                 case XENKBD_TYPE_POS:
88                         input_report_abs(dev, ABS_X, event->pos.abs_x);
89                         input_report_abs(dev, ABS_Y, event->pos.abs_y);
90                         if (event->pos.rel_z)
91                                 input_report_rel(dev, REL_WHEEL,
92                                                  -event->pos.rel_z);
93                         break;
94                 }
95                 if (dev)
96                         input_sync(dev);
97         }
98         mb();                   /* ensure we got ring contents */
99         page->in_cons = cons;
100         notify_remote_via_irq(info->irq);
101
102         return IRQ_HANDLED;
103 }
104
105 static int __devinit xenkbd_probe(struct xenbus_device *dev,
106                                   const struct xenbus_device_id *id)
107 {
108         int ret, i, abs;
109         struct xenkbd_info *info;
110         struct input_dev *kbd, *ptr;
111
112         info = kzalloc(sizeof(*info), GFP_KERNEL);
113         if (!info) {
114                 xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
115                 return -ENOMEM;
116         }
117         dev_set_drvdata(&dev->dev, info);
118         info->xbdev = dev;
119         info->irq = -1;
120         snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
121
122         info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
123         if (!info->page)
124                 goto error_nomem;
125
126         if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
127                 abs = 0;
128         if (abs)
129                 xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
130
131         /* keyboard */
132         kbd = input_allocate_device();
133         if (!kbd)
134                 goto error_nomem;
135         kbd->name = "Xen Virtual Keyboard";
136         kbd->phys = info->phys;
137         kbd->id.bustype = BUS_PCI;
138         kbd->id.vendor = 0x5853;
139         kbd->id.product = 0xffff;
140
141         __set_bit(EV_KEY, kbd->evbit);
142         for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
143                 __set_bit(i, kbd->keybit);
144         for (i = KEY_OK; i < KEY_MAX; i++)
145                 __set_bit(i, kbd->keybit);
146
147         ret = input_register_device(kbd);
148         if (ret) {
149                 input_free_device(kbd);
150                 xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
151                 goto error;
152         }
153         info->kbd = kbd;
154
155         /* pointing device */
156         ptr = input_allocate_device();
157         if (!ptr)
158                 goto error_nomem;
159         ptr->name = "Xen Virtual Pointer";
160         ptr->phys = info->phys;
161         ptr->id.bustype = BUS_PCI;
162         ptr->id.vendor = 0x5853;
163         ptr->id.product = 0xfffe;
164
165         if (abs) {
166                 __set_bit(EV_ABS, ptr->evbit);
167                 input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
168                 input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
169         } else {
170                 input_set_capability(ptr, EV_REL, REL_X);
171                 input_set_capability(ptr, EV_REL, REL_Y);
172         }
173         input_set_capability(ptr, EV_REL, REL_WHEEL);
174
175         __set_bit(EV_KEY, ptr->evbit);
176         for (i = BTN_LEFT; i <= BTN_TASK; i++)
177                 __set_bit(i, ptr->keybit);
178
179         ret = input_register_device(ptr);
180         if (ret) {
181                 input_free_device(ptr);
182                 xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
183                 goto error;
184         }
185         info->ptr = ptr;
186
187         ret = xenkbd_connect_backend(dev, info);
188         if (ret < 0)
189                 goto error;
190
191         return 0;
192
193  error_nomem:
194         ret = -ENOMEM;
195         xenbus_dev_fatal(dev, ret, "allocating device memory");
196  error:
197         xenkbd_remove(dev);
198         return ret;
199 }
200
201 static int xenkbd_resume(struct xenbus_device *dev)
202 {
203         struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
204
205         xenkbd_disconnect_backend(info);
206         memset(info->page, 0, PAGE_SIZE);
207         return xenkbd_connect_backend(dev, info);
208 }
209
210 static int xenkbd_remove(struct xenbus_device *dev)
211 {
212         struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
213
214         xenkbd_disconnect_backend(info);
215         if (info->kbd)
216                 input_unregister_device(info->kbd);
217         if (info->ptr)
218                 input_unregister_device(info->ptr);
219         free_page((unsigned long)info->page);
220         kfree(info);
221         return 0;
222 }
223
224 static int xenkbd_connect_backend(struct xenbus_device *dev,
225                                   struct xenkbd_info *info)
226 {
227         int ret, evtchn;
228         struct xenbus_transaction xbt;
229
230         ret = xenbus_alloc_evtchn(dev, &evtchn);
231         if (ret)
232                 return ret;
233         ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
234                                         0, dev->devicetype, info);
235         if (ret < 0) {
236                 xenbus_free_evtchn(dev, evtchn);
237                 xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
238                 return ret;
239         }
240         info->irq = ret;
241
242  again:
243         ret = xenbus_transaction_start(&xbt);
244         if (ret) {
245                 xenbus_dev_fatal(dev, ret, "starting transaction");
246                 return ret;
247         }
248         ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
249                             virt_to_mfn(info->page));
250         if (ret)
251                 goto error_xenbus;
252         ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
253                             evtchn);
254         if (ret)
255                 goto error_xenbus;
256         ret = xenbus_transaction_end(xbt, 0);
257         if (ret) {
258                 if (ret == -EAGAIN)
259                         goto again;
260                 xenbus_dev_fatal(dev, ret, "completing transaction");
261                 return ret;
262         }
263
264         xenbus_switch_state(dev, XenbusStateInitialised);
265         return 0;
266
267  error_xenbus:
268         xenbus_transaction_end(xbt, 1);
269         xenbus_dev_fatal(dev, ret, "writing xenstore");
270         return ret;
271 }
272
273 static void xenkbd_disconnect_backend(struct xenkbd_info *info)
274 {
275         if (info->irq >= 0)
276                 unbind_from_irqhandler(info->irq, info);
277         info->irq = -1;
278 }
279
280 static void xenkbd_backend_changed(struct xenbus_device *dev,
281                                    enum xenbus_state backend_state)
282 {
283         struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
284         int ret, val;
285
286         switch (backend_state) {
287         case XenbusStateInitialising:
288         case XenbusStateInitialised:
289         case XenbusStateUnknown:
290         case XenbusStateClosed:
291                 break;
292
293         case XenbusStateInitWait:
294 InitWait:
295                 ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
296                                    "feature-abs-pointer", "%d", &val);
297                 if (ret < 0)
298                         val = 0;
299                 if (val) {
300                         ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
301                                             "request-abs-pointer", "1");
302                         if (ret)
303                                 pr_warning("can't request abs-pointer\n");
304                 }
305                 xenbus_switch_state(dev, XenbusStateConnected);
306                 break;
307
308         case XenbusStateConnected:
309                 /*
310                  * Work around xenbus race condition: If backend goes
311                  * through InitWait to Connected fast enough, we can
312                  * get Connected twice here.
313                  */
314                 if (dev->state != XenbusStateConnected)
315                         goto InitWait; /* no InitWait seen yet, fudge it */
316
317                 /* Set input abs params to match backend screen res */
318                 if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
319                                  "width", "%d", &val) > 0)
320                         input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
321
322                 if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
323                                  "height", "%d", &val) > 0)
324                         input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
325
326                 break;
327
328         case XenbusStateClosing:
329                 xenbus_frontend_closed(dev);
330                 break;
331         }
332 }
333
334 static struct xenbus_device_id xenkbd_ids[] = {
335         { "vkbd" },
336         { "" }
337 };
338
339 static struct xenbus_driver xenkbd_driver = {
340         .name = "vkbd",
341         .owner = THIS_MODULE,
342         .ids = xenkbd_ids,
343         .probe = xenkbd_probe,
344         .remove = xenkbd_remove,
345         .resume = xenkbd_resume,
346         .otherend_changed = xenkbd_backend_changed,
347 };
348
349 static int __init xenkbd_init(void)
350 {
351         if (!xen_domain())
352                 return -ENODEV;
353
354         /* Nothing to do if running in dom0. */
355         if (xen_initial_domain())
356                 return -ENODEV;
357
358         return xenbus_register_frontend(&xenkbd_driver);
359 }
360
361 static void __exit xenkbd_cleanup(void)
362 {
363         xenbus_unregister_driver(&xenkbd_driver);
364 }
365
366 module_init(xenkbd_init);
367 module_exit(xenkbd_cleanup);
368
369 MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
370 MODULE_LICENSE("GPL");
371 MODULE_ALIAS("xen:vkbd");