Commit d0ffb9be authored by Dmitry Torokhov's avatar Dmitry Torokhov
Browse files

Input: handlers - rename 'list' to 'client'



The naming convention in input handlers was very confusing -
client stuctures were called lists, regular lists were also
called lists making anyone looking at the code go mad.

Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 5b2a0826
Loading
Loading
Loading
Loading
+80 −70
Original line number Diff line number Diff line
@@ -29,11 +29,11 @@ struct evdev {
	char name[16];
	struct input_handle handle;
	wait_queue_head_t wait;
	struct evdev_list *grab;
	struct list_head list;
	struct evdev_client *grab;
	struct list_head client_list;
};

struct evdev_list {
struct evdev_client {
	struct input_event buffer[EVDEV_BUFFER_SIZE];
	int head;
	int tail;
@@ -47,28 +47,28 @@ static struct evdev *evdev_table[EVDEV_MINORS];
static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
	struct evdev *evdev = handle->private;
	struct evdev_list *list;
	struct evdev_client *client;

	if (evdev->grab) {
		list = evdev->grab;
		client = evdev->grab;

		do_gettimeofday(&list->buffer[list->head].time);
		list->buffer[list->head].type = type;
		list->buffer[list->head].code = code;
		list->buffer[list->head].value = value;
		list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
		do_gettimeofday(&client->buffer[client->head].time);
		client->buffer[client->head].type = type;
		client->buffer[client->head].code = code;
		client->buffer[client->head].value = value;
		client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);

		kill_fasync(&list->fasync, SIGIO, POLL_IN);
		kill_fasync(&client->fasync, SIGIO, POLL_IN);
	} else
		list_for_each_entry(list, &evdev->list, node) {
		list_for_each_entry(client, &evdev->client_list, node) {

			do_gettimeofday(&list->buffer[list->head].time);
			list->buffer[list->head].type = type;
			list->buffer[list->head].code = code;
			list->buffer[list->head].value = value;
			list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
			do_gettimeofday(&client->buffer[client->head].time);
			client->buffer[client->head].type = type;
			client->buffer[client->head].code = code;
			client->buffer[client->head].value = value;
			client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);

			kill_fasync(&list->fasync, SIGIO, POLL_IN);
			kill_fasync(&client->fasync, SIGIO, POLL_IN);
		}

	wake_up_interruptible(&evdev->wait);
@@ -76,22 +76,23 @@ static void evdev_event(struct input_handle *handle, unsigned int type, unsigned

static int evdev_fasync(int fd, struct file *file, int on)
{
	struct evdev_client *client = file->private_data;
	int retval;
	struct evdev_list *list = file->private_data;

	retval = fasync_helper(fd, file, on, &list->fasync);
	retval = fasync_helper(fd, file, on, &client->fasync);

	return retval < 0 ? retval : 0;
}

static int evdev_flush(struct file *file, fl_owner_t id)
{
	struct evdev_list *list = file->private_data;
	struct evdev_client *client = file->private_data;
	struct evdev *evdev = client->evdev;

	if (!list->evdev->exist)
	if (!evdev->exist)
		return -ENODEV;

	return input_flush_device(&list->evdev->handle, file);
	return input_flush_device(&evdev->handle, file);
}

static void evdev_free(struct evdev *evdev)
@@ -102,46 +103,53 @@ static void evdev_free(struct evdev *evdev)

static int evdev_release(struct inode *inode, struct file *file)
{
	struct evdev_list *list = file->private_data;
	struct evdev_client *client = file->private_data;
	struct evdev *evdev = client->evdev;

	if (list->evdev->grab == list) {
		input_release_device(&list->evdev->handle);
		list->evdev->grab = NULL;
	if (evdev->grab == client) {
		input_release_device(&evdev->handle);
		evdev->grab = NULL;
	}

	evdev_fasync(-1, file, 0);
	list_del(&list->node);
	list_del(&client->node);
	kfree(client);

	if (!--list->evdev->open) {
		if (list->evdev->exist)
			input_close_device(&list->evdev->handle);
	if (!--evdev->open) {
		if (evdev->exist)
			input_close_device(&evdev->handle);
		else
			evdev_free(list->evdev);
			evdev_free(evdev);
	}

	kfree(list);
	return 0;
}

static int evdev_open(struct inode *inode, struct file *file)
{
	struct evdev_list *list;
	struct evdev_client *client;
	struct evdev *evdev;
	int i = iminor(inode) - EVDEV_MINOR_BASE;

	if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
	if (i >= EVDEV_MINORS)
		return -ENODEV;

	if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
	evdev = evdev_table[i];

	if (!evdev || !evdev->exist)
		return -ENODEV;

	client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
	if (!client)
		return -ENOMEM;

	list->evdev = evdev_table[i];
	list_add_tail(&list->node, &evdev_table[i]->list);
	file->private_data = list;
	client->evdev = evdev;
	list_add_tail(&client->node, &evdev->client_list);

	if (!list->evdev->open++)
		if (list->evdev->exist)
			input_open_device(&list->evdev->handle);
	if (!evdev->open++ && evdev->exist)
		input_open_device(&evdev->handle);

	file->private_data = client;
	return 0;
}

@@ -245,18 +253,19 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev

static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
	struct evdev_list *list = file->private_data;
	struct evdev_client *client = file->private_data;
	struct evdev *evdev = client->evdev;
	struct input_event event;
	int retval = 0;

	if (!list->evdev->exist)
	if (!evdev->exist)
		return -ENODEV;

	while (retval < count) {

		if (evdev_event_from_user(buffer + retval, &event))
			return -EFAULT;
		input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
		input_inject_event(&evdev->handle, event.type, event.code, event.value);
		retval += evdev_event_size();
	}

@@ -265,32 +274,32 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_

static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
	struct evdev_list *list = file->private_data;
	struct evdev_client *client = file->private_data;
	struct evdev *evdev = client->evdev;
	int retval;

	if (count < evdev_event_size())
		return -EINVAL;

	if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
	if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))
		return -EAGAIN;

	retval = wait_event_interruptible(list->evdev->wait,
		list->head != list->tail || (!list->evdev->exist));

	retval = wait_event_interruptible(evdev->wait,
		client->head != client->tail || !evdev->exist);
	if (retval)
		return retval;

	if (!list->evdev->exist)
	if (!evdev->exist)
		return -ENODEV;

	while (list->head != list->tail && retval + evdev_event_size() <= count) {
	while (client->head != client->tail && retval + evdev_event_size() <= count) {

		struct input_event *event = (struct input_event *) list->buffer + list->tail;
		struct input_event *event = (struct input_event *) client->buffer + client->tail;

		if (evdev_event_to_user(buffer + retval, event))
			return -EFAULT;

		list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
		client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
		retval += evdev_event_size();
	}

@@ -300,11 +309,12 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count
/* No kernel lock - fine */
static unsigned int evdev_poll(struct file *file, poll_table *wait)
{
	struct evdev_list *list = file->private_data;
	struct evdev_client *client = file->private_data;
	struct evdev *evdev = client->evdev;

	poll_wait(file, &list->evdev->wait, wait);
	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
		(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
	poll_wait(file, &evdev->wait, wait);
	return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
		(evdev->exist ? 0 : (POLLHUP | POLLERR));
}

#ifdef CONFIG_COMPAT
@@ -387,8 +397,8 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
				void __user *p, int compat_mode)
{
	struct evdev_list *list = file->private_data;
	struct evdev *evdev = list->evdev;
	struct evdev_client *client = file->private_data;
	struct evdev *evdev = client->evdev;
	struct input_dev *dev = evdev->handle.dev;
	struct input_absinfo abs;
	struct ff_effect effect;
@@ -476,10 +486,10 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
					return -EBUSY;
				if (input_grab_device(&evdev->handle))
					return -EBUSY;
				evdev->grab = list;
				evdev->grab = client;
				return 0;
			} else {
				if (evdev->grab != list)
				if (evdev->grab != client)
					return -EINVAL;
				input_release_device(&evdev->handle);
				evdev->grab = NULL;
@@ -624,7 +634,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
	if (!evdev)
		return -ENOMEM;

	INIT_LIST_HEAD(&evdev->list);
	INIT_LIST_HEAD(&evdev->client_list);
	init_waitqueue_head(&evdev->wait);

	evdev->exist = 1;
@@ -671,7 +681,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
static void evdev_disconnect(struct input_handle *handle)
{
	struct evdev *evdev = handle->private;
	struct evdev_list *list;
	struct evdev_client *client;

	input_unregister_handle(handle);

@@ -684,8 +694,8 @@ static void evdev_disconnect(struct input_handle *handle)
		input_flush_device(handle, NULL);
		input_close_device(handle);
		wake_up_interruptible(&evdev->wait);
		list_for_each_entry(list, &evdev->list, node)
			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
		list_for_each_entry(client, &evdev->client_list, node)
			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
	} else
		evdev_free(evdev);
}
+68 −62
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ struct joydev {
	char name[16];
	struct input_handle handle;
	wait_queue_head_t wait;
	struct list_head list;
	struct list_head client_list;
	struct js_corr corr[ABS_MAX + 1];
	struct JS_DATA_SAVE_TYPE glue;
	int nabs;
@@ -55,7 +55,7 @@ struct joydev {
	__s16 abs[ABS_MAX + 1];
};

struct joydev_list {
struct joydev_client {
	struct js_event buffer[JOYDEV_BUFFER_SIZE];
	int head;
	int tail;
@@ -87,7 +87,7 @@ static int joydev_correct(int value, struct js_corr *corr)
static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
	struct joydev *joydev = handle->private;
	struct joydev_list *list;
	struct joydev_client *client;
	struct js_event event;

	switch (type) {
@@ -115,15 +115,15 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne

	event.time = jiffies_to_msecs(jiffies);

	list_for_each_entry(list, &joydev->list, node) {
	list_for_each_entry(client, &joydev->client_list, node) {

		memcpy(list->buffer + list->head, &event, sizeof(struct js_event));
		memcpy(client->buffer + client->head, &event, sizeof(struct js_event));

		if (list->startup == joydev->nabs + joydev->nkey)
			if (list->tail == (list->head = (list->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
				list->startup = 0;
		if (client->startup == joydev->nabs + joydev->nkey)
			if (client->tail == (client->head = (client->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
				client->startup = 0;

		kill_fasync(&list->fasync, SIGIO, POLL_IN);
		kill_fasync(&client->fasync, SIGIO, POLL_IN);
	}

	wake_up_interruptible(&joydev->wait);
@@ -132,9 +132,9 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne
static int joydev_fasync(int fd, struct file *file, int on)
{
	int retval;
	struct joydev_list *list = file->private_data;
	struct joydev_client *client = file->private_data;

	retval = fasync_helper(fd, file, on, &list->fasync);
	retval = fasync_helper(fd, file, on, &client->fasync);

	return retval < 0 ? retval : 0;
}
@@ -147,42 +147,48 @@ static void joydev_free(struct joydev *joydev)

static int joydev_release(struct inode *inode, struct file *file)
{
	struct joydev_list *list = file->private_data;
	struct joydev_client *client = file->private_data;
	struct joydev *joydev = client->joydev;

	joydev_fasync(-1, file, 0);

	list_del(&list->node);
	list_del(&client->node);
	kfree(client);

	if (!--list->joydev->open) {
		if (list->joydev->exist)
			input_close_device(&list->joydev->handle);
	if (!--joydev->open) {
		if (joydev->exist)
			input_close_device(&joydev->handle);
		else
			joydev_free(list->joydev);
			joydev_free(joydev);
	}

	kfree(list);
	return 0;
}

static int joydev_open(struct inode *inode, struct file *file)
{
	struct joydev_list *list;
	struct joydev_client *client;
	struct joydev *joydev;
	int i = iminor(inode) - JOYDEV_MINOR_BASE;

	if (i >= JOYDEV_MINORS || !joydev_table[i])
	if (i >= JOYDEV_MINORS)
		return -ENODEV;

	joydev = joydev_table[i];
	if (!joydev || !joydev->exist)
		return -ENODEV;

	if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL)))
	client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
	if (!client)
		return -ENOMEM;

	list->joydev = joydev_table[i];
	list_add_tail(&list->node, &joydev_table[i]->list);
	file->private_data = list;
	client->joydev = joydev;
	list_add_tail(&client->node, &joydev->client_list);

	if (!list->joydev->open++)
		if (list->joydev->exist)
			input_open_device(&list->joydev->handle);
	if (!joydev->open++ && joydev->exist)
		input_open_device(&joydev->handle);

	file->private_data = client;
	return 0;
}

@@ -193,12 +199,12 @@ static ssize_t joydev_write(struct file * file, const char __user * buffer, size

static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
	struct joydev_list *list = file->private_data;
	struct joydev *joydev = list->joydev;
	struct joydev_client *client = file->private_data;
	struct joydev *joydev = client->joydev;
	struct input_dev *input = joydev->handle.dev;
	int retval = 0;

	if (!list->joydev->exist)
	if (!joydev->exist)
		return -ENODEV;

	if (count < sizeof(struct js_event))
@@ -217,56 +223,55 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo
		if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
			return -EFAULT;

		list->startup = 0;
		list->tail = list->head;
		client->startup = 0;
		client->tail = client->head;

		return sizeof(struct JS_DATA_TYPE);
	}

	if (list->startup == joydev->nabs + joydev->nkey &&
	    list->head == list->tail && (file->f_flags & O_NONBLOCK))
	if (client->startup == joydev->nabs + joydev->nkey &&
	    client->head == client->tail && (file->f_flags & O_NONBLOCK))
		return -EAGAIN;

	retval = wait_event_interruptible(list->joydev->wait,
					  !list->joydev->exist ||
					  list->startup < joydev->nabs + joydev->nkey ||
					  list->head != list->tail);

	retval = wait_event_interruptible(joydev->wait,
					  !joydev->exist ||
					  client->startup < joydev->nabs + joydev->nkey ||
					  client->head != client->tail);
	if (retval)
		return retval;

	if (!list->joydev->exist)
	if (!joydev->exist)
		return -ENODEV;

	while (list->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
	while (client->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {

		struct js_event event;

		event.time = jiffies_to_msecs(jiffies);

		if (list->startup < joydev->nkey) {
		if (client->startup < joydev->nkey) {
			event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
			event.number = list->startup;
			event.number = client->startup;
			event.value = !!test_bit(joydev->keypam[event.number], input->key);
		} else {
			event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
			event.number = list->startup - joydev->nkey;
			event.number = client->startup - joydev->nkey;
			event.value = joydev->abs[event.number];
		}

		if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
			return -EFAULT;

		list->startup++;
		client->startup++;
		retval += sizeof(struct js_event);
	}

	while (list->head != list->tail && retval + sizeof(struct js_event) <= count) {
	while (client->head != client->tail && retval + sizeof(struct js_event) <= count) {

		if (copy_to_user(buf + retval, list->buffer + list->tail, sizeof(struct js_event)))
		if (copy_to_user(buf + retval, client->buffer + client->tail, sizeof(struct js_event)))
			return -EFAULT;

		list->tail = (list->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
		client->tail = (client->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
		retval += sizeof(struct js_event);
	}

@@ -276,11 +281,12 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo
/* No kernel lock - fine */
static unsigned int joydev_poll(struct file *file, poll_table *wait)
{
	struct joydev_list *list = file->private_data;
	struct joydev_client *client = file->private_data;
	struct joydev *joydev = client->joydev;

	poll_wait(file, &list->joydev->wait, wait);
	return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ?
		(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
	poll_wait(file, &joydev->wait, wait);
	return ((client->head != client->tail || client->startup < joydev->nabs + joydev->nkey) ?
		(POLLIN | POLLRDNORM) : 0) | (joydev->exist ? 0 : (POLLHUP | POLLERR));
}

static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp)
@@ -374,8 +380,8 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __u
#ifdef CONFIG_COMPAT
static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct joydev_list *list = file->private_data;
	struct joydev *joydev = list->joydev;
	struct joydev_client *client = file->private_data;
	struct joydev *joydev = client->joydev;
	void __user *argp = (void __user *)arg;
	s32 tmp32;
	struct JS_DATA_SAVE_TYPE_32 ds32;
@@ -428,8 +434,8 @@ static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo

static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	struct joydev_list *list = file->private_data;
	struct joydev *joydev = list->joydev;
	struct joydev_client *client = file->private_data;
	struct joydev *joydev = client->joydev;
	void __user *argp = (void __user *)arg;

	if (!joydev->exist)
@@ -484,7 +490,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
	if (!joydev)
		return -ENOMEM;

	INIT_LIST_HEAD(&joydev->list);
	INIT_LIST_HEAD(&joydev->client_list);
	init_waitqueue_head(&joydev->wait);

	joydev->minor = minor;
@@ -572,7 +578,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
static void joydev_disconnect(struct input_handle *handle)
{
	struct joydev *joydev = handle->private;
	struct joydev_list *list;
	struct joydev_client *client;

	input_unregister_handle(handle);

@@ -583,8 +589,8 @@ static void joydev_disconnect(struct input_handle *handle)
	if (joydev->open) {
		input_close_device(handle);
		wake_up_interruptible(&joydev->wait);
		list_for_each_entry(list, &joydev->list, node)
			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
		list_for_each_entry(client, &joydev->client_list, node)
			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
	} else
		joydev_free(joydev);
}
+122 −115

File changed.

Preview size limit exceeded, changes collapsed.

+59 −51
Original line number Diff line number Diff line
@@ -111,13 +111,13 @@ struct tsdev {
	int minor;
	char name[8];
	wait_queue_head_t wait;
	struct list_head list;
	struct list_head client_list;
	struct input_handle handle;
	int x, y, pressure;
	struct ts_calibration cal;
};

struct tsdev_list {
struct tsdev_client {
	struct fasync_struct *fasync;
	struct list_head node;
	struct tsdev *tsdev;
@@ -139,17 +139,18 @@ static struct tsdev *tsdev_table[TSDEV_MINORS/2];

static int tsdev_fasync(int fd, struct file *file, int on)
{
	struct tsdev_list *list = file->private_data;
	struct tsdev_client *client = file->private_data;
	int retval;

	retval = fasync_helper(fd, file, on, &list->fasync);
	retval = fasync_helper(fd, file, on, &client->fasync);
	return retval < 0 ? retval : 0;
}

static int tsdev_open(struct inode *inode, struct file *file)
{
	int i = iminor(inode) - TSDEV_MINOR_BASE;
	struct tsdev_list *list;
	struct tsdev_client *client;
	struct tsdev *tsdev;

	printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled "
		"for removal.\nSee Documentation/feature-removal-schedule.txt "
@@ -158,19 +159,22 @@ static int tsdev_open(struct inode *inode, struct file *file)
	if (i >= TSDEV_MINORS)
		return -ENODEV;

	if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
	tsdev = tsdev_table[i & TSDEV_MINOR_MASK];
	if (!tsdev || !tsdev->exist)
		return -ENODEV;

	client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
	if (!client)
		return -ENOMEM;

	list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
	client->tsdev = tsdev;
	client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
	list_add_tail(&client->node, &tsdev->client_list);

	i &= TSDEV_MINOR_MASK;
	list->tsdev = tsdev_table[i];
	list_add_tail(&list->node, &tsdev_table[i]->list);
	file->private_data = list;
	if (!tsdev->open++ && tsdev->exist)
		input_open_device(&tsdev->handle);

	if (!list->tsdev->open++)
		if (list->tsdev->exist)
			input_open_device(&list->tsdev->handle);
	file->private_data = client;
	return 0;
}

@@ -182,45 +186,48 @@ static void tsdev_free(struct tsdev *tsdev)

static int tsdev_release(struct inode *inode, struct file *file)
{
	struct tsdev_list *list = file->private_data;
	struct tsdev_client *client = file->private_data;
	struct tsdev *tsdev = client->tsdev;

	tsdev_fasync(-1, file, 0);
	list_del(&list->node);

	if (!--list->tsdev->open) {
		if (list->tsdev->exist)
			input_close_device(&list->tsdev->handle);
	list_del(&client->node);
	kfree(client);

	if (!--tsdev->open) {
		if (tsdev->exist)
			input_close_device(&tsdev->handle);
		else
			tsdev_free(list->tsdev);
			tsdev_free(tsdev);
	}
	kfree(list);

	return 0;
}

static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
			  loff_t *ppos)
{
	struct tsdev_list *list = file->private_data;
	struct tsdev_client *client = file->private_data;
	struct tsdev *tsdev = client->tsdev;
	int retval = 0;

	if (list->head == list->tail && list->tsdev->exist && (file->f_flags & O_NONBLOCK))
	if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK))
		return -EAGAIN;

	retval = wait_event_interruptible(list->tsdev->wait,
			list->head != list->tail || !list->tsdev->exist);

	retval = wait_event_interruptible(tsdev->wait,
			client->head != client->tail || !tsdev->exist);
	if (retval)
		return retval;

	if (!list->tsdev->exist)
	if (!tsdev->exist)
		return -ENODEV;

	while (list->head != list->tail &&
	while (client->head != client->tail &&
	       retval + sizeof (struct ts_event) <= count) {
		if (copy_to_user (buffer + retval, list->event + list->tail,
		if (copy_to_user (buffer + retval, client->event + client->tail,
				  sizeof (struct ts_event)))
			return -EFAULT;
		list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
		client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
		retval += sizeof (struct ts_event);
	}

@@ -230,18 +237,19 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
/* No kernel lock - fine */
static unsigned int tsdev_poll(struct file *file, poll_table *wait)
{
	struct tsdev_list *list = file->private_data;
	struct tsdev_client *client = file->private_data;
	struct tsdev *tsdev = client->tsdev;

	poll_wait(file, &list->tsdev->wait, wait);
	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
		(list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
	poll_wait(file, &tsdev->wait, wait);
	return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
		(tsdev->exist ? 0 : (POLLHUP | POLLERR));
}

static int tsdev_ioctl(struct inode *inode, struct file *file,
		       unsigned int cmd, unsigned long arg)
{
	struct tsdev_list *list = file->private_data;
	struct tsdev *tsdev = list->tsdev;
	struct tsdev_client *client = file->private_data;
	struct tsdev *tsdev = client->tsdev;
	int retval = 0;

	switch (cmd) {
@@ -279,7 +287,7 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
			unsigned int code, int value)
{
	struct tsdev *tsdev = handle->private;
	struct tsdev_list *list;
	struct tsdev_client *client;
	struct timeval time;

	switch (type) {
@@ -343,18 +351,18 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
	if (type != EV_SYN || code != SYN_REPORT)
		return;

	list_for_each_entry(list, &tsdev->list, node) {
	list_for_each_entry(client, &tsdev->client_list, node) {
		int x, y, tmp;

		do_gettimeofday(&time);
		list->event[list->head].millisecs = time.tv_usec / 100;
		list->event[list->head].pressure = tsdev->pressure;
		client->event[client->head].millisecs = time.tv_usec / 100;
		client->event[client->head].pressure = tsdev->pressure;

		x = tsdev->x;
		y = tsdev->y;

		/* Calibration */
		if (!list->raw) {
		if (!client->raw) {
			x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
			y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
			if (tsdev->cal.xyswap) {
@@ -362,10 +370,10 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
			}
		}

		list->event[list->head].x = x;
		list->event[list->head].y = y;
		list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1);
		kill_fasync(&list->fasync, SIGIO, POLL_IN);
		client->event[client->head].x = x;
		client->event[client->head].y = y;
		client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1);
		kill_fasync(&client->fasync, SIGIO, POLL_IN);
	}
	wake_up_interruptible(&tsdev->wait);
}
@@ -390,7 +398,7 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
	if (!tsdev)
		return -ENOMEM;

	INIT_LIST_HEAD(&tsdev->list);
	INIT_LIST_HEAD(&tsdev->client_list);
	init_waitqueue_head(&tsdev->wait);

	sprintf(tsdev->name, "ts%d", minor);
@@ -451,7 +459,7 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
static void tsdev_disconnect(struct input_handle *handle)
{
	struct tsdev *tsdev = handle->private;
	struct tsdev_list *list;
	struct tsdev_client *client;

	input_unregister_handle(handle);

@@ -463,8 +471,8 @@ static void tsdev_disconnect(struct input_handle *handle)
	if (tsdev->open) {
		input_close_device(handle);
		wake_up_interruptible(&tsdev->wait);
		list_for_each_entry(list, &tsdev->list, node)
			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
		list_for_each_entry(client, &tsdev->client_list, node)
			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
	} else
		tsdev_free(tsdev);
}