aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/evdev.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 88d8e4cb419..75c4e868303 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -41,6 +41,7 @@ struct evdev {
41struct evdev_client { 41struct evdev_client {
42 unsigned int head; 42 unsigned int head;
43 unsigned int tail; 43 unsigned int tail;
44 unsigned int packet_head; /* [future] position of the first element of next packet */
44 spinlock_t buffer_lock; /* protects access to buffer, head and tail */ 45 spinlock_t buffer_lock; /* protects access to buffer, head and tail */
45 struct fasync_struct *fasync; 46 struct fasync_struct *fasync;
46 struct evdev *evdev; 47 struct evdev *evdev;
@@ -72,12 +73,16 @@ static void evdev_pass_event(struct evdev_client *client,
72 client->buffer[client->tail].type = EV_SYN; 73 client->buffer[client->tail].type = EV_SYN;
73 client->buffer[client->tail].code = SYN_DROPPED; 74 client->buffer[client->tail].code = SYN_DROPPED;
74 client->buffer[client->tail].value = 0; 75 client->buffer[client->tail].value = 0;
75 }
76 76
77 spin_unlock(&client->buffer_lock); 77 client->packet_head = client->tail;
78 }
78 79
79 if (event->type == EV_SYN) 80 if (event->type == EV_SYN && event->code == SYN_REPORT) {
81 client->packet_head = client->head;
80 kill_fasync(&client->fasync, SIGIO, POLL_IN); 82 kill_fasync(&client->fasync, SIGIO, POLL_IN);
83 }
84
85 spin_unlock(&client->buffer_lock);
81} 86}
82 87
83/* 88/*
@@ -387,12 +392,12 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
387 if (count < input_event_size()) 392 if (count < input_event_size())
388 return -EINVAL; 393 return -EINVAL;
389 394
390 if (client->head == client->tail && evdev->exist && 395 if (client->packet_head == client->tail && evdev->exist &&
391 (file->f_flags & O_NONBLOCK)) 396 (file->f_flags & O_NONBLOCK))
392 return -EAGAIN; 397 return -EAGAIN;
393 398
394 retval = wait_event_interruptible(evdev->wait, 399 retval = wait_event_interruptible(evdev->wait,
395 client->head != client->tail || !evdev->exist); 400 client->packet_head != client->tail || !evdev->exist);
396 if (retval) 401 if (retval)
397 return retval; 402 return retval;
398 403
@@ -421,7 +426,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
421 poll_wait(file, &evdev->wait, wait); 426 poll_wait(file, &evdev->wait, wait);
422 427
423 mask = evdev->exist ? POLLOUT | POLLWRNORM : POLLHUP | POLLERR; 428 mask = evdev->exist ? POLLOUT | POLLWRNORM : POLLHUP | POLLERR;
424 if (client->head != client->tail) 429 if (client->packet_head != client->tail)
425 mask |= POLLIN | POLLRDNORM; 430 mask |= POLLIN | POLLRDNORM;
426 431
427 return mask; 432 return mask;