diff options
-rw-r--r-- | drivers/input/evdev.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 88d8e4cb419a..75c4e8683033 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -41,6 +41,7 @@ struct evdev { | |||
41 | struct evdev_client { | 41 | struct 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; |