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