Loading drivers/input/keyboard/gpio_keys.c +16 −1 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ struct gpio_button_data { spinlock_t lock; bool disabled; bool key_pressed; bool suspended; }; struct gpio_keys_drvdata { Loading Loading @@ -396,8 +397,20 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) BUG_ON(irq != bdata->irq); if (bdata->button->wakeup) if (bdata->button->wakeup) { const struct gpio_keys_button *button = bdata->button; pm_stay_awake(bdata->input->dev.parent); if (bdata->suspended && (button->type == 0 || button->type == EV_KEY)) { /* * Simulate wakeup key press in case the key has * already released by the time we got interrupt * handler to run. */ input_report_key(bdata->input, button->code, 1); } } mod_delayed_work(system_wq, &bdata->work, Loading Loading @@ -855,6 +868,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev) struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup) enable_irq_wake(bdata->irq); bdata->suspended = true; } } else { mutex_lock(&input->mutex); Loading @@ -878,6 +892,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev) struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup) disable_irq_wake(bdata->irq); bdata->suspended = false; } } else { mutex_lock(&input->mutex); Loading drivers/input/misc/xen-kbdfront.c +179 −40 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <linux/module.h> #include <linux/input.h> #include <linux/input/mt.h> #include <linux/slab.h> #include <asm/xen/hypervisor.h> Loading @@ -34,11 +35,14 @@ struct xenkbd_info { struct input_dev *kbd; struct input_dev *ptr; struct input_dev *mtouch; struct xenkbd_page *page; int gref; int irq; struct xenbus_device *xbdev; char phys[32]; /* current MT slot/contact ID we are injecting events in */ int mtouch_cur_contact_id; }; enum { KPARAM_X, KPARAM_Y, KPARAM_CNT }; Loading @@ -56,54 +60,124 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *); * to do that. */ static irqreturn_t input_handler(int rq, void *dev_id) static void xenkbd_handle_motion_event(struct xenkbd_info *info, struct xenkbd_motion *motion) { struct xenkbd_info *info = dev_id; struct xenkbd_page *page = info->page; __u32 cons, prod; input_report_rel(info->ptr, REL_X, motion->rel_x); input_report_rel(info->ptr, REL_Y, motion->rel_y); if (motion->rel_z) input_report_rel(info->ptr, REL_WHEEL, -motion->rel_z); input_sync(info->ptr); } prod = page->in_prod; if (prod == page->in_cons) return IRQ_HANDLED; rmb(); /* ensure we see ring contents up to prod */ for (cons = page->in_cons; cons != prod; cons++) { union xenkbd_in_event *event; static void xenkbd_handle_position_event(struct xenkbd_info *info, struct xenkbd_position *pos) { input_report_abs(info->ptr, ABS_X, pos->abs_x); input_report_abs(info->ptr, ABS_Y, pos->abs_y); if (pos->rel_z) input_report_rel(info->ptr, REL_WHEEL, -pos->rel_z); input_sync(info->ptr); } static void xenkbd_handle_key_event(struct xenkbd_info *info, struct xenkbd_key *key) { struct input_dev *dev; event = &XENKBD_IN_RING_REF(page, cons); if (test_bit(key->keycode, info->ptr->keybit)) { dev = info->ptr; } else if (test_bit(key->keycode, info->kbd->keybit)) { dev = info->kbd; } else { pr_warn("unhandled keycode 0x%x\n", key->keycode); return; } input_report_key(dev, key->keycode, key->pressed); input_sync(dev); } static void xenkbd_handle_mt_event(struct xenkbd_info *info, struct xenkbd_mtouch *mtouch) { if (unlikely(!info->mtouch)) return; if (mtouch->contact_id != info->mtouch_cur_contact_id) { info->mtouch_cur_contact_id = mtouch->contact_id; input_mt_slot(info->mtouch, mtouch->contact_id); } switch (mtouch->event_type) { case XENKBD_MT_EV_DOWN: input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, true); /* fall through */ case XENKBD_MT_EV_MOTION: input_report_abs(info->mtouch, ABS_MT_POSITION_X, mtouch->u.pos.abs_x); input_report_abs(info->mtouch, ABS_MT_POSITION_Y, mtouch->u.pos.abs_y); break; case XENKBD_MT_EV_SHAPE: input_report_abs(info->mtouch, ABS_MT_TOUCH_MAJOR, mtouch->u.shape.major); input_report_abs(info->mtouch, ABS_MT_TOUCH_MINOR, mtouch->u.shape.minor); break; case XENKBD_MT_EV_ORIENT: input_report_abs(info->mtouch, ABS_MT_ORIENTATION, mtouch->u.orientation); break; case XENKBD_MT_EV_UP: input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, false); break; case XENKBD_MT_EV_SYN: input_mt_sync_frame(info->mtouch); input_sync(info->mtouch); break; } } static void xenkbd_handle_event(struct xenkbd_info *info, union xenkbd_in_event *event) { switch (event->type) { case XENKBD_TYPE_MOTION: input_report_rel(dev, REL_X, event->motion.rel_x); input_report_rel(dev, REL_Y, event->motion.rel_y); if (event->motion.rel_z) input_report_rel(dev, REL_WHEEL, -event->motion.rel_z); xenkbd_handle_motion_event(info, &event->motion); break; case XENKBD_TYPE_KEY: dev = NULL; if (test_bit(event->key.keycode, info->kbd->keybit)) dev = info->kbd; if (test_bit(event->key.keycode, info->ptr->keybit)) dev = info->ptr; if (dev) input_report_key(dev, event->key.keycode, event->key.pressed); else pr_warn("unhandled keycode 0x%x\n", event->key.keycode); xenkbd_handle_key_event(info, &event->key); break; case XENKBD_TYPE_POS: input_report_abs(dev, ABS_X, event->pos.abs_x); input_report_abs(dev, ABS_Y, event->pos.abs_y); if (event->pos.rel_z) input_report_rel(dev, REL_WHEEL, -event->pos.rel_z); xenkbd_handle_position_event(info, &event->pos); break; case XENKBD_TYPE_MTOUCH: xenkbd_handle_mt_event(info, &event->mtouch); break; } if (dev) input_sync(dev); } static irqreturn_t input_handler(int rq, void *dev_id) { struct xenkbd_info *info = dev_id; struct xenkbd_page *page = info->page; __u32 cons, prod; prod = page->in_prod; if (prod == page->in_cons) return IRQ_HANDLED; rmb(); /* ensure we see ring contents up to prod */ for (cons = page->in_cons; cons != prod; cons++) xenkbd_handle_event(info, &XENKBD_IN_RING_REF(page, cons)); mb(); /* ensure we got ring contents */ page->in_cons = cons; notify_remote_via_irq(info->irq); Loading @@ -115,9 +189,9 @@ static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; unsigned int abs; unsigned int abs, touch; struct xenkbd_info *info; struct input_dev *kbd, *ptr; struct input_dev *kbd, *ptr, *mtouch; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { Loading Loading @@ -152,6 +226,17 @@ static int xenkbd_probe(struct xenbus_device *dev, } } touch = xenbus_read_unsigned(dev->nodename, XENKBD_FIELD_FEAT_MTOUCH, 0); if (touch) { ret = xenbus_write(XBT_NIL, dev->nodename, XENKBD_FIELD_REQ_MTOUCH, "1"); if (ret) { pr_warn("xenkbd: can't request multi-touch"); touch = 0; } } /* keyboard */ kbd = input_allocate_device(); if (!kbd) Loading Loading @@ -208,6 +293,58 @@ static int xenkbd_probe(struct xenbus_device *dev, } info->ptr = ptr; /* multi-touch device */ if (touch) { int num_cont, width, height; mtouch = input_allocate_device(); if (!mtouch) goto error_nomem; num_cont = xenbus_read_unsigned(info->xbdev->nodename, XENKBD_FIELD_MT_NUM_CONTACTS, 1); width = xenbus_read_unsigned(info->xbdev->nodename, XENKBD_FIELD_MT_WIDTH, XENFB_WIDTH); height = xenbus_read_unsigned(info->xbdev->nodename, XENKBD_FIELD_MT_HEIGHT, XENFB_HEIGHT); mtouch->name = "Xen Virtual Multi-touch"; mtouch->phys = info->phys; mtouch->id.bustype = BUS_PCI; mtouch->id.vendor = 0x5853; mtouch->id.product = 0xfffd; input_set_abs_params(mtouch, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); input_set_abs_params(mtouch, ABS_MT_POSITION_X, 0, width, 0, 0); input_set_abs_params(mtouch, ABS_MT_POSITION_Y, 0, height, 0, 0); input_set_abs_params(mtouch, ABS_MT_PRESSURE, 0, 255, 0, 0); ret = input_mt_init_slots(mtouch, num_cont, INPUT_MT_DIRECT); if (ret) { input_free_device(mtouch); xenbus_dev_fatal(info->xbdev, ret, "input_mt_init_slots"); goto error; } ret = input_register_device(mtouch); if (ret) { input_free_device(mtouch); xenbus_dev_fatal(info->xbdev, ret, "input_register_device(mtouch)"); goto error; } info->mtouch_cur_contact_id = -1; info->mtouch = mtouch; } ret = xenkbd_connect_backend(dev, info); if (ret < 0) goto error; Loading Loading @@ -240,6 +377,8 @@ static int xenkbd_remove(struct xenbus_device *dev) input_unregister_device(info->kbd); if (info->ptr) input_unregister_device(info->ptr); if (info->mtouch) input_unregister_device(info->mtouch); free_page((unsigned long)info->page); kfree(info); return 0; Loading drivers/input/serio/i8042.c +9 −3 Original line number Diff line number Diff line Loading @@ -436,8 +436,10 @@ static int i8042_start(struct serio *serio) { struct i8042_port *port = serio->port_data; spin_lock_irq(&i8042_lock); port->exists = true; mb(); spin_unlock_irq(&i8042_lock); return 0; } Loading @@ -450,16 +452,20 @@ static void i8042_stop(struct serio *serio) { struct i8042_port *port = serio->port_data; spin_lock_irq(&i8042_lock); port->exists = false; port->serio = NULL; spin_unlock_irq(&i8042_lock); /* * We need to make sure that interrupt handler finishes using * our serio port before we return from this function. * We synchronize with both AUX and KBD IRQs because there is * a (very unlikely) chance that AUX IRQ is raised for KBD port * and vice versa. */ synchronize_irq(I8042_AUX_IRQ); synchronize_irq(I8042_KBD_IRQ); port->serio = NULL; } /* Loading Loading @@ -576,7 +582,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) spin_unlock_irqrestore(&i8042_lock, flags); if (likely(port->exists && !filtered)) if (likely(serio && !filtered)) serio_interrupt(serio, data, dfl); out: Loading Loading
drivers/input/keyboard/gpio_keys.c +16 −1 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ struct gpio_button_data { spinlock_t lock; bool disabled; bool key_pressed; bool suspended; }; struct gpio_keys_drvdata { Loading Loading @@ -396,8 +397,20 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) BUG_ON(irq != bdata->irq); if (bdata->button->wakeup) if (bdata->button->wakeup) { const struct gpio_keys_button *button = bdata->button; pm_stay_awake(bdata->input->dev.parent); if (bdata->suspended && (button->type == 0 || button->type == EV_KEY)) { /* * Simulate wakeup key press in case the key has * already released by the time we got interrupt * handler to run. */ input_report_key(bdata->input, button->code, 1); } } mod_delayed_work(system_wq, &bdata->work, Loading Loading @@ -855,6 +868,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev) struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup) enable_irq_wake(bdata->irq); bdata->suspended = true; } } else { mutex_lock(&input->mutex); Loading @@ -878,6 +892,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev) struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup) disable_irq_wake(bdata->irq); bdata->suspended = false; } } else { mutex_lock(&input->mutex); Loading
drivers/input/misc/xen-kbdfront.c +179 −40 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <linux/module.h> #include <linux/input.h> #include <linux/input/mt.h> #include <linux/slab.h> #include <asm/xen/hypervisor.h> Loading @@ -34,11 +35,14 @@ struct xenkbd_info { struct input_dev *kbd; struct input_dev *ptr; struct input_dev *mtouch; struct xenkbd_page *page; int gref; int irq; struct xenbus_device *xbdev; char phys[32]; /* current MT slot/contact ID we are injecting events in */ int mtouch_cur_contact_id; }; enum { KPARAM_X, KPARAM_Y, KPARAM_CNT }; Loading @@ -56,54 +60,124 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *); * to do that. */ static irqreturn_t input_handler(int rq, void *dev_id) static void xenkbd_handle_motion_event(struct xenkbd_info *info, struct xenkbd_motion *motion) { struct xenkbd_info *info = dev_id; struct xenkbd_page *page = info->page; __u32 cons, prod; input_report_rel(info->ptr, REL_X, motion->rel_x); input_report_rel(info->ptr, REL_Y, motion->rel_y); if (motion->rel_z) input_report_rel(info->ptr, REL_WHEEL, -motion->rel_z); input_sync(info->ptr); } prod = page->in_prod; if (prod == page->in_cons) return IRQ_HANDLED; rmb(); /* ensure we see ring contents up to prod */ for (cons = page->in_cons; cons != prod; cons++) { union xenkbd_in_event *event; static void xenkbd_handle_position_event(struct xenkbd_info *info, struct xenkbd_position *pos) { input_report_abs(info->ptr, ABS_X, pos->abs_x); input_report_abs(info->ptr, ABS_Y, pos->abs_y); if (pos->rel_z) input_report_rel(info->ptr, REL_WHEEL, -pos->rel_z); input_sync(info->ptr); } static void xenkbd_handle_key_event(struct xenkbd_info *info, struct xenkbd_key *key) { struct input_dev *dev; event = &XENKBD_IN_RING_REF(page, cons); if (test_bit(key->keycode, info->ptr->keybit)) { dev = info->ptr; } else if (test_bit(key->keycode, info->kbd->keybit)) { dev = info->kbd; } else { pr_warn("unhandled keycode 0x%x\n", key->keycode); return; } input_report_key(dev, key->keycode, key->pressed); input_sync(dev); } static void xenkbd_handle_mt_event(struct xenkbd_info *info, struct xenkbd_mtouch *mtouch) { if (unlikely(!info->mtouch)) return; if (mtouch->contact_id != info->mtouch_cur_contact_id) { info->mtouch_cur_contact_id = mtouch->contact_id; input_mt_slot(info->mtouch, mtouch->contact_id); } switch (mtouch->event_type) { case XENKBD_MT_EV_DOWN: input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, true); /* fall through */ case XENKBD_MT_EV_MOTION: input_report_abs(info->mtouch, ABS_MT_POSITION_X, mtouch->u.pos.abs_x); input_report_abs(info->mtouch, ABS_MT_POSITION_Y, mtouch->u.pos.abs_y); break; case XENKBD_MT_EV_SHAPE: input_report_abs(info->mtouch, ABS_MT_TOUCH_MAJOR, mtouch->u.shape.major); input_report_abs(info->mtouch, ABS_MT_TOUCH_MINOR, mtouch->u.shape.minor); break; case XENKBD_MT_EV_ORIENT: input_report_abs(info->mtouch, ABS_MT_ORIENTATION, mtouch->u.orientation); break; case XENKBD_MT_EV_UP: input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, false); break; case XENKBD_MT_EV_SYN: input_mt_sync_frame(info->mtouch); input_sync(info->mtouch); break; } } static void xenkbd_handle_event(struct xenkbd_info *info, union xenkbd_in_event *event) { switch (event->type) { case XENKBD_TYPE_MOTION: input_report_rel(dev, REL_X, event->motion.rel_x); input_report_rel(dev, REL_Y, event->motion.rel_y); if (event->motion.rel_z) input_report_rel(dev, REL_WHEEL, -event->motion.rel_z); xenkbd_handle_motion_event(info, &event->motion); break; case XENKBD_TYPE_KEY: dev = NULL; if (test_bit(event->key.keycode, info->kbd->keybit)) dev = info->kbd; if (test_bit(event->key.keycode, info->ptr->keybit)) dev = info->ptr; if (dev) input_report_key(dev, event->key.keycode, event->key.pressed); else pr_warn("unhandled keycode 0x%x\n", event->key.keycode); xenkbd_handle_key_event(info, &event->key); break; case XENKBD_TYPE_POS: input_report_abs(dev, ABS_X, event->pos.abs_x); input_report_abs(dev, ABS_Y, event->pos.abs_y); if (event->pos.rel_z) input_report_rel(dev, REL_WHEEL, -event->pos.rel_z); xenkbd_handle_position_event(info, &event->pos); break; case XENKBD_TYPE_MTOUCH: xenkbd_handle_mt_event(info, &event->mtouch); break; } if (dev) input_sync(dev); } static irqreturn_t input_handler(int rq, void *dev_id) { struct xenkbd_info *info = dev_id; struct xenkbd_page *page = info->page; __u32 cons, prod; prod = page->in_prod; if (prod == page->in_cons) return IRQ_HANDLED; rmb(); /* ensure we see ring contents up to prod */ for (cons = page->in_cons; cons != prod; cons++) xenkbd_handle_event(info, &XENKBD_IN_RING_REF(page, cons)); mb(); /* ensure we got ring contents */ page->in_cons = cons; notify_remote_via_irq(info->irq); Loading @@ -115,9 +189,9 @@ static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; unsigned int abs; unsigned int abs, touch; struct xenkbd_info *info; struct input_dev *kbd, *ptr; struct input_dev *kbd, *ptr, *mtouch; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { Loading Loading @@ -152,6 +226,17 @@ static int xenkbd_probe(struct xenbus_device *dev, } } touch = xenbus_read_unsigned(dev->nodename, XENKBD_FIELD_FEAT_MTOUCH, 0); if (touch) { ret = xenbus_write(XBT_NIL, dev->nodename, XENKBD_FIELD_REQ_MTOUCH, "1"); if (ret) { pr_warn("xenkbd: can't request multi-touch"); touch = 0; } } /* keyboard */ kbd = input_allocate_device(); if (!kbd) Loading Loading @@ -208,6 +293,58 @@ static int xenkbd_probe(struct xenbus_device *dev, } info->ptr = ptr; /* multi-touch device */ if (touch) { int num_cont, width, height; mtouch = input_allocate_device(); if (!mtouch) goto error_nomem; num_cont = xenbus_read_unsigned(info->xbdev->nodename, XENKBD_FIELD_MT_NUM_CONTACTS, 1); width = xenbus_read_unsigned(info->xbdev->nodename, XENKBD_FIELD_MT_WIDTH, XENFB_WIDTH); height = xenbus_read_unsigned(info->xbdev->nodename, XENKBD_FIELD_MT_HEIGHT, XENFB_HEIGHT); mtouch->name = "Xen Virtual Multi-touch"; mtouch->phys = info->phys; mtouch->id.bustype = BUS_PCI; mtouch->id.vendor = 0x5853; mtouch->id.product = 0xfffd; input_set_abs_params(mtouch, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); input_set_abs_params(mtouch, ABS_MT_POSITION_X, 0, width, 0, 0); input_set_abs_params(mtouch, ABS_MT_POSITION_Y, 0, height, 0, 0); input_set_abs_params(mtouch, ABS_MT_PRESSURE, 0, 255, 0, 0); ret = input_mt_init_slots(mtouch, num_cont, INPUT_MT_DIRECT); if (ret) { input_free_device(mtouch); xenbus_dev_fatal(info->xbdev, ret, "input_mt_init_slots"); goto error; } ret = input_register_device(mtouch); if (ret) { input_free_device(mtouch); xenbus_dev_fatal(info->xbdev, ret, "input_register_device(mtouch)"); goto error; } info->mtouch_cur_contact_id = -1; info->mtouch = mtouch; } ret = xenkbd_connect_backend(dev, info); if (ret < 0) goto error; Loading Loading @@ -240,6 +377,8 @@ static int xenkbd_remove(struct xenbus_device *dev) input_unregister_device(info->kbd); if (info->ptr) input_unregister_device(info->ptr); if (info->mtouch) input_unregister_device(info->mtouch); free_page((unsigned long)info->page); kfree(info); return 0; Loading
drivers/input/serio/i8042.c +9 −3 Original line number Diff line number Diff line Loading @@ -436,8 +436,10 @@ static int i8042_start(struct serio *serio) { struct i8042_port *port = serio->port_data; spin_lock_irq(&i8042_lock); port->exists = true; mb(); spin_unlock_irq(&i8042_lock); return 0; } Loading @@ -450,16 +452,20 @@ static void i8042_stop(struct serio *serio) { struct i8042_port *port = serio->port_data; spin_lock_irq(&i8042_lock); port->exists = false; port->serio = NULL; spin_unlock_irq(&i8042_lock); /* * We need to make sure that interrupt handler finishes using * our serio port before we return from this function. * We synchronize with both AUX and KBD IRQs because there is * a (very unlikely) chance that AUX IRQ is raised for KBD port * and vice versa. */ synchronize_irq(I8042_AUX_IRQ); synchronize_irq(I8042_KBD_IRQ); port->serio = NULL; } /* Loading Loading @@ -576,7 +582,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) spin_unlock_irqrestore(&i8042_lock, flags); if (likely(port->exists && !filtered)) if (likely(serio && !filtered)) serio_interrupt(serio, data, dfl); out: Loading