[RFC] Input: support the specified input device number
diff mbox

Message ID 4ACD4A4B.3080200@samsung.com
State Rejected
Headers show

Commit Message

Joonyoung Shim Oct. 8, 2009, 2:11 a.m. UTC
None

Patch
diff mbox

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 1148140..91ee7a0 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -791,16 +791,12 @@  static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
 			 const struct input_device_id *id)
 {
 	struct evdev *evdev;
-	int minor;
+	int minor = dev->input_no;
 	int error;
 
-	for (minor = 0; minor < EVDEV_MINORS; minor++)
-		if (!evdev_table[minor])
-			break;
-
-	if (minor == EVDEV_MINORS) {
-		printk(KERN_ERR "evdev: no more free evdev devices\n");
-		return -ENFILE;
+	if (minor >= EVDEV_MINORS) {
+		printk(KERN_ERR "evdev: invalid evdev device number\n");
+		return -EINVAL;
 	}
 
 	evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index b8ed429..4d568e3 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -23,6 +23,7 @@ 
 #include <linux/mutex.h>
 #include <linux/rcupdate.h>
 #include <linux/smp_lock.h>
+#include <linux/idr.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -59,6 +60,8 @@  static LIST_HEAD(input_handler_list);
  */
 static DEFINE_MUTEX(input_mutex);
 
+static DEFINE_IDR(input_idr);
+
 static struct input_handler *input_table[8];
 
 static inline int is_event_supported(unsigned int code,
@@ -287,6 +290,36 @@  static void input_handle_event(struct input_dev *dev,
 		input_pass_event(dev, type, code, value);
 }
 
+/*
+ * Get new free input device number and associate pointer with it or associate
+ * pointer with specified number bigger than zero.
+ */
+static int input_no_get(struct idr *p, int n)
+{
+	int input_no;
+	int start_no = 0;
+	int err;
+
+	if (n > 0)
+		start_no = n;
+
+	do {
+		err = -ENOMEM;
+		if (idr_pre_get(p, GFP_KERNEL))
+			err = idr_get_new_above(p, NULL, start_no, &input_no);
+	} while (err == -EAGAIN);
+
+	if (err)
+		return err;
+
+	if (n > 0 && input_no != n) {
+		idr_remove(p, input_no);
+		return -EINVAL;
+	}
+
+	return input_no;
+}
+
 /**
  * input_event() - report new input event
  * @dev: device that generated the event
@@ -1463,7 +1496,6 @@  EXPORT_SYMBOL(input_set_capability);
  */
 int input_register_device(struct input_dev *dev)
 {
-	static atomic_t input_no = ATOMIC_INIT(0);
 	struct input_handler *handler;
 	const char *path;
 	int error;
@@ -1489,8 +1521,11 @@  int input_register_device(struct input_dev *dev)
 	if (!dev->setkeycode)
 		dev->setkeycode = input_default_setkeycode;
 
-	dev_set_name(&dev->dev, "input%ld",
-		     (unsigned long) atomic_inc_return(&input_no) - 1);
+	error = input_no_get(&input_idr, dev->input_no);
+	if (error < 0)
+		return error;
+	dev->input_no = error;
+	dev_set_name(&dev->dev, "input%d", dev->input_no);
 
 	error = device_add(&dev->dev);
 	if (error)
diff --git a/include/linux/input.h b/include/linux/input.h
index 0ccfc30..6145fb7 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1002,6 +1002,7 @@  struct ff_effect {
  * @phys: physical path to the device in the system hierarchy
  * @uniq: unique identification code for the device (if device has it)
  * @id: id of the device (struct input_id)
+ * @input_no: number of the input device
  * @evbit: bitmap of types of events supported by the device (EV_KEY,
  *	EV_REL, etc.)
  * @keybit: bitmap of keys/buttons this device has
@@ -1074,6 +1075,7 @@  struct input_dev {
 	const char *phys;
 	const char *uniq;
 	struct input_id id;
+	int input_no;
 
 	unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
 	unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];