|
@@ -41,6 +41,7 @@ struct evdev {
|
|
|
struct evdev_client {
|
|
|
unsigned int head;
|
|
|
unsigned int tail;
|
|
|
+ unsigned int packet_head; /* [future] position of the first element of next packet */
|
|
|
spinlock_t buffer_lock; /* protects access to buffer, head and tail */
|
|
|
struct fasync_struct *fasync;
|
|
|
struct evdev *evdev;
|
|
@@ -72,12 +73,16 @@ static void evdev_pass_event(struct evdev_client *client,
|
|
|
client->buffer[client->tail].type = EV_SYN;
|
|
|
client->buffer[client->tail].code = SYN_DROPPED;
|
|
|
client->buffer[client->tail].value = 0;
|
|
|
- }
|
|
|
|
|
|
- spin_unlock(&client->buffer_lock);
|
|
|
+ client->packet_head = client->tail;
|
|
|
+ }
|
|
|
|
|
|
- if (event->type == EV_SYN)
|
|
|
+ if (event->type == EV_SYN && event->code == SYN_REPORT) {
|
|
|
+ client->packet_head = client->head;
|
|
|
kill_fasync(&client->fasync, SIGIO, POLL_IN);
|
|
|
+ }
|
|
|
+
|
|
|
+ spin_unlock(&client->buffer_lock);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -387,12 +392,12 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
|
|
|
if (count < input_event_size())
|
|
|
return -EINVAL;
|
|
|
|
|
|
- if (client->head == client->tail && evdev->exist &&
|
|
|
+ if (client->packet_head == client->tail && evdev->exist &&
|
|
|
(file->f_flags & O_NONBLOCK))
|
|
|
return -EAGAIN;
|
|
|
|
|
|
retval = wait_event_interruptible(evdev->wait,
|
|
|
- client->head != client->tail || !evdev->exist);
|
|
|
+ client->packet_head != client->tail || !evdev->exist);
|
|
|
if (retval)
|
|
|
return retval;
|
|
|
|
|
@@ -421,7 +426,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
|
|
|
poll_wait(file, &evdev->wait, wait);
|
|
|
|
|
|
mask = evdev->exist ? POLLOUT | POLLWRNORM : POLLHUP | POLLERR;
|
|
|
- if (client->head != client->tail)
|
|
|
+ if (client->packet_head != client->tail)
|
|
|
mask |= POLLIN | POLLRDNORM;
|
|
|
|
|
|
return mask;
|