Input: rework handle creation code

 - consolidate code for binding handlers to a device
 - return error codes from handlers connect() methods back to input
   core and log failures

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 5629e39..86b2707 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -380,12 +380,6 @@
 }
 
 
-static void input_link_handle(struct input_handle *handle)
-{
-	list_add_tail(&handle->d_node, &handle->dev->h_list);
-	list_add_tail(&handle->h_node, &handle->handler->h_list);
-}
-
 #define MATCH_BIT(bit, max) \
 		for (i = 0; i < NBITS(max); i++) \
 			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
@@ -432,6 +426,29 @@
 	return NULL;
 }
 
+static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
+{
+	const struct input_device_id *id;
+	int error;
+
+	if (handler->blacklist && input_match_device(handler->blacklist, dev))
+		return -ENODEV;
+
+	id = input_match_device(handler->id_table, dev);
+	if (!id)
+		return -ENODEV;
+
+	error = handler->connect(handler, dev, id);
+	if (error && error != -ENODEV)
+		printk(KERN_ERR
+			"input: failed to attach handler %s to device %s, "
+			"error: %d\n",
+			handler->name, kobject_name(&dev->cdev.kobj), error);
+
+	return error;
+}
+
+
 #ifdef CONFIG_PROC_FS
 
 static struct proc_dir_entry *proc_bus_input_dir;
@@ -1032,9 +1049,7 @@
 int input_register_device(struct input_dev *dev)
 {
 	static atomic_t input_no = ATOMIC_INIT(0);
-	struct input_handle *handle;
 	struct input_handler *handler;
-	const struct input_device_id *id;
 	const char *path;
 	int error;
 
@@ -1074,13 +1089,7 @@
 	kfree(path);
 
 	list_for_each_entry(handler, &input_handler_list, node)
-		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
-			if ((id = input_match_device(handler->id_table, dev)))
-				if ((handle = handler->connect(handler, dev, id))) {
-					input_link_handle(handle);
-					if (handler->start)
-						handler->start(handle);
-				}
+		input_attach_handler(dev, handler);
 
 	input_wakeup_procfs_readers();
 
@@ -1090,7 +1099,7 @@
 
 void input_unregister_device(struct input_dev *dev)
 {
-	struct list_head *node, *next;
+	struct input_handle *handle, *next;
 	int code;
 
 	for (code = 0; code <= KEY_MAX; code++)
@@ -1100,12 +1109,9 @@
 
 	del_timer_sync(&dev->timer);
 
-	list_for_each_safe(node, next, &dev->h_list) {
-		struct input_handle * handle = to_handle(node);
-		list_del_init(&handle->d_node);
-		list_del_init(&handle->h_node);
+	list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
 		handle->handler->disconnect(handle);
-	}
+	WARN_ON(!list_empty(&dev->h_list));
 
 	list_del_init(&dev->node);
 
@@ -1118,8 +1124,6 @@
 int input_register_handler(struct input_handler *handler)
 {
 	struct input_dev *dev;
-	struct input_handle *handle;
-	const struct input_device_id *id;
 
 	INIT_LIST_HEAD(&handler->h_list);
 
@@ -1133,13 +1137,7 @@
 	list_add_tail(&handler->node, &input_handler_list);
 
 	list_for_each_entry(dev, &input_dev_list, node)
-		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
-			if ((id = input_match_device(handler->id_table, dev)))
-				if ((handle = handler->connect(handler, dev, id))) {
-					input_link_handle(handle);
-					if (handler->start)
-						handler->start(handle);
-				}
+		input_attach_handler(dev, handler);
 
 	input_wakeup_procfs_readers();
 	return 0;
@@ -1148,14 +1146,11 @@
 
 void input_unregister_handler(struct input_handler *handler)
 {
-	struct list_head *node, *next;
+	struct input_handle *handle, *next;
 
-	list_for_each_safe(node, next, &handler->h_list) {
-		struct input_handle * handle = to_handle_h(node);
-		list_del_init(&handle->h_node);
-		list_del_init(&handle->d_node);
+	list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
 		handler->disconnect(handle);
-	}
+	WARN_ON(!list_empty(&handler->h_list));
 
 	list_del_init(&handler->node);
 
@@ -1166,6 +1161,27 @@
 }
 EXPORT_SYMBOL(input_unregister_handler);
 
+int input_register_handle(struct input_handle *handle)
+{
+	struct input_handler *handler = handle->handler;
+
+	list_add_tail(&handle->d_node, &handle->dev->h_list);
+	list_add_tail(&handle->h_node, &handler->h_list);
+
+	if (handler->start)
+		handler->start(handle);
+
+	return 0;
+}
+EXPORT_SYMBOL(input_register_handle);
+
+void input_unregister_handle(struct input_handle *handle)
+{
+	list_del_init(&handle->h_node);
+	list_del_init(&handle->d_node);
+}
+EXPORT_SYMBOL(input_unregister_handle);
+
 static int input_open_file(struct inode *inode, struct file *file)
 {
 	struct input_handler *handler = input_table[iminor(inode) >> 5];