Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / fbfront / xenkbd.c
1 /*
2  * linux/drivers/input/keyboard/xenkbd.c -- Xen para-virtual input device
3  *
4  * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
5  * Copyright (C) 2006 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 xenfb.c.
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/module.h>
23 #include <linux/slab.h>
24 #include <linux/input.h>
25 #include <asm/hypervisor.h>
26 #include <xen/evtchn.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 {
33         struct input_dev *kbd;
34         struct input_dev *ptr;
35         struct xenkbd_page *page;
36         int irq;
37         struct xenbus_device *xbdev;
38         char phys[32];
39 };
40
41 static int xenkbd_remove(struct xenbus_device *);
42 static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
43 static void xenkbd_disconnect_backend(struct xenkbd_info *);
44
45 /*
46  * Note: if you need to send out events, see xenfb_do_update() for how
47  * to do that.
48  */
49
50 static irqreturn_t input_handler(int rq, void *dev_id)
51 {
52         struct xenkbd_info *info = dev_id;
53         struct xenkbd_page *page = info->page;
54         __u32 cons, prod;
55
56         prod = page->in_prod;
57         if (prod == page->in_cons)
58                 return IRQ_HANDLED;
59         rmb();                  /* ensure we see ring contents up to prod */
60         for (cons = page->in_cons; cons != prod; cons++) {
61                 union xenkbd_in_event *event;
62                 struct input_dev *dev;
63                 event = &XENKBD_IN_RING_REF(page, cons);
64
65                 dev = info->ptr;
66                 switch (event->type) {
67                 case XENKBD_TYPE_MOTION:
68                         if (event->motion.rel_z)
69                                 input_report_rel(dev, REL_WHEEL,
70                                                  -event->motion.rel_z);
71                         input_report_rel(dev, REL_X, event->motion.rel_x);
72                         input_report_rel(dev, REL_Y, event->motion.rel_y);
73                         break;
74                 case XENKBD_TYPE_KEY:
75                         dev = NULL;
76                         if (test_bit(event->key.keycode, info->kbd->keybit))
77                                 dev = info->kbd;
78                         if (test_bit(event->key.keycode, info->ptr->keybit))
79                                 dev = info->ptr;
80                         if (dev)
81                                 input_report_key(dev, event->key.keycode,
82                                                  event->key.pressed);
83                         else
84                                 pr_warning("xenkbd: unhandled keycode 0x%x\n",
85                                            event->key.keycode);
86                         break;
87                 case XENKBD_TYPE_POS:
88                         if (event->pos.rel_z)
89                                 input_report_rel(dev, REL_WHEEL,
90                                                  -event->pos.rel_z);
91                         input_report_abs(dev, ABS_X, event->pos.abs_x);
92                         input_report_abs(dev, ABS_Y, event->pos.abs_y);
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 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         snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
120
121         info->page = (void *)__get_free_page(GFP_KERNEL);
122         if (!info->page)
123                 goto error_nomem;
124         info->page->in_cons = info->page->in_prod = 0;
125         info->page->out_cons = info->page->out_prod = 0;
126
127         if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
128                 abs = 0;
129         if (abs)
130                 xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
131
132         /* keyboard */
133         kbd = input_allocate_device();
134         if (!kbd)
135                 goto error_nomem;
136         kbd->name = "Xen Virtual Keyboard";
137         kbd->phys = info->phys;
138         kbd->id.bustype = BUS_PCI;
139         kbd->id.vendor = 0x5853;
140         kbd->id.product = 0xffff;
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         info->page->in_cons = info->page->in_prod = 0;
207         info->page->out_cons = info->page->out_prod = 0;
208         return xenkbd_connect_backend(dev, info);
209 }
210
211 static int xenkbd_remove(struct xenbus_device *dev)
212 {
213         struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
214
215         xenkbd_disconnect_backend(info);
216         input_unregister_device(info->kbd);
217         input_unregister_device(info->ptr);
218         free_page((unsigned long)info->page);
219         kfree(info);
220         return 0;
221 }
222
223 static int xenkbd_connect_backend(struct xenbus_device *dev,
224                                   struct xenkbd_info *info)
225 {
226         int ret;
227         struct xenbus_transaction xbt;
228
229         ret = bind_listening_port_to_irqhandler(
230                 dev->otherend_id, input_handler, 0, "xenkbd", info);
231         if (ret < 0) {
232                 xenbus_dev_fatal(dev, ret,
233                                  "bind_listening_port_to_irqhandler");
234                 return ret;
235         }
236         info->irq = ret;
237
238  again:
239         ret = xenbus_transaction_start(&xbt);
240         if (ret) {
241                 xenbus_dev_fatal(dev, ret, "starting transaction");
242                 return ret;
243         }
244         ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
245                             virt_to_mfn(info->page));
246         if (ret)
247                 goto error_xenbus;
248         ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
249                             irq_to_evtchn_port(info->irq));
250         if (ret)
251                 goto error_xenbus;
252         ret = xenbus_transaction_end(xbt, 0);
253         if (ret) {
254                 if (ret == -EAGAIN)
255                         goto again;
256                 xenbus_dev_fatal(dev, ret, "completing transaction");
257                 return ret;
258         }
259
260         xenbus_switch_state(dev, XenbusStateInitialised);
261         return 0;
262
263  error_xenbus:
264         xenbus_transaction_end(xbt, 1);
265         xenbus_dev_fatal(dev, ret, "writing xenstore");
266         return ret;
267 }
268
269 static void xenkbd_disconnect_backend(struct xenkbd_info *info)
270 {
271         if (info->irq >= 0)
272                 unbind_from_irqhandler(info->irq, info);
273         info->irq = -1;
274 }
275
276 static void xenkbd_backend_changed(struct xenbus_device *dev,
277                                    enum xenbus_state backend_state)
278 {
279         struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
280         int ret, val;
281
282         switch (backend_state) {
283         case XenbusStateInitialising:
284         case XenbusStateInitialised:
285         case XenbusStateReconfiguring:
286         case XenbusStateReconfigured:
287         case XenbusStateUnknown:
288         case XenbusStateClosed:
289                 break;
290
291         case XenbusStateInitWait:
292         InitWait:
293                 ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
294                                    "feature-abs-pointer", "%d", &val);
295                 if (ret < 0)
296                         val = 0;
297                 if (val) {
298                         ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
299                                             "request-abs-pointer", "1");
300                         if (ret)
301                                 ; /* FIXME */
302                 }
303                 xenbus_switch_state(dev, XenbusStateConnected);
304                 break;
305
306         case XenbusStateConnected:
307                 /*
308                  * Work around xenbus race condition: If backend goes
309                  * through InitWait to Connected fast enough, we can
310                  * get Connected twice here.
311                  */
312                 if (dev->state != XenbusStateConnected)
313                         goto InitWait; /* no InitWait seen yet, fudge it */
314
315                 /* Set input abs params to match backend screen res */
316                 if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
317                                    "width", "%d", &val) > 0 )
318                         input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
319
320                 if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
321                                    "height", "%d", &val) > 0 )
322                         input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
323
324                 break;
325
326         case XenbusStateClosing:
327                 xenbus_frontend_closed(dev);
328                 break;
329         }
330 }
331
332 static const struct xenbus_device_id xenkbd_ids[] = {
333         { "vkbd" },
334         { "" }
335 };
336 MODULE_ALIAS("xen:vkbd");
337
338 static DEFINE_XENBUS_DRIVER(xenkbd, ,
339         .probe = xenkbd_probe,
340         .remove = xenkbd_remove,
341         .resume = xenkbd_resume,
342         .otherend_changed = xenkbd_backend_changed,
343 );
344
345 static int __init xenkbd_init(void)
346 {
347         if (!is_running_on_xen())
348                 return -ENODEV;
349
350         /* Nothing to do if running in dom0. */
351         if (is_initial_xendomain())
352                 return -ENODEV;
353
354         return xenbus_register_frontend(&xenkbd_driver);
355 }
356
357 static void __exit xenkbd_cleanup(void)
358 {
359         return xenbus_unregister_driver(&xenkbd_driver);
360 }
361
362 module_init(xenkbd_init);
363 module_exit(xenkbd_cleanup);
364
365 MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
366 MODULE_LICENSE("GPL");