Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9657d75c authored by Dmitry Torokhov's avatar Dmitry Torokhov
Browse files

Input: convert from class devices to standard devices



Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent d63219a1
Loading
Loading
Loading
Loading
+42 −42
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ struct evdev {
	wait_queue_head_t wait;
	struct evdev_client *grab;
	struct list_head client_list;
	struct device dev;
};

struct evdev_client {
@@ -94,8 +95,10 @@ static int evdev_flush(struct file *file, fl_owner_t id)
	return input_flush_device(&evdev->handle, file);
}

static void evdev_free(struct evdev *evdev)
static void evdev_free(struct device *dev)
{
	struct evdev *evdev = container_of(dev, struct evdev, dev);

	evdev_table[evdev->minor] = NULL;
	kfree(evdev);
}
@@ -114,12 +117,10 @@ static int evdev_release(struct inode *inode, struct file *file)
	list_del(&client->node);
	kfree(client);

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

	put_device(&evdev->dev);

	return 0;
}
@@ -139,24 +140,32 @@ static int evdev_open(struct inode *inode, struct file *file)
	if (!evdev || !evdev->exist)
		return -ENODEV;

	get_device(&evdev->dev);

	client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
	if (!client)
		return -ENOMEM;
	if (!client) {
		error = -ENOMEM;
		goto err_put_evdev;
	}

	client->evdev = evdev;
	list_add_tail(&client->node, &evdev->client_list);

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

	file->private_data = client;
	return 0;

 err_free_client:
	list_del(&client->node);
	kfree(client);
 err_put_evdev:
	put_device(&evdev->dev);
	return error;
}

#ifdef CONFIG_COMPAT
@@ -625,8 +634,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
			 const struct input_device_id *id)
{
	struct evdev *evdev;
	struct class_device *cdev;
	dev_t devt;
	int minor;
	int error;

@@ -649,38 +656,32 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
	evdev->handle.name = evdev->name;
	evdev->handle.handler = handler;
	evdev->handle.private = evdev;
	sprintf(evdev->name, "event%d", minor);

	evdev_table[minor] = evdev;
	snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);

	devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
	snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
		 "event%d", minor);
	evdev->dev.class = &input_class;
	evdev->dev.parent = &dev->dev;
	evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
	evdev->dev.release = evdev_free;
	device_initialize(&evdev->dev);

	cdev = class_device_create(&input_class, &dev->cdev, devt,
				   dev->cdev.dev, evdev->name);
	if (IS_ERR(cdev)) {
		error = PTR_ERR(cdev);
		goto err_free_evdev;
	}
	evdev_table[minor] = evdev;

	/* temporary symlink to keep userspace happy */
	error = sysfs_create_link(&input_class.subsys.kobj,
				  &cdev->kobj, evdev->name);
	error = device_add(&evdev->dev);
	if (error)
		goto err_cdev_destroy;
		goto err_free_evdev;

	error = input_register_handle(&evdev->handle);
	if (error)
		goto err_remove_link;
		goto err_delete_evdev;

	return 0;

 err_remove_link:
	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
 err_cdev_destroy:
	class_device_destroy(&input_class, devt);
 err_delete_evdev:
	device_del(&evdev->dev);
 err_free_evdev:
	kfree(evdev);
	evdev_table[minor] = NULL;
	put_device(&evdev->dev);
	return error;
}

@@ -690,10 +691,8 @@ static void evdev_disconnect(struct input_handle *handle)
	struct evdev_client *client;

	input_unregister_handle(handle);
	device_del(&evdev->dev);

	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
	class_device_destroy(&input_class,
			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
	evdev->exist = 0;

	if (evdev->open) {
@@ -702,8 +701,9 @@ static void evdev_disconnect(struct input_handle *handle)
		list_for_each_entry(client, &evdev->client_list, node)
			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
		wake_up_interruptible(&evdev->wait);
	} else
		evdev_free(evdev);
	}

	put_device(&evdev->dev);
}

static const struct input_device_id evdev_ids[] = {
+74 −62
Original line number Diff line number Diff line
@@ -442,7 +442,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
		printk(KERN_ERR
			"input: failed to attach handler %s to device %s, "
			"error: %d\n",
			handler->name, kobject_name(&dev->cdev.kobj), error);
			handler->name, kobject_name(&dev->dev.kobj), error);

	return error;
}
@@ -527,7 +527,7 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
static int input_devices_seq_show(struct seq_file *seq, void *v)
{
	struct input_dev *dev = container_of(v, struct input_dev, node);
	const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
	const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
	struct input_handle *handle;

	seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
@@ -683,14 +683,16 @@ static inline void input_proc_exit(void) { }
#endif

#define INPUT_DEV_STRING_ATTR_SHOW(name)				\
static ssize_t input_dev_show_##name(struct class_device *dev, char *buf)	\
static ssize_t input_dev_show_##name(struct device *dev,		\
				     struct device_attribute *attr,	\
				     char *buf)				\
{									\
	struct input_dev *input_dev = to_input_dev(dev);		\
									\
	return scnprintf(buf, PAGE_SIZE, "%s\n",			\
			 input_dev->name ? input_dev->name : "");	\
}									\
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)

INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys);
@@ -744,7 +746,9 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
	return len;
}

static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
static ssize_t input_dev_show_modalias(struct device *dev,
				       struct device_attribute *attr,
				       char *buf)
{
	struct input_dev *id = to_input_dev(dev);
	ssize_t len;
@@ -753,13 +757,13 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)

	return min_t(int, len, PAGE_SIZE);
}
static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);

static struct attribute *input_dev_attrs[] = {
	&class_device_attr_name.attr,
	&class_device_attr_phys.attr,
	&class_device_attr_uniq.attr,
	&class_device_attr_modalias.attr,
	&dev_attr_name.attr,
	&dev_attr_phys.attr,
	&dev_attr_uniq.attr,
	&dev_attr_modalias.attr,
	NULL
};

@@ -768,12 +772,14 @@ static struct attribute_group input_dev_attr_group = {
};

#define INPUT_DEV_ID_ATTR(name)						\
static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf)	\
static ssize_t input_dev_show_id_##name(struct device *dev,		\
					struct device_attribute *attr,	\
					char *buf)			\
{									\
	struct input_dev *input_dev = to_input_dev(dev);		\
	return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name);	\
}									\
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)

INPUT_DEV_ID_ATTR(bustype);
INPUT_DEV_ID_ATTR(vendor);
@@ -781,10 +787,10 @@ INPUT_DEV_ID_ATTR(product);
INPUT_DEV_ID_ATTR(version);

static struct attribute *input_dev_id_attrs[] = {
	&class_device_attr_bustype.attr,
	&class_device_attr_vendor.attr,
	&class_device_attr_product.attr,
	&class_device_attr_version.attr,
	&dev_attr_bustype.attr,
	&dev_attr_vendor.attr,
	&dev_attr_product.attr,
	&dev_attr_version.attr,
	NULL
};

@@ -814,14 +820,16 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
}

#define INPUT_DEV_CAP_ATTR(ev, bm)					\
static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf)	\
static ssize_t input_dev_show_cap_##bm(struct device *dev,		\
				       struct device_attribute *attr,	\
				       char *buf)			\
{									\
	struct input_dev *input_dev = to_input_dev(dev);		\
	int len = input_print_bitmap(buf, PAGE_SIZE,			\
				     input_dev->bm##bit, ev##_MAX, 1);	\
	return min_t(int, len, PAGE_SIZE);				\
}									\
static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)

INPUT_DEV_CAP_ATTR(EV, ev);
INPUT_DEV_CAP_ATTR(KEY, key);
@@ -834,15 +842,15 @@ INPUT_DEV_CAP_ATTR(FF, ff);
INPUT_DEV_CAP_ATTR(SW, sw);

static struct attribute *input_dev_caps_attrs[] = {
	&class_device_attr_ev.attr,
	&class_device_attr_key.attr,
	&class_device_attr_rel.attr,
	&class_device_attr_abs.attr,
	&class_device_attr_msc.attr,
	&class_device_attr_led.attr,
	&class_device_attr_snd.attr,
	&class_device_attr_ff.attr,
	&class_device_attr_sw.attr,
	&dev_attr_ev.attr,
	&dev_attr_key.attr,
	&dev_attr_rel.attr,
	&dev_attr_abs.attr,
	&dev_attr_msc.attr,
	&dev_attr_led.attr,
	&dev_attr_snd.attr,
	&dev_attr_ff.attr,
	&dev_attr_sw.attr,
	NULL
};

@@ -858,9 +866,9 @@ static struct attribute_group *input_dev_attr_groups[] = {
	NULL
};

static void input_dev_release(struct class_device *class_dev)
static void input_dev_release(struct device *device)
{
	struct input_dev *dev = to_input_dev(class_dev);
	struct input_dev *dev = to_input_dev(device);

	input_ff_destroy(dev);
	kfree(dev);
@@ -947,10 +955,10 @@ static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_ind
			return err;					\
	} while (0)

static int input_dev_uevent(struct class_device *cdev, char **envp,
static int input_dev_uevent(struct device *device, char **envp,
			    int num_envp, char *buffer, int buffer_size)
{
	struct input_dev *dev = to_input_dev(cdev);
	struct input_dev *dev = to_input_dev(device);
	int i = 0;
	int len = 0;

@@ -988,11 +996,15 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
	return 0;
}

struct class input_class = {
	.name			= "input",
static struct device_type input_dev_type = {
	.groups		= input_dev_attr_groups,
	.release	= input_dev_release,
	.uevent		= input_dev_uevent,
};

struct class input_class = {
	.name		= "input",
};
EXPORT_SYMBOL_GPL(input_class);

/**
@@ -1010,9 +1022,9 @@ struct input_dev *input_allocate_device(void)

	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
	if (dev) {
		dev->cdev.class = &input_class;
		dev->cdev.groups = input_dev_attr_groups;
		class_device_initialize(&dev->cdev);
		dev->dev.type = &input_dev_type;
		dev->dev.class = &input_class;
		device_initialize(&dev->dev);
		mutex_init(&dev->mutex);
		INIT_LIST_HEAD(&dev->h_list);
		INIT_LIST_HEAD(&dev->node);
@@ -1131,17 +1143,17 @@ int input_register_device(struct input_dev *dev)

	list_add_tail(&dev->node, &input_dev_list);

	snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
		 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);

	if (!dev->cdev.dev)
		dev->cdev.dev = dev->dev.parent;
	if (dev->cdev.dev)
		dev->dev.parent = dev->cdev.dev;

	error = class_device_add(&dev->cdev);
	error = device_add(&dev->dev);
	if (error)
		return error;

	path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
	printk(KERN_INFO "input: %s as %s\n",
		dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
	kfree(path);
@@ -1173,7 +1185,7 @@ void input_unregister_device(struct input_dev *dev)

	list_del_init(&dev->node);

	class_device_unregister(&dev->cdev);
	device_unregister(&dev->dev);

	input_wakeup_procfs_readers();
}
+43 −41
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ struct joydev {
	struct input_handle handle;
	wait_queue_head_t wait;
	struct list_head client_list;
	struct device dev;

	struct js_corr corr[ABS_MAX + 1];
	struct JS_DATA_SAVE_TYPE glue;
	int nabs;
@@ -138,8 +140,10 @@ static int joydev_fasync(int fd, struct file *file, int on)
	return retval < 0 ? retval : 0;
}

static void joydev_free(struct joydev *joydev)
static void joydev_free(struct device *dev)
{
	struct joydev *joydev = container_of(dev, struct joydev, dev);

	joydev_table[joydev->minor] = NULL;
	kfree(joydev);
}
@@ -154,12 +158,10 @@ static int joydev_release(struct inode *inode, struct file *file)
	list_del(&client->node);
	kfree(client);

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

	put_device(&joydev->dev);

	return 0;
}
@@ -178,24 +180,32 @@ static int joydev_open(struct inode *inode, struct file *file)
	if (!joydev || !joydev->exist)
		return -ENODEV;

	get_device(&joydev->dev);

	client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
	if (!client)
		return -ENOMEM;
	if (!client) {
		error = -ENOMEM;
		goto err_put_joydev;
	}

	client->joydev = joydev;
	list_add_tail(&client->node, &joydev->client_list);

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

	file->private_data = client;
	return 0;

 err_free_client:
	list_del(&client->node);
	kfree(client);
 err_put_joydev:
	put_device(&joydev->dev);
	return error;
}

static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
@@ -481,8 +491,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
			  const struct input_device_id *id)
{
	struct joydev *joydev;
	struct class_device *cdev;
	dev_t devt;
	int i, j, t, minor;
	int error;

@@ -505,7 +513,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
	joydev->handle.name = joydev->name;
	joydev->handle.handler = handler;
	joydev->handle.private = joydev;
	sprintf(joydev->name, "js%d", minor);
	snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);

	for (i = 0; i < ABS_MAX + 1; i++)
		if (test_bit(i, dev->absbit)) {
@@ -547,36 +555,30 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
		joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
	}

	joydev_table[minor] = joydev;

	devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
	snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
		 "js%d", minor);
	joydev->dev.class = &input_class;
	joydev->dev.parent = &dev->dev;
	joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
	joydev->dev.release = joydev_free;
	device_initialize(&joydev->dev);

	cdev = class_device_create(&input_class, &dev->cdev, devt,
				   dev->cdev.dev, joydev->name);
	if (IS_ERR(cdev)) {
		error = PTR_ERR(cdev);
		goto err_free_joydev;
	}
	joydev_table[minor] = joydev;

	/* temporary symlink to keep userspace happy */
	error = sysfs_create_link(&input_class.subsys.kobj,
				  &cdev->kobj, joydev->name);
	error = device_add(&joydev->dev);
	if (error)
		goto err_cdev_destroy;
		goto err_free_joydev;

	error = input_register_handle(&joydev->handle);
	if (error)
		goto err_remove_link;
		goto err_delete_joydev;

	return 0;

 err_remove_link:
	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
 err_cdev_destroy:
	class_device_destroy(&input_class, devt);
 err_delete_joydev:
	device_del(&joydev->dev);
 err_free_joydev:
	joydev_table[minor] = NULL;
	kfree(joydev);
	put_device(&joydev->dev);
	return error;
}

@@ -587,9 +589,8 @@ static void joydev_disconnect(struct input_handle *handle)
	struct joydev_client *client;

	input_unregister_handle(handle);
	device_del(&joydev->dev);

	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
	class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
	joydev->exist = 0;

	if (joydev->open) {
@@ -597,8 +598,9 @@ static void joydev_disconnect(struct input_handle *handle)
		list_for_each_entry(client, &joydev->client_list, node)
			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
		wake_up_interruptible(&joydev->wait);
	} else
		joydev_free(joydev);
	}

	put_device(&joydev->dev);
}

static const struct input_device_id joydev_blacklist[] = {
+132 −110
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ struct mousedev {
	wait_queue_head_t wait;
	struct list_head client_list;
	struct input_handle handle;
	struct device dev;

	struct list_head mixdev_node;
	int mixdev_open;
@@ -112,7 +113,7 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
static struct input_handler mousedev_handler;

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

#define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
@@ -218,10 +219,10 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int

	if (value) {
		set_bit(index, &mousedev->packet.buttons);
		set_bit(index, &mousedev_mix.packet.buttons);
		set_bit(index, &mousedev_mix->packet.buttons);
	} else {
		clear_bit(index, &mousedev->packet.buttons);
		clear_bit(index, &mousedev_mix.packet.buttons);
		clear_bit(index, &mousedev_mix->packet.buttons);
	}
}

@@ -287,11 +288,11 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
			 * motion packet so we won't mess current position.
			 */
			set_bit(0, &mousedev->packet.buttons);
			set_bit(0, &mousedev_mix.packet.buttons);
			mousedev_notify_readers(mousedev, &mousedev_mix.packet);
			mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
			set_bit(0, &mousedev_mix->packet.buttons);
			mousedev_notify_readers(mousedev, &mousedev_mix->packet);
			mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
			clear_bit(0, &mousedev->packet.buttons);
			clear_bit(0, &mousedev_mix.packet.buttons);
			clear_bit(0, &mousedev_mix->packet.buttons);
		}
		mousedev->touch = mousedev->pkt_count = 0;
		mousedev->frac_dx = 0;
@@ -343,7 +344,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
				}

				mousedev_notify_readers(mousedev, &mousedev->packet);
				mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
				mousedev_notify_readers(mousedev_mix, &mousedev->packet);

				mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
				mousedev->packet.abs_event = 0;
@@ -362,8 +363,10 @@ static int mousedev_fasync(int fd, struct file *file, int on)
	return retval < 0 ? retval : 0;
}

static void mousedev_free(struct mousedev *mousedev)
static void mousedev_free(struct device *dev)
{
	struct mousedev *mousedev = container_of(dev, struct mousedev, dev);

	mousedev_table[mousedev->minor] = NULL;
	kfree(mousedev);
}
@@ -372,15 +375,16 @@ static int mixdev_add_device(struct mousedev *mousedev)
{
	int error;

	if (mousedev_mix.open) {
	if (mousedev_mix->open) {
		error = input_open_device(&mousedev->handle);
		if (error)
			return error;

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

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

	return 0;
@@ -395,36 +399,40 @@ static void mixdev_remove_device(struct mousedev *mousedev)
	}

	list_del_init(&mousedev->mixdev_node);
	put_device(&mousedev->dev);
}

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

	if (mousedev_mix->open++)
		return;

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

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

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

	if (--mousedev_mix->open)
		return;

	list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
	list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
		if (mousedev->mixdev_open) {
			mousedev->mixdev_open = 0;
			if (!--mousedev->open) {
				if (mousedev->exist)
			if (!--mousedev->open && mousedev->exist)
				input_close_device(&mousedev->handle);
				else
					mousedev_free(mousedev);
			}
		}
	}
}
@@ -439,14 +447,12 @@ static int mousedev_release(struct inode *inode, struct file *file)
	list_del(&client->node);
	kfree(client);

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

	put_device(&mousedev->dev);

	return 0;
}
@@ -473,9 +479,13 @@ static int mousedev_open(struct inode *inode, struct file *file)
	if (!mousedev)
		return -ENODEV;

	get_device(&mousedev->dev);

	client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
	if (!client)
		return -ENOMEM;
	if (!client) {
		error = -ENOMEM;
		goto err_put_mousedev;
	}

	spin_lock_init(&client->packet_lock);
	client->pos_x = xres / 2;
@@ -483,21 +493,23 @@ static int mousedev_open(struct inode *inode, struct file *file)
	client->mousedev = mousedev;
	list_add_tail(&client->node, &mousedev->client_list);

	if (!mousedev->open++) {
	if (mousedev->minor == MOUSEDEV_MIX)
		mixdev_open_devices();
		else if (mousedev->exist) {
	else if (!mousedev->open++ && mousedev->exist) {
		error = input_open_device(&mousedev->handle);
			if (error) {
				list_del(&client->node);
				kfree(client);
				return error;
			}
		}
		if (error)
			goto err_free_client;
	}

	file->private_data = client;
	return 0;

 err_free_client:
	list_del(&client->node);
	kfree(client);
 err_put_mousedev:
	put_device(&mousedev->dev);
	return error;
}

static inline int mousedev_limit_delta(int delta, int limit)
@@ -680,57 +692,96 @@ static const struct file_operations mousedev_fops = {
	.fasync =	mousedev_fasync,
};

static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
			    const struct input_device_id *id)
static struct mousedev *mousedev_create(struct input_dev *dev,
					struct input_handler *handler,
					int minor)
{
	struct mousedev *mousedev;
	struct class_device *cdev;
	dev_t devt;
	int minor;
	int error;

	for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
	if (minor == MOUSEDEV_MINORS) {
		printk(KERN_ERR "mousedev: no more free mousedev devices\n");
		return -ENFILE;
	}

	mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
	if (!mousedev)
		return -ENOMEM;
	if (!mousedev) {
		error = -ENOMEM;
		goto err_out;
	}

	INIT_LIST_HEAD(&mousedev->client_list);
	INIT_LIST_HEAD(&mousedev->mixdev_node);
	init_waitqueue_head(&mousedev->wait);

	if (minor == MOUSEDEV_MIX)
		strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
	else
		snprintf(mousedev->name, sizeof(mousedev->name),
			 "mouse%d", minor);

	mousedev->minor = minor;
	mousedev->exist = 1;
	mousedev->handle.dev = dev;
	mousedev->handle.name = mousedev->name;
	mousedev->handle.handler = handler;
	mousedev->handle.private = mousedev;
	sprintf(mousedev->name, "mouse%d", minor);

	mousedev_table[minor] = mousedev;
	strlcpy(mousedev->dev.bus_id, mousedev->name,
		sizeof(mousedev->dev.bus_id));
	mousedev->dev.class = &input_class;
	if (dev)
		mousedev->dev.parent = &dev->dev;
	mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
	mousedev->dev.release = mousedev_free;
	device_initialize(&mousedev->dev);

	devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
	mousedev_table[minor] = mousedev;

	cdev = class_device_create(&input_class, &dev->cdev, devt,
				   dev->cdev.dev, mousedev->name);
	if (IS_ERR(cdev)) {
		error = PTR_ERR(cdev);
	error = device_add(&mousedev->dev);
	if (error)
		goto err_free_mousedev;

	return mousedev;

 err_free_mousedev:
	put_device(&mousedev->dev);
 err_out:
	return ERR_PTR(error);
}

	/* temporary symlink to keep userspace happy */
	error = sysfs_create_link(&input_class.subsys.kobj,
				  &cdev->kobj, mousedev->name);
	if (error)
		goto err_cdev_destroy;
static void mousedev_destroy(struct mousedev *mousedev)
{
	struct mousedev_client *client;

	device_del(&mousedev->dev);
	mousedev->exist = 0;

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

	put_device(&mousedev->dev);
}

static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
			    const struct input_device_id *id)
{
	struct mousedev *mousedev;
	int minor;
	int error;

	for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
	if (minor == MOUSEDEV_MINORS) {
		printk(KERN_ERR "mousedev: no more free mousedev devices\n");
		return -ENFILE;
	}

	mousedev = mousedev_create(dev, handler, minor);
	if (IS_ERR(mousedev))
		return PTR_ERR(mousedev);

	error = input_register_handle(&mousedev->handle);
	if (error)
		goto err_remove_link;
		goto err_delete_mousedev;

	error = mixdev_add_device(mousedev);
	if (error)
@@ -740,37 +791,18 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev

 err_unregister_handle:
	input_unregister_handle(&mousedev->handle);
 err_remove_link:
	sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
 err_cdev_destroy:
	class_device_destroy(&input_class, devt);
 err_free_mousedev:
	mousedev_table[minor] = NULL;
	kfree(mousedev);
 err_delete_mousedev:
	device_unregister(&mousedev->dev);
	return error;
}

static void mousedev_disconnect(struct input_handle *handle)
{
	struct mousedev *mousedev = handle->private;
	struct mousedev_client *client;

	input_unregister_handle(handle);

	sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
	class_device_destroy(&input_class,
			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
	mousedev->exist = 0;

	mixdev_remove_device(mousedev);

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

static const struct input_device_id mousedev_ids[] = {
@@ -822,25 +854,16 @@ static int psaux_registered;

static int __init mousedev_init(void)
{
	struct class_device *cdev;
	int error;

	mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
	if (IS_ERR(mousedev_mix))
		return PTR_ERR(mousedev_mix);

	error = input_register_handler(&mousedev_handler);
	if (error)
	if (error) {
		mousedev_destroy(mousedev_mix);
		return error;

	memset(&mousedev_mix, 0, sizeof(struct mousedev));
	INIT_LIST_HEAD(&mousedev_mix.client_list);
	init_waitqueue_head(&mousedev_mix.wait);
	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
	mousedev_mix.exist = 1;
	mousedev_mix.minor = MOUSEDEV_MIX;

	cdev = class_device_create(&input_class, NULL,
			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
	if (IS_ERR(cdev)) {
		input_unregister_handler(&mousedev_handler);
		return PTR_ERR(cdev);
	}

#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -863,9 +886,8 @@ static void __exit mousedev_exit(void)
	if (psaux_registered)
		misc_deregister(&psaux_mouse);
#endif
	class_device_destroy(&input_class,
			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
	input_unregister_handler(&mousedev_handler);
	mousedev_destroy(mousedev_mix);
}

module_init(mousedev_init);
+44 −44

File changed.

Preview size limit exceeded, changes collapsed.

Loading