2 * linux/drivers/input/keyboard/xenkbd.c -- Xen para-virtual input device
6 * Anthony Liguori <aliguori@us.ibm.com>
8 * Based on linux/drivers/input/mouse/sermouse.c
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive for
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/module.h>
18 #include <linux/input.h>
19 #include <asm/hypervisor.h>
20 #include <xen/evtchn.h>
21 #include <xen/xenbus.h>
22 #include <linux/xenkbd.h>
26 struct input_dev *dev;
27 struct xenkbd_info *info;
32 static irqreturn_t input_handler(int rq, void *dev_id, struct pt_regs *regs)
34 struct xenkbd_device *dev = dev_id;
35 struct xenkbd_info *info = dev ? dev->info : 0;
36 static int button_map[3] = { BTN_RIGHT, BTN_MIDDLE, BTN_LEFT };
40 rmb(); /* ensure we see ring contents up to prod */
41 for (cons = info->in_cons; cons != prod; cons++) {
42 union xenkbd_in_event *event;
43 event = &XENKBD_IN_RING_REF(info, cons);
45 switch (event->type) {
46 case XENKBD_TYPE_MOTION:
47 input_report_rel(dev->dev, REL_X, event->motion.rel_x);
48 input_report_rel(dev->dev, REL_Y, event->motion.rel_y);
50 case XENKBD_TYPE_BUTTON:
51 if (event->button.button < 3)
52 input_report_key(dev->dev,
53 button_map[event->button.button],
54 event->button.pressed);
57 input_report_key(dev->dev, event->key.keycode, event->key.pressed);
62 mb(); /* ensure we got ring contents */
64 notify_remote_via_evtchn(dev->evtchn);
69 static struct xenkbd_device *xenkbd_dev;
71 int __init xenkbd_init(void)
75 struct xenkbd_device *dev;
76 struct input_dev *input_dev;
77 struct evtchn_alloc_unbound alloc_unbound;
78 struct xenbus_transaction xbt;
80 /* Nothing to do if running in dom0. */
81 if (is_initial_xendomain())
84 /* if we're not set up to use graphics mode, then don't initialize */
85 if (xenbus_scanf(XBT_NIL, "console", "use_graphics", "%d", &ret) < 0)
91 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
92 input_dev = input_allocate_device();
93 if (!dev || !input_dev)
97 dev->info = (void *)__get_free_page(GFP_KERNEL);
103 alloc_unbound.dom = DOMID_SELF;
104 alloc_unbound.remote_dom = 0;
105 ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
109 dev->evtchn = alloc_unbound.port;
110 ret = bind_evtchn_to_irqhandler(dev->evtchn, input_handler, 0,
116 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
117 input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
118 input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
120 /* FIXME not sure this is quite right */
121 for (i = 0; i < 256; i++)
122 set_bit(i, input_dev->keybit);
124 input_dev->name = "Xen Virtual Keyboard/Mouse";
126 input_register_device(input_dev);
129 ret = xenbus_transaction_start(&xbt);
132 ret = xenbus_printf(xbt, "vkbd", "page-ref", "%lu",
133 virt_to_mfn(dev->info));
136 ret = xenbus_printf(xbt, "vkbd", "event-channel", "%u",
140 ret = xenbus_transaction_end(xbt, 0);
147 dev->info->in_cons = dev->info->in_prod = 0;
148 dev->info->out_cons = dev->info->out_prod = 0;
155 xenbus_transaction_end(xbt, 1);
157 input_unregister_device(input_dev);
158 unbind_from_irqhandler(dev->irq, dev);
160 free_page((unsigned long)dev->info);
166 static void __exit xenkbd_cleanup(void)
168 input_unregister_device(xenkbd_dev->dev);
169 unbind_from_irqhandler(xenkbd_dev->irq, xenkbd_dev);
170 free_page((unsigned long)xenkbd_dev->info);
175 module_init(xenkbd_init);
176 module_exit(xenkbd_cleanup);
178 MODULE_LICENSE("GPL");