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

Input: handlers - handle errors from input_open_device()



Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent d0ffb9be
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ static int evdev_open(struct inode *inode, struct file *file)
	struct evdev_client *client;
	struct evdev *evdev;
	int i = iminor(inode) - EVDEV_MINOR_BASE;
	int error;

	if (i >= EVDEV_MINORS)
		return -ENODEV;
@@ -146,8 +147,14 @@ static int evdev_open(struct inode *inode, struct file *file)
	client->evdev = evdev;
	list_add_tail(&client->node, &evdev->client_list);

	if (!evdev->open++ && evdev->exist)
		input_open_device(&evdev->handle);
	if (!evdev->open++ && evdev->exist) {
		error = input_open_device(&evdev->handle);
		if (error) {
			list_del(&client->node);
			kfree(client);
			return error;
		}
	}

	file->private_data = client;
	return 0;
+9 −2
Original line number Diff line number Diff line
@@ -170,6 +170,7 @@ static int joydev_open(struct inode *inode, struct file *file)
	struct joydev_client *client;
	struct joydev *joydev;
	int i = iminor(inode) - JOYDEV_MINOR_BASE;
	int error;

	if (i >= JOYDEV_MINORS)
		return -ENODEV;
@@ -185,8 +186,14 @@ static int joydev_open(struct inode *inode, struct file *file)
	client->joydev = joydev;
	list_add_tail(&client->node, &joydev->client_list);

	if (!joydev->open++ && joydev->exist)
		input_open_device(&joydev->handle);
	if (!joydev->open++ && joydev->exist) {
		error = input_open_device(&joydev->handle);
		if (error) {
			list_del(&client->node);
			kfree(client);
			return error;
		}
	}

	file->private_data = client;
	return 0;
+80 −34
Original line number Diff line number Diff line
@@ -66,6 +66,9 @@ struct mousedev {
	struct list_head client_list;
	struct input_handle handle;

	struct list_head mixdev_node;
	int mixdev_open;

	struct mousedev_hw_data packet;
	unsigned int pkt_count;
	int old_x[4], old_y[4];
@@ -111,6 +114,7 @@ static struct input_handler mousedev_handler;

static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
static struct mousedev mousedev_mix;
static LIST_HEAD(mousedev_mix_list);

#define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
#define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
@@ -364,14 +368,58 @@ static void mousedev_free(struct mousedev *mousedev)
	kfree(mousedev);
}

static void mixdev_release(void)
static int mixdev_add_device(struct mousedev *mousedev)
{
	struct input_handle *handle;
	int error;

	list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
		struct mousedev *mousedev = handle->private;
	if (mousedev_mix.open) {
		error = input_open_device(&mousedev->handle);
		if (error)
			return error;

		mousedev->open++;
		mousedev->mixdev_open++;
	}

	list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);

	return 0;
}

static void mixdev_remove_device(struct mousedev *mousedev)
{
	if (mousedev->mixdev_open) {
		mousedev->mixdev_open = 0;
		if (!--mousedev->open && mousedev->exist)
			input_close_device(&mousedev->handle);
	}

	list_del_init(&mousedev->mixdev_node);
}

static void mixdev_open_devices(void)
{
	struct mousedev *mousedev;

	list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
		if (mousedev->exist && !mousedev->open) {
			if (input_open_device(&mousedev->handle))
				continue;

			mousedev->open++;
			mousedev->mixdev_open++;
		}
	}
}

static void mixdev_close_devices(void)
{
	struct mousedev *mousedev, *next;

		if (!mousedev->open) {
	list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
		if (mousedev->mixdev_open) {
			mousedev->mixdev_open = 0;
			if (!--mousedev->open) {
				if (mousedev->exist)
					input_close_device(&mousedev->handle);
				else
@@ -379,6 +427,7 @@ static void mixdev_release(void)
			}
		}
	}
}

static int mousedev_release(struct inode *inode, struct file *file)
{
@@ -392,23 +441,22 @@ static int mousedev_release(struct inode *inode, struct file *file)

	if (!--mousedev->open) {
		if (mousedev->minor == MOUSEDEV_MIX)
			mixdev_release();
		else if (!mousedev_mix.open) {
			if (mousedev->exist)
			mixdev_close_devices();
		else if (mousedev->exist)
			input_close_device(&mousedev->handle);
		else
			mousedev_free(mousedev);
	}
	}

	return 0;
}


static int mousedev_open(struct inode *inode, struct file *file)
{
	struct mousedev_client *client;
	struct input_handle *handle;
	struct mousedev *mousedev;
	int error;
	int i;

#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -436,15 +484,16 @@ static int mousedev_open(struct inode *inode, struct file *file)
	list_add_tail(&client->node, &mousedev->client_list);

	if (!mousedev->open++) {
		if (mousedev->minor == MOUSEDEV_MIX) {
			list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
				struct mousedev *md = handle->private;
				if (!md->open && md->exist)
					input_open_device(handle);
		if (mousedev->minor == MOUSEDEV_MIX)
			mixdev_open_devices();
		else if (mousedev->exist) {
			error = input_open_device(&mousedev->handle);
			if (error) {
				list_del(&client->node);
				kfree(client);
				return error;
			}
		}
		} else
			if (!mousedev_mix.open && mousedev->exist)
				input_open_device(&mousedev->handle);
	}

	file->private_data = client;
@@ -683,11 +732,9 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
	if (error)
		goto err_remove_link;

	if (mousedev_mix.open) {
		error = input_open_device(&mousedev->handle);
	error = mixdev_add_device(mousedev);
	if (error)
		goto err_unregister_handle;
	}

	return 0;

@@ -715,17 +762,16 @@ static void mousedev_disconnect(struct input_handle *handle)
			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
	mousedev->exist = 0;

	mixdev_remove_device(mousedev);

	if (mousedev->open) {
		input_close_device(handle);
		wake_up_interruptible(&mousedev->wait);
		list_for_each_entry(client, &mousedev->client_list, node)
			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
	} else {
		if (mousedev_mix.open)
			input_close_device(handle);
	} else
		mousedev_free(mousedev);
}
}

static const struct input_device_id mousedev_ids[] = {
	{
+9 −2
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ static int tsdev_open(struct inode *inode, struct file *file)
	int i = iminor(inode) - TSDEV_MINOR_BASE;
	struct tsdev_client *client;
	struct tsdev *tsdev;
	int error;

	printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled "
		"for removal.\nSee Documentation/feature-removal-schedule.txt "
@@ -171,8 +172,14 @@ static int tsdev_open(struct inode *inode, struct file *file)
	client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
	list_add_tail(&client->node, &tsdev->client_list);

	if (!tsdev->open++ && tsdev->exist)
		input_open_device(&tsdev->handle);
	if (!tsdev->open++ && tsdev->exist) {
		error = input_open_device(&tsdev->handle);
		if (error) {
			list_del(&client->node);
			kfree(client);
			return error;
		}
	}

	file->private_data = client;
	return 0;