diff options
Diffstat (limited to 'drivers/input/evdev.c')
| -rw-r--r-- | drivers/input/evdev.c | 150 | 
1 files changed, 80 insertions, 70 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 840fa198652..8a4cce5c780 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -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) @@ -100,48 +101,55 @@ static void evdev_free(struct evdev *evdev)  	kfree(evdev);  } -static int evdev_release(struct inode * inode, struct file * file) +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) +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; + +	evdev = evdev_table[i]; + +	if (!evdev || !evdev->exist)  		return -ENODEV; -	if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL))) +	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;  } @@ -243,54 +251,55 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev  #endif /* CONFIG_COMPAT */ -static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) +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();  	}  	return retval;  } -static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) +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);  }  |