Skip to content

Commit 0ffff11

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull a few more input updates from Dmitry Torokhov: - multi-touch handling for Xen - fix for long-standing bug causing crashes in i8042 on boot - change to gpio_keys to better handle key presses during system state transition * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: i8042 - fix crash at boot time Input: gpio_keys - handle the missing key press event in resume phase Input: xen-kbdfront - add multi-touch support
2 parents dcf903d + dda5202 commit 0ffff11

File tree

3 files changed

+204
-44
lines changed

3 files changed

+204
-44
lines changed

drivers/input/keyboard/gpio_keys.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct gpio_button_data {
4848
spinlock_t lock;
4949
bool disabled;
5050
bool key_pressed;
51+
bool suspended;
5152
};
5253

5354
struct gpio_keys_drvdata {
@@ -396,8 +397,20 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
396397

397398
BUG_ON(irq != bdata->irq);
398399

399-
if (bdata->button->wakeup)
400+
if (bdata->button->wakeup) {
401+
const struct gpio_keys_button *button = bdata->button;
402+
400403
pm_stay_awake(bdata->input->dev.parent);
404+
if (bdata->suspended &&
405+
(button->type == 0 || button->type == EV_KEY)) {
406+
/*
407+
* Simulate wakeup key press in case the key has
408+
* already released by the time we got interrupt
409+
* handler to run.
410+
*/
411+
input_report_key(bdata->input, button->code, 1);
412+
}
413+
}
401414

402415
mod_delayed_work(system_wq,
403416
&bdata->work,
@@ -855,6 +868,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
855868
struct gpio_button_data *bdata = &ddata->data[i];
856869
if (bdata->button->wakeup)
857870
enable_irq_wake(bdata->irq);
871+
bdata->suspended = true;
858872
}
859873
} else {
860874
mutex_lock(&input->mutex);
@@ -878,6 +892,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
878892
struct gpio_button_data *bdata = &ddata->data[i];
879893
if (bdata->button->wakeup)
880894
disable_irq_wake(bdata->irq);
895+
bdata->suspended = false;
881896
}
882897
} else {
883898
mutex_lock(&input->mutex);

drivers/input/misc/xen-kbdfront.c

Lines changed: 179 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/errno.h>
1818
#include <linux/module.h>
1919
#include <linux/input.h>
20+
#include <linux/input/mt.h>
2021
#include <linux/slab.h>
2122

2223
#include <asm/xen/hypervisor.h>
@@ -34,11 +35,14 @@
3435
struct xenkbd_info {
3536
struct input_dev *kbd;
3637
struct input_dev *ptr;
38+
struct input_dev *mtouch;
3739
struct xenkbd_page *page;
3840
int gref;
3941
int irq;
4042
struct xenbus_device *xbdev;
4143
char phys[32];
44+
/* current MT slot/contact ID we are injecting events in */
45+
int mtouch_cur_contact_id;
4246
};
4347

4448
enum { KPARAM_X, KPARAM_Y, KPARAM_CNT };
@@ -56,6 +60,112 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *);
5660
* to do that.
5761
*/
5862

63+
static void xenkbd_handle_motion_event(struct xenkbd_info *info,
64+
struct xenkbd_motion *motion)
65+
{
66+
input_report_rel(info->ptr, REL_X, motion->rel_x);
67+
input_report_rel(info->ptr, REL_Y, motion->rel_y);
68+
if (motion->rel_z)
69+
input_report_rel(info->ptr, REL_WHEEL, -motion->rel_z);
70+
input_sync(info->ptr);
71+
}
72+
73+
static void xenkbd_handle_position_event(struct xenkbd_info *info,
74+
struct xenkbd_position *pos)
75+
{
76+
input_report_abs(info->ptr, ABS_X, pos->abs_x);
77+
input_report_abs(info->ptr, ABS_Y, pos->abs_y);
78+
if (pos->rel_z)
79+
input_report_rel(info->ptr, REL_WHEEL, -pos->rel_z);
80+
input_sync(info->ptr);
81+
}
82+
83+
static void xenkbd_handle_key_event(struct xenkbd_info *info,
84+
struct xenkbd_key *key)
85+
{
86+
struct input_dev *dev;
87+
88+
if (test_bit(key->keycode, info->ptr->keybit)) {
89+
dev = info->ptr;
90+
} else if (test_bit(key->keycode, info->kbd->keybit)) {
91+
dev = info->kbd;
92+
} else {
93+
pr_warn("unhandled keycode 0x%x\n", key->keycode);
94+
return;
95+
}
96+
97+
input_report_key(dev, key->keycode, key->pressed);
98+
input_sync(dev);
99+
}
100+
101+
static void xenkbd_handle_mt_event(struct xenkbd_info *info,
102+
struct xenkbd_mtouch *mtouch)
103+
{
104+
if (unlikely(!info->mtouch))
105+
return;
106+
107+
if (mtouch->contact_id != info->mtouch_cur_contact_id) {
108+
info->mtouch_cur_contact_id = mtouch->contact_id;
109+
input_mt_slot(info->mtouch, mtouch->contact_id);
110+
}
111+
112+
switch (mtouch->event_type) {
113+
case XENKBD_MT_EV_DOWN:
114+
input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, true);
115+
/* fall through */
116+
117+
case XENKBD_MT_EV_MOTION:
118+
input_report_abs(info->mtouch, ABS_MT_POSITION_X,
119+
mtouch->u.pos.abs_x);
120+
input_report_abs(info->mtouch, ABS_MT_POSITION_Y,
121+
mtouch->u.pos.abs_y);
122+
break;
123+
124+
case XENKBD_MT_EV_SHAPE:
125+
input_report_abs(info->mtouch, ABS_MT_TOUCH_MAJOR,
126+
mtouch->u.shape.major);
127+
input_report_abs(info->mtouch, ABS_MT_TOUCH_MINOR,
128+
mtouch->u.shape.minor);
129+
break;
130+
131+
case XENKBD_MT_EV_ORIENT:
132+
input_report_abs(info->mtouch, ABS_MT_ORIENTATION,
133+
mtouch->u.orientation);
134+
break;
135+
136+
case XENKBD_MT_EV_UP:
137+
input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, false);
138+
break;
139+
140+
case XENKBD_MT_EV_SYN:
141+
input_mt_sync_frame(info->mtouch);
142+
input_sync(info->mtouch);
143+
break;
144+
}
145+
}
146+
147+
static void xenkbd_handle_event(struct xenkbd_info *info,
148+
union xenkbd_in_event *event)
149+
{
150+
switch (event->type) {
151+
case XENKBD_TYPE_MOTION:
152+
xenkbd_handle_motion_event(info, &event->motion);
153+
break;
154+
155+
case XENKBD_TYPE_KEY:
156+
xenkbd_handle_key_event(info, &event->key);
157+
break;
158+
159+
case XENKBD_TYPE_POS:
160+
xenkbd_handle_position_event(info, &event->pos);
161+
break;
162+
163+
case XENKBD_TYPE_MTOUCH:
164+
xenkbd_handle_mt_event(info, &event->mtouch);
165+
break;
166+
}
167+
}
168+
59169
static irqreturn_t input_handler(int rq, void *dev_id)
60170
{
61171
struct xenkbd_info *info = dev_id;
@@ -66,44 +176,8 @@ static irqreturn_t input_handler(int rq, void *dev_id)
66176
if (prod == page->in_cons)
67177
return IRQ_HANDLED;
68178
rmb(); /* ensure we see ring contents up to prod */
69-
for (cons = page->in_cons; cons != prod; cons++) {
70-
union xenkbd_in_event *event;
71-
struct input_dev *dev;
72-
event = &XENKBD_IN_RING_REF(page, cons);
73-
74-
dev = info->ptr;
75-
switch (event->type) {
76-
case XENKBD_TYPE_MOTION:
77-
input_report_rel(dev, REL_X, event->motion.rel_x);
78-
input_report_rel(dev, REL_Y, event->motion.rel_y);
79-
if (event->motion.rel_z)
80-
input_report_rel(dev, REL_WHEEL,
81-
-event->motion.rel_z);
82-
break;
83-
case XENKBD_TYPE_KEY:
84-
dev = NULL;
85-
if (test_bit(event->key.keycode, info->kbd->keybit))
86-
dev = info->kbd;
87-
if (test_bit(event->key.keycode, info->ptr->keybit))
88-
dev = info->ptr;
89-
if (dev)
90-
input_report_key(dev, event->key.keycode,
91-
event->key.pressed);
92-
else
93-
pr_warn("unhandled keycode 0x%x\n",
94-
event->key.keycode);
95-
break;
96-
case XENKBD_TYPE_POS:
97-
input_report_abs(dev, ABS_X, event->pos.abs_x);
98-
input_report_abs(dev, ABS_Y, event->pos.abs_y);
99-
if (event->pos.rel_z)
100-
input_report_rel(dev, REL_WHEEL,
101-
-event->pos.rel_z);
102-
break;
103-
}
104-
if (dev)
105-
input_sync(dev);
106-
}
179+
for (cons = page->in_cons; cons != prod; cons++)
180+
xenkbd_handle_event(info, &XENKBD_IN_RING_REF(page, cons));
107181
mb(); /* ensure we got ring contents */
108182
page->in_cons = cons;
109183
notify_remote_via_irq(info->irq);
@@ -115,9 +189,9 @@ static int xenkbd_probe(struct xenbus_device *dev,
115189
const struct xenbus_device_id *id)
116190
{
117191
int ret, i;
118-
unsigned int abs;
192+
unsigned int abs, touch;
119193
struct xenkbd_info *info;
120-
struct input_dev *kbd, *ptr;
194+
struct input_dev *kbd, *ptr, *mtouch;
121195

122196
info = kzalloc(sizeof(*info), GFP_KERNEL);
123197
if (!info) {
@@ -152,6 +226,17 @@ static int xenkbd_probe(struct xenbus_device *dev,
152226
}
153227
}
154228

229+
touch = xenbus_read_unsigned(dev->nodename,
230+
XENKBD_FIELD_FEAT_MTOUCH, 0);
231+
if (touch) {
232+
ret = xenbus_write(XBT_NIL, dev->nodename,
233+
XENKBD_FIELD_REQ_MTOUCH, "1");
234+
if (ret) {
235+
pr_warn("xenkbd: can't request multi-touch");
236+
touch = 0;
237+
}
238+
}
239+
155240
/* keyboard */
156241
kbd = input_allocate_device();
157242
if (!kbd)
@@ -208,6 +293,58 @@ static int xenkbd_probe(struct xenbus_device *dev,
208293
}
209294
info->ptr = ptr;
210295

296+
/* multi-touch device */
297+
if (touch) {
298+
int num_cont, width, height;
299+
300+
mtouch = input_allocate_device();
301+
if (!mtouch)
302+
goto error_nomem;
303+
304+
num_cont = xenbus_read_unsigned(info->xbdev->nodename,
305+
XENKBD_FIELD_MT_NUM_CONTACTS,
306+
1);
307+
width = xenbus_read_unsigned(info->xbdev->nodename,
308+
XENKBD_FIELD_MT_WIDTH,
309+
XENFB_WIDTH);
310+
height = xenbus_read_unsigned(info->xbdev->nodename,
311+
XENKBD_FIELD_MT_HEIGHT,
312+
XENFB_HEIGHT);
313+
314+
mtouch->name = "Xen Virtual Multi-touch";
315+
mtouch->phys = info->phys;
316+
mtouch->id.bustype = BUS_PCI;
317+
mtouch->id.vendor = 0x5853;
318+
mtouch->id.product = 0xfffd;
319+
320+
input_set_abs_params(mtouch, ABS_MT_TOUCH_MAJOR,
321+
0, 255, 0, 0);
322+
input_set_abs_params(mtouch, ABS_MT_POSITION_X,
323+
0, width, 0, 0);
324+
input_set_abs_params(mtouch, ABS_MT_POSITION_Y,
325+
0, height, 0, 0);
326+
input_set_abs_params(mtouch, ABS_MT_PRESSURE,
327+
0, 255, 0, 0);
328+
329+
ret = input_mt_init_slots(mtouch, num_cont, INPUT_MT_DIRECT);
330+
if (ret) {
331+
input_free_device(mtouch);
332+
xenbus_dev_fatal(info->xbdev, ret,
333+
"input_mt_init_slots");
334+
goto error;
335+
}
336+
337+
ret = input_register_device(mtouch);
338+
if (ret) {
339+
input_free_device(mtouch);
340+
xenbus_dev_fatal(info->xbdev, ret,
341+
"input_register_device(mtouch)");
342+
goto error;
343+
}
344+
info->mtouch_cur_contact_id = -1;
345+
info->mtouch = mtouch;
346+
}
347+
211348
ret = xenkbd_connect_backend(dev, info);
212349
if (ret < 0)
213350
goto error;
@@ -240,6 +377,8 @@ static int xenkbd_remove(struct xenbus_device *dev)
240377
input_unregister_device(info->kbd);
241378
if (info->ptr)
242379
input_unregister_device(info->ptr);
380+
if (info->mtouch)
381+
input_unregister_device(info->mtouch);
243382
free_page((unsigned long)info->page);
244383
kfree(info);
245384
return 0;

drivers/input/serio/i8042.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,10 @@ static int i8042_start(struct serio *serio)
436436
{
437437
struct i8042_port *port = serio->port_data;
438438

439+
spin_lock_irq(&i8042_lock);
439440
port->exists = true;
440-
mb();
441+
spin_unlock_irq(&i8042_lock);
442+
441443
return 0;
442444
}
443445

@@ -450,16 +452,20 @@ static void i8042_stop(struct serio *serio)
450452
{
451453
struct i8042_port *port = serio->port_data;
452454

455+
spin_lock_irq(&i8042_lock);
453456
port->exists = false;
457+
port->serio = NULL;
458+
spin_unlock_irq(&i8042_lock);
454459

455460
/*
461+
* We need to make sure that interrupt handler finishes using
462+
* our serio port before we return from this function.
456463
* We synchronize with both AUX and KBD IRQs because there is
457464
* a (very unlikely) chance that AUX IRQ is raised for KBD port
458465
* and vice versa.
459466
*/
460467
synchronize_irq(I8042_AUX_IRQ);
461468
synchronize_irq(I8042_KBD_IRQ);
462-
port->serio = NULL;
463469
}
464470

465471
/*
@@ -576,7 +582,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
576582

577583
spin_unlock_irqrestore(&i8042_lock, flags);
578584

579-
if (likely(port->exists && !filtered))
585+
if (likely(serio && !filtered))
580586
serio_interrupt(serio, data, dfl);
581587

582588
out:

0 commit comments

Comments
 (0)