Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Xen para-virtual input device
0003  *
0004  * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
0005  * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
0006  *
0007  *  Based on linux/drivers/input/mouse/sermouse.c
0008  *
0009  *  This file is subject to the terms and conditions of the GNU General Public
0010  *  License. See the file COPYING in the main directory of this archive for
0011  *  more details.
0012  */
0013 
0014 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0015 
0016 #include <linux/kernel.h>
0017 #include <linux/errno.h>
0018 #include <linux/module.h>
0019 #include <linux/input.h>
0020 #include <linux/input/mt.h>
0021 #include <linux/slab.h>
0022 
0023 #include <asm/xen/hypervisor.h>
0024 
0025 #include <xen/xen.h>
0026 #include <xen/events.h>
0027 #include <xen/page.h>
0028 #include <xen/grant_table.h>
0029 #include <xen/interface/grant_table.h>
0030 #include <xen/interface/io/fbif.h>
0031 #include <xen/interface/io/kbdif.h>
0032 #include <xen/xenbus.h>
0033 #include <xen/platform_pci.h>
0034 
0035 struct xenkbd_info {
0036     struct input_dev *kbd;
0037     struct input_dev *ptr;
0038     struct input_dev *mtouch;
0039     struct xenkbd_page *page;
0040     int gref;
0041     int irq;
0042     struct xenbus_device *xbdev;
0043     char phys[32];
0044     /* current MT slot/contact ID we are injecting events in */
0045     int mtouch_cur_contact_id;
0046 };
0047 
0048 enum { KPARAM_X, KPARAM_Y, KPARAM_CNT };
0049 static int ptr_size[KPARAM_CNT] = { XENFB_WIDTH, XENFB_HEIGHT };
0050 module_param_array(ptr_size, int, NULL, 0444);
0051 MODULE_PARM_DESC(ptr_size,
0052     "Pointing device width, height in pixels (default 800,600)");
0053 
0054 static int xenkbd_remove(struct xenbus_device *);
0055 static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
0056 static void xenkbd_disconnect_backend(struct xenkbd_info *);
0057 
0058 /*
0059  * Note: if you need to send out events, see xenfb_do_update() for how
0060  * to do that.
0061  */
0062 
0063 static void xenkbd_handle_motion_event(struct xenkbd_info *info,
0064                        struct xenkbd_motion *motion)
0065 {
0066     if (unlikely(!info->ptr))
0067         return;
0068 
0069     input_report_rel(info->ptr, REL_X, motion->rel_x);
0070     input_report_rel(info->ptr, REL_Y, motion->rel_y);
0071     if (motion->rel_z)
0072         input_report_rel(info->ptr, REL_WHEEL, -motion->rel_z);
0073     input_sync(info->ptr);
0074 }
0075 
0076 static void xenkbd_handle_position_event(struct xenkbd_info *info,
0077                      struct xenkbd_position *pos)
0078 {
0079     if (unlikely(!info->ptr))
0080         return;
0081 
0082     input_report_abs(info->ptr, ABS_X, pos->abs_x);
0083     input_report_abs(info->ptr, ABS_Y, pos->abs_y);
0084     if (pos->rel_z)
0085         input_report_rel(info->ptr, REL_WHEEL, -pos->rel_z);
0086     input_sync(info->ptr);
0087 }
0088 
0089 static void xenkbd_handle_key_event(struct xenkbd_info *info,
0090                     struct xenkbd_key *key)
0091 {
0092     struct input_dev *dev;
0093     int value = key->pressed;
0094 
0095     if (test_bit(key->keycode, info->ptr->keybit)) {
0096         dev = info->ptr;
0097     } else if (test_bit(key->keycode, info->kbd->keybit)) {
0098         dev = info->kbd;
0099         if (key->pressed && test_bit(key->keycode, info->kbd->key))
0100             value = 2; /* Mark as autorepeat */
0101     } else {
0102         pr_warn("unhandled keycode 0x%x\n", key->keycode);
0103         return;
0104     }
0105 
0106     if (unlikely(!dev))
0107         return;
0108 
0109     input_event(dev, EV_KEY, key->keycode, value);
0110     input_sync(dev);
0111 }
0112 
0113 static void xenkbd_handle_mt_event(struct xenkbd_info *info,
0114                    struct xenkbd_mtouch *mtouch)
0115 {
0116     if (unlikely(!info->mtouch))
0117         return;
0118 
0119     if (mtouch->contact_id != info->mtouch_cur_contact_id) {
0120         info->mtouch_cur_contact_id = mtouch->contact_id;
0121         input_mt_slot(info->mtouch, mtouch->contact_id);
0122     }
0123 
0124     switch (mtouch->event_type) {
0125     case XENKBD_MT_EV_DOWN:
0126         input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, true);
0127         fallthrough;
0128 
0129     case XENKBD_MT_EV_MOTION:
0130         input_report_abs(info->mtouch, ABS_MT_POSITION_X,
0131                  mtouch->u.pos.abs_x);
0132         input_report_abs(info->mtouch, ABS_MT_POSITION_Y,
0133                  mtouch->u.pos.abs_y);
0134         break;
0135 
0136     case XENKBD_MT_EV_SHAPE:
0137         input_report_abs(info->mtouch, ABS_MT_TOUCH_MAJOR,
0138                  mtouch->u.shape.major);
0139         input_report_abs(info->mtouch, ABS_MT_TOUCH_MINOR,
0140                  mtouch->u.shape.minor);
0141         break;
0142 
0143     case XENKBD_MT_EV_ORIENT:
0144         input_report_abs(info->mtouch, ABS_MT_ORIENTATION,
0145                  mtouch->u.orientation);
0146         break;
0147 
0148     case XENKBD_MT_EV_UP:
0149         input_mt_report_slot_inactive(info->mtouch);
0150         break;
0151 
0152     case XENKBD_MT_EV_SYN:
0153         input_mt_sync_frame(info->mtouch);
0154         input_sync(info->mtouch);
0155         break;
0156     }
0157 }
0158 
0159 static void xenkbd_handle_event(struct xenkbd_info *info,
0160                 union xenkbd_in_event *event)
0161 {
0162     switch (event->type) {
0163     case XENKBD_TYPE_MOTION:
0164         xenkbd_handle_motion_event(info, &event->motion);
0165         break;
0166 
0167     case XENKBD_TYPE_KEY:
0168         xenkbd_handle_key_event(info, &event->key);
0169         break;
0170 
0171     case XENKBD_TYPE_POS:
0172         xenkbd_handle_position_event(info, &event->pos);
0173         break;
0174 
0175     case XENKBD_TYPE_MTOUCH:
0176         xenkbd_handle_mt_event(info, &event->mtouch);
0177         break;
0178     }
0179 }
0180 
0181 static irqreturn_t input_handler(int rq, void *dev_id)
0182 {
0183     struct xenkbd_info *info = dev_id;
0184     struct xenkbd_page *page = info->page;
0185     __u32 cons, prod;
0186 
0187     prod = page->in_prod;
0188     if (prod == page->in_cons)
0189         return IRQ_HANDLED;
0190     rmb();          /* ensure we see ring contents up to prod */
0191     for (cons = page->in_cons; cons != prod; cons++)
0192         xenkbd_handle_event(info, &XENKBD_IN_RING_REF(page, cons));
0193     mb();           /* ensure we got ring contents */
0194     page->in_cons = cons;
0195     notify_remote_via_irq(info->irq);
0196 
0197     return IRQ_HANDLED;
0198 }
0199 
0200 static int xenkbd_probe(struct xenbus_device *dev,
0201                   const struct xenbus_device_id *id)
0202 {
0203     int ret, i;
0204     bool with_mtouch, with_kbd, with_ptr;
0205     struct xenkbd_info *info;
0206     struct input_dev *kbd, *ptr, *mtouch;
0207 
0208     info = kzalloc(sizeof(*info), GFP_KERNEL);
0209     if (!info) {
0210         xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
0211         return -ENOMEM;
0212     }
0213     dev_set_drvdata(&dev->dev, info);
0214     info->xbdev = dev;
0215     info->irq = -1;
0216     info->gref = -1;
0217     snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
0218 
0219     info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
0220     if (!info->page)
0221         goto error_nomem;
0222 
0223     /*
0224      * The below are reverse logic, e.g. if the feature is set, then
0225      * do not expose the corresponding virtual device.
0226      */
0227     with_kbd = !xenbus_read_unsigned(dev->otherend,
0228                      XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0);
0229 
0230     with_ptr = !xenbus_read_unsigned(dev->otherend,
0231                      XENKBD_FIELD_FEAT_DSBL_POINTER, 0);
0232 
0233     /* Direct logic: if set, then create multi-touch device. */
0234     with_mtouch = xenbus_read_unsigned(dev->otherend,
0235                        XENKBD_FIELD_FEAT_MTOUCH, 0);
0236     if (with_mtouch) {
0237         ret = xenbus_write(XBT_NIL, dev->nodename,
0238                    XENKBD_FIELD_REQ_MTOUCH, "1");
0239         if (ret) {
0240             pr_warn("xenkbd: can't request multi-touch");
0241             with_mtouch = 0;
0242         }
0243     }
0244 
0245     /* keyboard */
0246     if (with_kbd) {
0247         kbd = input_allocate_device();
0248         if (!kbd)
0249             goto error_nomem;
0250         kbd->name = "Xen Virtual Keyboard";
0251         kbd->phys = info->phys;
0252         kbd->id.bustype = BUS_PCI;
0253         kbd->id.vendor = 0x5853;
0254         kbd->id.product = 0xffff;
0255 
0256         __set_bit(EV_KEY, kbd->evbit);
0257         for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
0258             __set_bit(i, kbd->keybit);
0259         for (i = KEY_OK; i < KEY_MAX; i++)
0260             __set_bit(i, kbd->keybit);
0261 
0262         ret = input_register_device(kbd);
0263         if (ret) {
0264             input_free_device(kbd);
0265             xenbus_dev_fatal(dev, ret,
0266                      "input_register_device(kbd)");
0267             goto error;
0268         }
0269         info->kbd = kbd;
0270     }
0271 
0272     /* pointing device */
0273     if (with_ptr) {
0274         unsigned int abs;
0275 
0276         /* Set input abs params to match backend screen res */
0277         abs = xenbus_read_unsigned(dev->otherend,
0278                        XENKBD_FIELD_FEAT_ABS_POINTER, 0);
0279         ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend,
0280                               XENKBD_FIELD_WIDTH,
0281                               ptr_size[KPARAM_X]);
0282         ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend,
0283                               XENKBD_FIELD_HEIGHT,
0284                               ptr_size[KPARAM_Y]);
0285         if (abs) {
0286             ret = xenbus_write(XBT_NIL, dev->nodename,
0287                        XENKBD_FIELD_REQ_ABS_POINTER, "1");
0288             if (ret) {
0289                 pr_warn("xenkbd: can't request abs-pointer\n");
0290                 abs = 0;
0291             }
0292         }
0293 
0294         ptr = input_allocate_device();
0295         if (!ptr)
0296             goto error_nomem;
0297         ptr->name = "Xen Virtual Pointer";
0298         ptr->phys = info->phys;
0299         ptr->id.bustype = BUS_PCI;
0300         ptr->id.vendor = 0x5853;
0301         ptr->id.product = 0xfffe;
0302 
0303         if (abs) {
0304             __set_bit(EV_ABS, ptr->evbit);
0305             input_set_abs_params(ptr, ABS_X, 0,
0306                          ptr_size[KPARAM_X], 0, 0);
0307             input_set_abs_params(ptr, ABS_Y, 0,
0308                          ptr_size[KPARAM_Y], 0, 0);
0309         } else {
0310             input_set_capability(ptr, EV_REL, REL_X);
0311             input_set_capability(ptr, EV_REL, REL_Y);
0312         }
0313         input_set_capability(ptr, EV_REL, REL_WHEEL);
0314 
0315         __set_bit(EV_KEY, ptr->evbit);
0316         for (i = BTN_LEFT; i <= BTN_TASK; i++)
0317             __set_bit(i, ptr->keybit);
0318 
0319         ret = input_register_device(ptr);
0320         if (ret) {
0321             input_free_device(ptr);
0322             xenbus_dev_fatal(dev, ret,
0323                      "input_register_device(ptr)");
0324             goto error;
0325         }
0326         info->ptr = ptr;
0327     }
0328 
0329     /* multi-touch device */
0330     if (with_mtouch) {
0331         int num_cont, width, height;
0332 
0333         mtouch = input_allocate_device();
0334         if (!mtouch)
0335             goto error_nomem;
0336 
0337         num_cont = xenbus_read_unsigned(info->xbdev->otherend,
0338                         XENKBD_FIELD_MT_NUM_CONTACTS,
0339                         1);
0340         width = xenbus_read_unsigned(info->xbdev->otherend,
0341                          XENKBD_FIELD_MT_WIDTH,
0342                          XENFB_WIDTH);
0343         height = xenbus_read_unsigned(info->xbdev->otherend,
0344                           XENKBD_FIELD_MT_HEIGHT,
0345                           XENFB_HEIGHT);
0346 
0347         mtouch->name = "Xen Virtual Multi-touch";
0348         mtouch->phys = info->phys;
0349         mtouch->id.bustype = BUS_PCI;
0350         mtouch->id.vendor = 0x5853;
0351         mtouch->id.product = 0xfffd;
0352 
0353         input_set_abs_params(mtouch, ABS_MT_TOUCH_MAJOR,
0354                      0, 255, 0, 0);
0355         input_set_abs_params(mtouch, ABS_MT_POSITION_X,
0356                      0, width, 0, 0);
0357         input_set_abs_params(mtouch, ABS_MT_POSITION_Y,
0358                      0, height, 0, 0);
0359 
0360         ret = input_mt_init_slots(mtouch, num_cont, INPUT_MT_DIRECT);
0361         if (ret) {
0362             input_free_device(mtouch);
0363             xenbus_dev_fatal(info->xbdev, ret,
0364                      "input_mt_init_slots");
0365             goto error;
0366         }
0367 
0368         ret = input_register_device(mtouch);
0369         if (ret) {
0370             input_free_device(mtouch);
0371             xenbus_dev_fatal(info->xbdev, ret,
0372                      "input_register_device(mtouch)");
0373             goto error;
0374         }
0375         info->mtouch_cur_contact_id = -1;
0376         info->mtouch = mtouch;
0377     }
0378 
0379     if (!(with_kbd || with_ptr || with_mtouch)) {
0380         ret = -ENXIO;
0381         goto error;
0382     }
0383 
0384     ret = xenkbd_connect_backend(dev, info);
0385     if (ret < 0)
0386         goto error;
0387 
0388     return 0;
0389 
0390  error_nomem:
0391     ret = -ENOMEM;
0392     xenbus_dev_fatal(dev, ret, "allocating device memory");
0393  error:
0394     xenkbd_remove(dev);
0395     return ret;
0396 }
0397 
0398 static int xenkbd_resume(struct xenbus_device *dev)
0399 {
0400     struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
0401 
0402     xenkbd_disconnect_backend(info);
0403     memset(info->page, 0, PAGE_SIZE);
0404     return xenkbd_connect_backend(dev, info);
0405 }
0406 
0407 static int xenkbd_remove(struct xenbus_device *dev)
0408 {
0409     struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
0410 
0411     xenkbd_disconnect_backend(info);
0412     if (info->kbd)
0413         input_unregister_device(info->kbd);
0414     if (info->ptr)
0415         input_unregister_device(info->ptr);
0416     if (info->mtouch)
0417         input_unregister_device(info->mtouch);
0418     free_page((unsigned long)info->page);
0419     kfree(info);
0420     return 0;
0421 }
0422 
0423 static int xenkbd_connect_backend(struct xenbus_device *dev,
0424                   struct xenkbd_info *info)
0425 {
0426     int ret, evtchn;
0427     struct xenbus_transaction xbt;
0428 
0429     ret = gnttab_grant_foreign_access(dev->otherend_id,
0430                                       virt_to_gfn(info->page), 0);
0431     if (ret < 0)
0432         return ret;
0433     info->gref = ret;
0434 
0435     ret = xenbus_alloc_evtchn(dev, &evtchn);
0436     if (ret)
0437         goto error_grant;
0438     ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
0439                     0, dev->devicetype, info);
0440     if (ret < 0) {
0441         xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
0442         goto error_evtchan;
0443     }
0444     info->irq = ret;
0445 
0446  again:
0447     ret = xenbus_transaction_start(&xbt);
0448     if (ret) {
0449         xenbus_dev_fatal(dev, ret, "starting transaction");
0450         goto error_irqh;
0451     }
0452     ret = xenbus_printf(xbt, dev->nodename, XENKBD_FIELD_RING_REF, "%lu",
0453                 virt_to_gfn(info->page));
0454     if (ret)
0455         goto error_xenbus;
0456     ret = xenbus_printf(xbt, dev->nodename, XENKBD_FIELD_RING_GREF,
0457                 "%u", info->gref);
0458     if (ret)
0459         goto error_xenbus;
0460     ret = xenbus_printf(xbt, dev->nodename, XENKBD_FIELD_EVT_CHANNEL, "%u",
0461                 evtchn);
0462     if (ret)
0463         goto error_xenbus;
0464     ret = xenbus_transaction_end(xbt, 0);
0465     if (ret) {
0466         if (ret == -EAGAIN)
0467             goto again;
0468         xenbus_dev_fatal(dev, ret, "completing transaction");
0469         goto error_irqh;
0470     }
0471 
0472     xenbus_switch_state(dev, XenbusStateInitialised);
0473     return 0;
0474 
0475  error_xenbus:
0476     xenbus_transaction_end(xbt, 1);
0477     xenbus_dev_fatal(dev, ret, "writing xenstore");
0478  error_irqh:
0479     unbind_from_irqhandler(info->irq, info);
0480     info->irq = -1;
0481  error_evtchan:
0482     xenbus_free_evtchn(dev, evtchn);
0483  error_grant:
0484     gnttab_end_foreign_access(info->gref, NULL);
0485     info->gref = -1;
0486     return ret;
0487 }
0488 
0489 static void xenkbd_disconnect_backend(struct xenkbd_info *info)
0490 {
0491     if (info->irq >= 0)
0492         unbind_from_irqhandler(info->irq, info);
0493     info->irq = -1;
0494     if (info->gref >= 0)
0495         gnttab_end_foreign_access(info->gref, NULL);
0496     info->gref = -1;
0497 }
0498 
0499 static void xenkbd_backend_changed(struct xenbus_device *dev,
0500                    enum xenbus_state backend_state)
0501 {
0502     switch (backend_state) {
0503     case XenbusStateInitialising:
0504     case XenbusStateInitialised:
0505     case XenbusStateReconfiguring:
0506     case XenbusStateReconfigured:
0507     case XenbusStateUnknown:
0508         break;
0509 
0510     case XenbusStateInitWait:
0511         xenbus_switch_state(dev, XenbusStateConnected);
0512         break;
0513 
0514     case XenbusStateConnected:
0515         /*
0516          * Work around xenbus race condition: If backend goes
0517          * through InitWait to Connected fast enough, we can
0518          * get Connected twice here.
0519          */
0520         if (dev->state != XenbusStateConnected)
0521             xenbus_switch_state(dev, XenbusStateConnected);
0522         break;
0523 
0524     case XenbusStateClosed:
0525         if (dev->state == XenbusStateClosed)
0526             break;
0527         fallthrough;    /* Missed the backend's CLOSING state */
0528     case XenbusStateClosing:
0529         xenbus_frontend_closed(dev);
0530         break;
0531     }
0532 }
0533 
0534 static const struct xenbus_device_id xenkbd_ids[] = {
0535     { XENKBD_DRIVER_NAME },
0536     { "" }
0537 };
0538 
0539 static struct xenbus_driver xenkbd_driver = {
0540     .ids = xenkbd_ids,
0541     .probe = xenkbd_probe,
0542     .remove = xenkbd_remove,
0543     .resume = xenkbd_resume,
0544     .otherend_changed = xenkbd_backend_changed,
0545     .not_essential = true,
0546 };
0547 
0548 static int __init xenkbd_init(void)
0549 {
0550     if (!xen_domain())
0551         return -ENODEV;
0552 
0553     /* Nothing to do if running in dom0. */
0554     if (xen_initial_domain())
0555         return -ENODEV;
0556 
0557     if (!xen_has_pv_devices())
0558         return -ENODEV;
0559 
0560     return xenbus_register_frontend(&xenkbd_driver);
0561 }
0562 
0563 static void __exit xenkbd_cleanup(void)
0564 {
0565     xenbus_unregister_driver(&xenkbd_driver);
0566 }
0567 
0568 module_init(xenkbd_init);
0569 module_exit(xenkbd_cleanup);
0570 
0571 MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
0572 MODULE_LICENSE("GPL");
0573 MODULE_ALIAS("xen:" XENKBD_DRIVER_NAME);