diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-04-12 01:29:46 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-04-12 01:29:46 -0400 |
commit | 5b2a08262a8c952fef008154933953f083ca5766 (patch) | |
tree | 47fb54c30509a4c444613a1737a212ddda3bb05d /drivers | |
parent | 6e782584e0713ea89da151333e7fe754c8f40324 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/keyboard.c | 28 | ||||
-rw-r--r-- | drivers/input/evbug.c | 32 | ||||
-rw-r--r-- | drivers/input/evdev.c | 47 | ||||
-rw-r--r-- | drivers/input/input.c | 88 | ||||
-rw-r--r-- | drivers/input/joydev.c | 48 | ||||
-rw-r--r-- | drivers/input/mousedev.c | 61 | ||||
-rw-r--r-- | drivers/input/power.c | 46 | ||||
-rw-r--r-- | drivers/input/tsdev.c | 58 |
8 files changed, 284 insertions, 124 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 3d211e8553f7..59712546f911 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/input.h> | 41 | #include <linux/input.h> |
42 | #include <linux/reboot.h> | 42 | #include <linux/reboot.h> |
43 | 43 | ||
44 | static void kbd_disconnect(struct input_handle *handle); | ||
45 | extern void ctrl_alt_del(void); | 44 | extern void ctrl_alt_del(void); |
46 | 45 | ||
47 | /* | 46 | /* |
@@ -1260,11 +1259,11 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type, | |||
1260 | * likes it, it can open it and get events from it. In this (kbd_connect) | 1259 | * likes it, it can open it and get events from it. In this (kbd_connect) |
1261 | * function, we should decide which VT to bind that keyboard to initially. | 1260 | * function, we should decide which VT to bind that keyboard to initially. |
1262 | */ | 1261 | */ |
1263 | static struct input_handle *kbd_connect(struct input_handler *handler, | 1262 | static int kbd_connect(struct input_handler *handler, struct input_dev *dev, |
1264 | struct input_dev *dev, | 1263 | const struct input_device_id *id) |
1265 | const struct input_device_id *id) | ||
1266 | { | 1264 | { |
1267 | struct input_handle *handle; | 1265 | struct input_handle *handle; |
1266 | int error; | ||
1268 | int i; | 1267 | int i; |
1269 | 1268 | ||
1270 | for (i = KEY_RESERVED; i < BTN_MISC; i++) | 1269 | for (i = KEY_RESERVED; i < BTN_MISC; i++) |
@@ -1272,24 +1271,37 @@ static struct input_handle *kbd_connect(struct input_handler *handler, | |||
1272 | break; | 1271 | break; |
1273 | 1272 | ||
1274 | if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) | 1273 | if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) |
1275 | return NULL; | 1274 | return -ENODEV; |
1276 | 1275 | ||
1277 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); | 1276 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); |
1278 | if (!handle) | 1277 | if (!handle) |
1279 | return NULL; | 1278 | return -ENOMEM; |
1280 | 1279 | ||
1281 | handle->dev = dev; | 1280 | handle->dev = dev; |
1282 | handle->handler = handler; | 1281 | handle->handler = handler; |
1283 | handle->name = "kbd"; | 1282 | handle->name = "kbd"; |
1284 | 1283 | ||
1285 | input_open_device(handle); | 1284 | error = input_register_handle(handle); |
1285 | if (error) | ||
1286 | goto err_free_handle; | ||
1287 | |||
1288 | error = input_open_device(handle); | ||
1289 | if (error) | ||
1290 | goto err_unregister_handle; | ||
1291 | |||
1292 | return 0; | ||
1286 | 1293 | ||
1287 | return handle; | 1294 | err_unregister_handle: |
1295 | input_unregister_handle(handle); | ||
1296 | err_free_handle: | ||
1297 | kfree(handle); | ||
1298 | return error; | ||
1288 | } | 1299 | } |
1289 | 1300 | ||
1290 | static void kbd_disconnect(struct input_handle *handle) | 1301 | static void kbd_disconnect(struct input_handle *handle) |
1291 | { | 1302 | { |
1292 | input_close_device(handle); | 1303 | input_close_device(handle); |
1304 | input_unregister_handle(handle); | ||
1293 | kfree(handle); | 1305 | kfree(handle); |
1294 | } | 1306 | } |
1295 | 1307 | ||
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c index 5a9653c3128a..c21f2f127234 100644 --- a/drivers/input/evbug.c +++ b/drivers/input/evbug.c | |||
@@ -38,31 +38,43 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
38 | MODULE_DESCRIPTION("Input driver event debug module"); | 38 | MODULE_DESCRIPTION("Input driver event debug module"); |
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | 40 | ||
41 | static char evbug_name[] = "evbug"; | ||
42 | |||
43 | static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 41 | static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) |
44 | { | 42 | { |
45 | printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", | 43 | printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", |
46 | handle->dev->phys, type, code, value); | 44 | handle->dev->phys, type, code, value); |
47 | } | 45 | } |
48 | 46 | ||
49 | static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev, | 47 | static int evbug_connect(struct input_handler *handler, struct input_dev *dev, |
50 | const struct input_device_id *id) | 48 | const struct input_device_id *id) |
51 | { | 49 | { |
52 | struct input_handle *handle; | 50 | struct input_handle *handle; |
51 | int error; | ||
53 | 52 | ||
54 | if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL))) | 53 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); |
55 | return NULL; | 54 | if (!handle) |
55 | return -ENOMEM; | ||
56 | 56 | ||
57 | handle->dev = dev; | 57 | handle->dev = dev; |
58 | handle->handler = handler; | 58 | handle->handler = handler; |
59 | handle->name = evbug_name; | 59 | handle->name = "evbug"; |
60 | |||
61 | error = input_register_handle(handle); | ||
62 | if (error) | ||
63 | goto err_free_handle; | ||
60 | 64 | ||
61 | input_open_device(handle); | 65 | error = input_open_device(handle); |
66 | if (error) | ||
67 | goto err_unregister_handle; | ||
62 | 68 | ||
63 | printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys); | 69 | printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys); |
64 | 70 | ||
65 | return handle; | 71 | return 0; |
72 | |||
73 | err_unregister_handle: | ||
74 | input_unregister_handle(handle); | ||
75 | err_free_handle: | ||
76 | kfree(handle); | ||
77 | return error; | ||
66 | } | 78 | } |
67 | 79 | ||
68 | static void evbug_disconnect(struct input_handle *handle) | 80 | static void evbug_disconnect(struct input_handle *handle) |
@@ -70,7 +82,7 @@ static void evbug_disconnect(struct input_handle *handle) | |||
70 | printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys); | 82 | printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys); |
71 | 83 | ||
72 | input_close_device(handle); | 84 | input_close_device(handle); |
73 | 85 | input_unregister_handle(handle); | |
74 | kfree(handle); | 86 | kfree(handle); |
75 | } | 87 | } |
76 | 88 | ||
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 64b47de052bb..840fa1986527 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -605,21 +605,24 @@ static const struct file_operations evdev_fops = { | |||
605 | .flush = evdev_flush | 605 | .flush = evdev_flush |
606 | }; | 606 | }; |
607 | 607 | ||
608 | static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, | 608 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, |
609 | const struct input_device_id *id) | 609 | const struct input_device_id *id) |
610 | { | 610 | { |
611 | struct evdev *evdev; | 611 | struct evdev *evdev; |
612 | struct class_device *cdev; | 612 | struct class_device *cdev; |
613 | dev_t devt; | ||
613 | int minor; | 614 | int minor; |
615 | int error; | ||
614 | 616 | ||
615 | for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); | 617 | for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); |
616 | if (minor == EVDEV_MINORS) { | 618 | if (minor == EVDEV_MINORS) { |
617 | printk(KERN_ERR "evdev: no more free evdev devices\n"); | 619 | printk(KERN_ERR "evdev: no more free evdev devices\n"); |
618 | return NULL; | 620 | return -ENFILE; |
619 | } | 621 | } |
620 | 622 | ||
621 | if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL))) | 623 | evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); |
622 | return NULL; | 624 | if (!evdev) |
625 | return -ENOMEM; | ||
623 | 626 | ||
624 | INIT_LIST_HEAD(&evdev->list); | 627 | INIT_LIST_HEAD(&evdev->list); |
625 | init_waitqueue_head(&evdev->wait); | 628 | init_waitqueue_head(&evdev->wait); |
@@ -634,15 +637,35 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct | |||
634 | 637 | ||
635 | evdev_table[minor] = evdev; | 638 | evdev_table[minor] = evdev; |
636 | 639 | ||
637 | cdev = class_device_create(&input_class, &dev->cdev, | 640 | devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), |
638 | MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), | 641 | |
639 | dev->cdev.dev, evdev->name); | 642 | cdev = class_device_create(&input_class, &dev->cdev, devt, |
643 | dev->cdev.dev, evdev->name); | ||
644 | if (IS_ERR(cdev)) { | ||
645 | error = PTR_ERR(cdev); | ||
646 | goto err_free_evdev; | ||
647 | } | ||
640 | 648 | ||
641 | /* temporary symlink to keep userspace happy */ | 649 | /* temporary symlink to keep userspace happy */ |
642 | sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, | 650 | error = sysfs_create_link(&input_class.subsys.kset.kobj, |
643 | evdev->name); | 651 | &cdev->kobj, evdev->name); |
652 | if (error) | ||
653 | goto err_cdev_destroy; | ||
654 | |||
655 | error = input_register_handle(&evdev->handle); | ||
656 | if (error) | ||
657 | goto err_remove_link; | ||
644 | 658 | ||
645 | return &evdev->handle; | 659 | return 0; |
660 | |||
661 | err_remove_link: | ||
662 | sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name); | ||
663 | err_cdev_destroy: | ||
664 | class_device_destroy(&input_class, devt); | ||
665 | err_free_evdev: | ||
666 | kfree(evdev); | ||
667 | evdev_table[minor] = NULL; | ||
668 | return error; | ||
646 | } | 669 | } |
647 | 670 | ||
648 | static void evdev_disconnect(struct input_handle *handle) | 671 | static void evdev_disconnect(struct input_handle *handle) |
@@ -650,6 +673,8 @@ static void evdev_disconnect(struct input_handle *handle) | |||
650 | struct evdev *evdev = handle->private; | 673 | struct evdev *evdev = handle->private; |
651 | struct evdev_list *list; | 674 | struct evdev_list *list; |
652 | 675 | ||
676 | input_unregister_handle(handle); | ||
677 | |||
653 | sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name); | 678 | sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name); |
654 | class_device_destroy(&input_class, | 679 | class_device_destroy(&input_class, |
655 | MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor)); | 680 | MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor)); |
diff --git a/drivers/input/input.c b/drivers/input/input.c index 5629e397520d..86b27079004a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -380,12 +380,6 @@ static int input_default_setkeycode(struct input_dev *dev, | |||
380 | } | 380 | } |
381 | 381 | ||
382 | 382 | ||
383 | static void input_link_handle(struct input_handle *handle) | ||
384 | { | ||
385 | list_add_tail(&handle->d_node, &handle->dev->h_list); | ||
386 | list_add_tail(&handle->h_node, &handle->handler->h_list); | ||
387 | } | ||
388 | |||
389 | #define MATCH_BIT(bit, max) \ | 383 | #define MATCH_BIT(bit, max) \ |
390 | for (i = 0; i < NBITS(max); i++) \ | 384 | for (i = 0; i < NBITS(max); i++) \ |
391 | if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \ | 385 | if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \ |
@@ -432,6 +426,29 @@ static const struct input_device_id *input_match_device(const struct input_devic | |||
432 | return NULL; | 426 | return NULL; |
433 | } | 427 | } |
434 | 428 | ||
429 | static int input_attach_handler(struct input_dev *dev, struct input_handler *handler) | ||
430 | { | ||
431 | const struct input_device_id *id; | ||
432 | int error; | ||
433 | |||
434 | if (handler->blacklist && input_match_device(handler->blacklist, dev)) | ||
435 | return -ENODEV; | ||
436 | |||
437 | id = input_match_device(handler->id_table, dev); | ||
438 | if (!id) | ||
439 | return -ENODEV; | ||
440 | |||
441 | error = handler->connect(handler, dev, id); | ||
442 | if (error && error != -ENODEV) | ||
443 | printk(KERN_ERR | ||
444 | "input: failed to attach handler %s to device %s, " | ||
445 | "error: %d\n", | ||
446 | handler->name, kobject_name(&dev->cdev.kobj), error); | ||
447 | |||
448 | return error; | ||
449 | } | ||
450 | |||
451 | |||
435 | #ifdef CONFIG_PROC_FS | 452 | #ifdef CONFIG_PROC_FS |
436 | 453 | ||
437 | static struct proc_dir_entry *proc_bus_input_dir; | 454 | static struct proc_dir_entry *proc_bus_input_dir; |
@@ -1032,9 +1049,7 @@ EXPORT_SYMBOL(input_free_device); | |||
1032 | int input_register_device(struct input_dev *dev) | 1049 | int input_register_device(struct input_dev *dev) |
1033 | { | 1050 | { |
1034 | static atomic_t input_no = ATOMIC_INIT(0); | 1051 | static atomic_t input_no = ATOMIC_INIT(0); |
1035 | struct input_handle *handle; | ||
1036 | struct input_handler *handler; | 1052 | struct input_handler *handler; |
1037 | const struct input_device_id *id; | ||
1038 | const char *path; | 1053 | const char *path; |
1039 | int error; | 1054 | int error; |
1040 | 1055 | ||
@@ -1074,13 +1089,7 @@ int input_register_device(struct input_dev *dev) | |||
1074 | kfree(path); | 1089 | kfree(path); |
1075 | 1090 | ||
1076 | list_for_each_entry(handler, &input_handler_list, node) | 1091 | list_for_each_entry(handler, &input_handler_list, node) |
1077 | if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) | 1092 | input_attach_handler(dev, handler); |
1078 | if ((id = input_match_device(handler->id_table, dev))) | ||
1079 | if ((handle = handler->connect(handler, dev, id))) { | ||
1080 | input_link_handle(handle); | ||
1081 | if (handler->start) | ||
1082 | handler->start(handle); | ||
1083 | } | ||
1084 | 1093 | ||
1085 | input_wakeup_procfs_readers(); | 1094 | input_wakeup_procfs_readers(); |
1086 | 1095 | ||
@@ -1090,7 +1099,7 @@ EXPORT_SYMBOL(input_register_device); | |||
1090 | 1099 | ||
1091 | void input_unregister_device(struct input_dev *dev) | 1100 | void input_unregister_device(struct input_dev *dev) |
1092 | { | 1101 | { |
1093 | struct list_head *node, *next; | 1102 | struct input_handle *handle, *next; |
1094 | int code; | 1103 | int code; |
1095 | 1104 | ||
1096 | for (code = 0; code <= KEY_MAX; code++) | 1105 | for (code = 0; code <= KEY_MAX; code++) |
@@ -1100,12 +1109,9 @@ void input_unregister_device(struct input_dev *dev) | |||
1100 | 1109 | ||
1101 | del_timer_sync(&dev->timer); | 1110 | del_timer_sync(&dev->timer); |
1102 | 1111 | ||
1103 | list_for_each_safe(node, next, &dev->h_list) { | 1112 | list_for_each_entry_safe(handle, next, &dev->h_list, d_node) |
1104 | struct input_handle * handle = to_handle(node); | ||
1105 | list_del_init(&handle->d_node); | ||
1106 | list_del_init(&handle->h_node); | ||
1107 | handle->handler->disconnect(handle); | 1113 | handle->handler->disconnect(handle); |
1108 | } | 1114 | WARN_ON(!list_empty(&dev->h_list)); |
1109 | 1115 | ||
1110 | list_del_init(&dev->node); | 1116 | list_del_init(&dev->node); |
1111 | 1117 | ||
@@ -1118,8 +1124,6 @@ EXPORT_SYMBOL(input_unregister_device); | |||
1118 | int input_register_handler(struct input_handler *handler) | 1124 | int input_register_handler(struct input_handler *handler) |
1119 | { | 1125 | { |
1120 | struct input_dev *dev; | 1126 | struct input_dev *dev; |
1121 | struct input_handle *handle; | ||
1122 | const struct input_device_id *id; | ||
1123 | 1127 | ||
1124 | INIT_LIST_HEAD(&handler->h_list); | 1128 | INIT_LIST_HEAD(&handler->h_list); |
1125 | 1129 | ||
@@ -1133,13 +1137,7 @@ int input_register_handler(struct input_handler *handler) | |||
1133 | list_add_tail(&handler->node, &input_handler_list); | 1137 | list_add_tail(&handler->node, &input_handler_list); |
1134 | 1138 | ||
1135 | list_for_each_entry(dev, &input_dev_list, node) | 1139 | list_for_each_entry(dev, &input_dev_list, node) |
1136 | if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) | 1140 | input_attach_handler(dev, handler); |
1137 | if ((id = input_match_device(handler->id_table, dev))) | ||
1138 | if ((handle = handler->connect(handler, dev, id))) { | ||
1139 | input_link_handle(handle); | ||
1140 | if (handler->start) | ||
1141 | handler->start(handle); | ||
1142 | } | ||
1143 | 1141 | ||
1144 | input_wakeup_procfs_readers(); | 1142 | input_wakeup_procfs_readers(); |
1145 | return 0; | 1143 | return 0; |
@@ -1148,14 +1146,11 @@ EXPORT_SYMBOL(input_register_handler); | |||
1148 | 1146 | ||
1149 | void input_unregister_handler(struct input_handler *handler) | 1147 | void input_unregister_handler(struct input_handler *handler) |
1150 | { | 1148 | { |
1151 | struct list_head *node, *next; | 1149 | struct input_handle *handle, *next; |
1152 | 1150 | ||
1153 | list_for_each_safe(node, next, &handler->h_list) { | 1151 | list_for_each_entry_safe(handle, next, &handler->h_list, h_node) |
1154 | struct input_handle * handle = to_handle_h(node); | ||
1155 | list_del_init(&handle->h_node); | ||
1156 | list_del_init(&handle->d_node); | ||
1157 | handler->disconnect(handle); | 1152 | handler->disconnect(handle); |
1158 | } | 1153 | WARN_ON(!list_empty(&handler->h_list)); |
1159 | 1154 | ||
1160 | list_del_init(&handler->node); | 1155 | list_del_init(&handler->node); |
1161 | 1156 | ||
@@ -1166,6 +1161,27 @@ void input_unregister_handler(struct input_handler *handler) | |||
1166 | } | 1161 | } |
1167 | EXPORT_SYMBOL(input_unregister_handler); | 1162 | EXPORT_SYMBOL(input_unregister_handler); |
1168 | 1163 | ||
1164 | int input_register_handle(struct input_handle *handle) | ||
1165 | { | ||
1166 | struct input_handler *handler = handle->handler; | ||
1167 | |||
1168 | list_add_tail(&handle->d_node, &handle->dev->h_list); | ||
1169 | list_add_tail(&handle->h_node, &handler->h_list); | ||
1170 | |||
1171 | if (handler->start) | ||
1172 | handler->start(handle); | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | EXPORT_SYMBOL(input_register_handle); | ||
1177 | |||
1178 | void input_unregister_handle(struct input_handle *handle) | ||
1179 | { | ||
1180 | list_del_init(&handle->h_node); | ||
1181 | list_del_init(&handle->d_node); | ||
1182 | } | ||
1183 | EXPORT_SYMBOL(input_unregister_handle); | ||
1184 | |||
1169 | static int input_open_file(struct inode *inode, struct file *file) | 1185 | static int input_open_file(struct inode *inode, struct file *file) |
1170 | { | 1186 | { |
1171 | struct input_handler *handler = input_table[iminor(inode) >> 5]; | 1187 | struct input_handler *handler = input_table[iminor(inode) >> 5]; |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 9f3529ad3fda..cf24a5bde539 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -465,21 +465,24 @@ static const struct file_operations joydev_fops = { | |||
465 | .fasync = joydev_fasync, | 465 | .fasync = joydev_fasync, |
466 | }; | 466 | }; |
467 | 467 | ||
468 | static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, | 468 | static int joydev_connect(struct input_handler *handler, struct input_dev *dev, |
469 | const struct input_device_id *id) | 469 | const struct input_device_id *id) |
470 | { | 470 | { |
471 | struct joydev *joydev; | 471 | struct joydev *joydev; |
472 | struct class_device *cdev; | 472 | struct class_device *cdev; |
473 | dev_t devt; | ||
473 | int i, j, t, minor; | 474 | int i, j, t, minor; |
475 | int error; | ||
474 | 476 | ||
475 | for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); | 477 | for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); |
476 | if (minor == JOYDEV_MINORS) { | 478 | if (minor == JOYDEV_MINORS) { |
477 | printk(KERN_ERR "joydev: no more free joydev devices\n"); | 479 | printk(KERN_ERR "joydev: no more free joydev devices\n"); |
478 | return NULL; | 480 | return -ENFILE; |
479 | } | 481 | } |
480 | 482 | ||
481 | if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL))) | 483 | joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL); |
482 | return NULL; | 484 | if (!joydev) |
485 | return -ENOMEM; | ||
483 | 486 | ||
484 | INIT_LIST_HEAD(&joydev->list); | 487 | INIT_LIST_HEAD(&joydev->list); |
485 | init_waitqueue_head(&joydev->wait); | 488 | init_waitqueue_head(&joydev->wait); |
@@ -534,22 +537,45 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct | |||
534 | 537 | ||
535 | joydev_table[minor] = joydev; | 538 | joydev_table[minor] = joydev; |
536 | 539 | ||
537 | cdev = class_device_create(&input_class, &dev->cdev, | 540 | devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), |
538 | MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), | 541 | |
539 | dev->cdev.dev, joydev->name); | 542 | cdev = class_device_create(&input_class, &dev->cdev, devt, |
543 | dev->cdev.dev, joydev->name); | ||
544 | if (IS_ERR(cdev)) { | ||
545 | error = PTR_ERR(cdev); | ||
546 | goto err_free_joydev; | ||
547 | } | ||
540 | 548 | ||
541 | /* temporary symlink to keep userspace happy */ | 549 | /* temporary symlink to keep userspace happy */ |
542 | sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, | 550 | error = sysfs_create_link(&input_class.subsys.kset.kobj, |
543 | joydev->name); | 551 | &cdev->kobj, joydev->name); |
552 | if (error) | ||
553 | goto err_cdev_destroy; | ||
554 | |||
555 | error = input_register_handle(&joydev->handle); | ||
556 | if (error) | ||
557 | goto err_remove_link; | ||
558 | |||
559 | return 0; | ||
544 | 560 | ||
545 | return &joydev->handle; | 561 | err_remove_link: |
562 | sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name); | ||
563 | err_cdev_destroy: | ||
564 | class_device_destroy(&input_class, devt); | ||
565 | err_free_joydev: | ||
566 | joydev_table[minor] = NULL; | ||
567 | kfree(joydev); | ||
568 | return error; | ||
546 | } | 569 | } |
547 | 570 | ||
571 | |||
548 | static void joydev_disconnect(struct input_handle *handle) | 572 | static void joydev_disconnect(struct input_handle *handle) |
549 | { | 573 | { |
550 | struct joydev *joydev = handle->private; | 574 | struct joydev *joydev = handle->private; |
551 | struct joydev_list *list; | 575 | struct joydev_list *list; |
552 | 576 | ||
577 | input_unregister_handle(handle); | ||
578 | |||
553 | sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name); | 579 | sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name); |
554 | class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); | 580 | class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); |
555 | joydev->exist = 0; | 581 | joydev->exist = 0; |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 664bcc8116fc..007e72f80251 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -624,23 +624,27 @@ static const struct file_operations mousedev_fops = { | |||
624 | .fasync = mousedev_fasync, | 624 | .fasync = mousedev_fasync, |
625 | }; | 625 | }; |
626 | 626 | ||
627 | static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, | 627 | static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, |
628 | const struct input_device_id *id) | 628 | const struct input_device_id *id) |
629 | { | 629 | { |
630 | struct mousedev *mousedev; | 630 | struct mousedev *mousedev; |
631 | struct class_device *cdev; | 631 | struct class_device *cdev; |
632 | int minor = 0; | 632 | dev_t devt; |
633 | int minor; | ||
634 | int error; | ||
633 | 635 | ||
634 | for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); | 636 | for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); |
635 | if (minor == MOUSEDEV_MINORS) { | 637 | if (minor == MOUSEDEV_MINORS) { |
636 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); | 638 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); |
637 | return NULL; | 639 | return -ENFILE; |
638 | } | 640 | } |
639 | 641 | ||
640 | if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL))) | 642 | mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); |
641 | return NULL; | 643 | if (!mousedev) |
644 | return -ENOMEM; | ||
642 | 645 | ||
643 | INIT_LIST_HEAD(&mousedev->list); | 646 | INIT_LIST_HEAD(&mousedev->list); |
647 | INIT_LIST_HEAD(&mousedev->mixdev_node); | ||
644 | init_waitqueue_head(&mousedev->wait); | 648 | init_waitqueue_head(&mousedev->wait); |
645 | 649 | ||
646 | mousedev->minor = minor; | 650 | mousedev->minor = minor; |
@@ -651,20 +655,45 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru | |||
651 | mousedev->handle.private = mousedev; | 655 | mousedev->handle.private = mousedev; |
652 | sprintf(mousedev->name, "mouse%d", minor); | 656 | sprintf(mousedev->name, "mouse%d", minor); |
653 | 657 | ||
654 | if (mousedev_mix.open) | ||
655 | input_open_device(&mousedev->handle); | ||
656 | |||
657 | mousedev_table[minor] = mousedev; | 658 | mousedev_table[minor] = mousedev; |
658 | 659 | ||
659 | cdev = class_device_create(&input_class, &dev->cdev, | 660 | devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), |
660 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), | 661 | |
661 | dev->cdev.dev, mousedev->name); | 662 | cdev = class_device_create(&input_class, &dev->cdev, devt, |
663 | dev->cdev.dev, mousedev->name); | ||
664 | if (IS_ERR(cdev)) { | ||
665 | error = PTR_ERR(cdev); | ||
666 | goto err_free_mousedev; | ||
667 | } | ||
662 | 668 | ||
663 | /* temporary symlink to keep userspace happy */ | 669 | /* temporary symlink to keep userspace happy */ |
664 | sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, | 670 | error = sysfs_create_link(&input_class.subsys.kset.kobj, |
665 | mousedev->name); | 671 | &cdev->kobj, mousedev->name); |
672 | if (error) | ||
673 | goto err_cdev_destroy; | ||
666 | 674 | ||
667 | return &mousedev->handle; | 675 | error = input_register_handle(&mousedev->handle); |
676 | if (error) | ||
677 | goto err_remove_link; | ||
678 | |||
679 | if (mousedev_mix.open) { | ||
680 | error = input_open_device(&mousedev->handle); | ||
681 | if (error) | ||
682 | goto err_unregister_handle; | ||
683 | } | ||
684 | |||
685 | return 0; | ||
686 | |||
687 | err_unregister_handle: | ||
688 | input_unregister_handle(&mousedev->handle); | ||
689 | err_remove_link: | ||
690 | sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name); | ||
691 | err_cdev_destroy: | ||
692 | class_device_destroy(&input_class, devt); | ||
693 | err_free_mousedev: | ||
694 | mousedev_table[minor] = NULL; | ||
695 | kfree(mousedev); | ||
696 | return error; | ||
668 | } | 697 | } |
669 | 698 | ||
670 | static void mousedev_disconnect(struct input_handle *handle) | 699 | static void mousedev_disconnect(struct input_handle *handle) |
@@ -672,6 +701,8 @@ static void mousedev_disconnect(struct input_handle *handle) | |||
672 | struct mousedev *mousedev = handle->private; | 701 | struct mousedev *mousedev = handle->private; |
673 | struct mousedev_list *list; | 702 | struct mousedev_list *list; |
674 | 703 | ||
704 | input_unregister_handle(handle); | ||
705 | |||
675 | sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name); | 706 | sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name); |
676 | class_device_destroy(&input_class, | 707 | class_device_destroy(&input_class, |
677 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); | 708 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); |
diff --git a/drivers/input/power.c b/drivers/input/power.c index ee82464a2fa7..e28d264b9e06 100644 --- a/drivers/input/power.c +++ b/drivers/input/power.c | |||
@@ -41,14 +41,14 @@ static struct input_handler power_handler; | |||
41 | * Power management can't be done in a interrupt context. So we have to | 41 | * Power management can't be done in a interrupt context. So we have to |
42 | * use keventd. | 42 | * use keventd. |
43 | */ | 43 | */ |
44 | static int suspend_button_pushed = 0; | 44 | static int suspend_button_pushed; |
45 | static void suspend_button_task_handler(void *data) | 45 | static void suspend_button_task_handler(struct work_struct *work) |
46 | { | 46 | { |
47 | udelay(200); /* debounce */ | 47 | udelay(200); /* debounce */ |
48 | suspend_button_pushed = 0; | 48 | suspend_button_pushed = 0; |
49 | } | 49 | } |
50 | 50 | ||
51 | static DECLARE_WORK(suspend_button_task, suspend_button_task_handler, NULL); | 51 | static DECLARE_WORK(suspend_button_task, suspend_button_task_handler); |
52 | 52 | ||
53 | static void power_event(struct input_handle *handle, unsigned int type, | 53 | static void power_event(struct input_handle *handle, unsigned int type, |
54 | unsigned int code, int down) | 54 | unsigned int code, int down) |
@@ -63,9 +63,9 @@ static void power_event(struct input_handle *handle, unsigned int type, | |||
63 | printk("Powering down entire device\n"); | 63 | printk("Powering down entire device\n"); |
64 | 64 | ||
65 | if (!suspend_button_pushed) { | 65 | if (!suspend_button_pushed) { |
66 | suspend_button_pushed = 1; | 66 | suspend_button_pushed = 1; |
67 | schedule_work(&suspend_button_task); | 67 | schedule_work(&suspend_button_task); |
68 | } | 68 | } |
69 | break; | 69 | break; |
70 | case KEY_POWER: | 70 | case KEY_POWER: |
71 | /* Hum power down the machine. */ | 71 | /* Hum power down the machine. */ |
@@ -84,7 +84,7 @@ static void power_event(struct input_handle *handle, unsigned int type, | |||
84 | dev->state = PM_RESUME; | 84 | dev->state = PM_RESUME; |
85 | else | 85 | else |
86 | dev->state = PM_SUSPEND; | 86 | dev->state = PM_SUSPEND; |
87 | pm_send(dev->pm_dev, dev->state, dev); | 87 | /* pm_send(dev->pm_dev, dev->state, dev); */ |
88 | break; | 88 | break; |
89 | case KEY_POWER: | 89 | case KEY_POWER: |
90 | /* Turn the input device off completely ? */ | 90 | /* Turn the input device off completely ? */ |
@@ -96,27 +96,41 @@ static void power_event(struct input_handle *handle, unsigned int type, | |||
96 | return; | 96 | return; |
97 | } | 97 | } |
98 | 98 | ||
99 | static struct input_handle *power_connect(struct input_handler *handler, | 99 | static int power_connect(struct input_handler *handler, struct input_dev *dev, |
100 | struct input_dev *dev, | 100 | const struct input_device_id *id) |
101 | const struct input_device_id *id) | ||
102 | { | 101 | { |
103 | struct input_handle *handle; | 102 | struct input_handle *handle; |
103 | int error; | ||
104 | 104 | ||
105 | if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL))) | 105 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); |
106 | return NULL; | 106 | if (!handle) |
107 | return -ENOMEM; | ||
107 | 108 | ||
108 | handle->dev = dev; | 109 | handle->dev = dev; |
109 | handle->handler = handler; | 110 | handle->handler = handler; |
111 | handle->name = "power"; | ||
110 | 112 | ||
111 | input_open_device(handle); | 113 | error = input_register_handle(handle); |
114 | if (error) | ||
115 | goto err_free_handle; | ||
112 | 116 | ||
113 | printk(KERN_INFO "power.c: Adding power management to input layer\n"); | 117 | error = input_open_device(handle); |
114 | return handle; | 118 | if (error) |
119 | goto err_unregister_handle; | ||
120 | |||
121 | return 0; | ||
122 | |||
123 | err_unregister_handle: | ||
124 | input_unregister_handle(handle); | ||
125 | err_free_handle: | ||
126 | kfree(handle); | ||
127 | return error; | ||
115 | } | 128 | } |
116 | 129 | ||
117 | static void power_disconnect(struct input_handle *handle) | 130 | static void power_disconnect(struct input_handle *handle) |
118 | { | 131 | { |
119 | input_close_device(handle); | 132 | input_close_device(handle); |
133 | input_unregister_handle(handle); | ||
120 | kfree(handle); | 134 | kfree(handle); |
121 | } | 135 | } |
122 | 136 | ||
@@ -135,7 +149,7 @@ static const struct input_device_id power_ids[] = { | |||
135 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, | 149 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, |
136 | .evbit = { BIT(EV_PWR) }, | 150 | .evbit = { BIT(EV_PWR) }, |
137 | }, | 151 | }, |
138 | { }, /* Terminating entry */ | 152 | { }, /* Terminating entry */ |
139 | }; | 153 | }; |
140 | 154 | ||
141 | MODULE_DEVICE_TABLE(input, power_ids); | 155 | MODULE_DEVICE_TABLE(input, power_ids); |
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index 0300dca8591d..a23aedc64ab1 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c | |||
@@ -155,7 +155,7 @@ static int tsdev_open(struct inode *inode, struct file *file) | |||
155 | "for removal.\nSee Documentation/feature-removal-schedule.txt " | 155 | "for removal.\nSee Documentation/feature-removal-schedule.txt " |
156 | "for details.\n"); | 156 | "for details.\n"); |
157 | 157 | ||
158 | if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) | 158 | if (i >= TSDEV_MINORS) |
159 | return -ENODEV; | 159 | return -ENODEV; |
160 | 160 | ||
161 | if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL))) | 161 | if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL))) |
@@ -246,14 +246,14 @@ static int tsdev_ioctl(struct inode *inode, struct file *file, | |||
246 | 246 | ||
247 | switch (cmd) { | 247 | switch (cmd) { |
248 | case TS_GET_CAL: | 248 | case TS_GET_CAL: |
249 | if (copy_to_user ((void __user *)arg, &tsdev->cal, | 249 | if (copy_to_user((void __user *)arg, &tsdev->cal, |
250 | sizeof (struct ts_calibration))) | 250 | sizeof (struct ts_calibration))) |
251 | retval = -EFAULT; | 251 | retval = -EFAULT; |
252 | break; | 252 | break; |
253 | 253 | ||
254 | case TS_SET_CAL: | 254 | case TS_SET_CAL: |
255 | if (copy_from_user (&tsdev->cal, (void __user *)arg, | 255 | if (copy_from_user(&tsdev->cal, (void __user *)arg, |
256 | sizeof (struct ts_calibration))) | 256 | sizeof (struct ts_calibration))) |
257 | retval = -EFAULT; | 257 | retval = -EFAULT; |
258 | break; | 258 | break; |
259 | 259 | ||
@@ -370,23 +370,25 @@ static void tsdev_event(struct input_handle *handle, unsigned int type, | |||
370 | wake_up_interruptible(&tsdev->wait); | 370 | wake_up_interruptible(&tsdev->wait); |
371 | } | 371 | } |
372 | 372 | ||
373 | static struct input_handle *tsdev_connect(struct input_handler *handler, | 373 | static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, |
374 | struct input_dev *dev, | 374 | const struct input_device_id *id) |
375 | const struct input_device_id *id) | ||
376 | { | 375 | { |
377 | struct tsdev *tsdev; | 376 | struct tsdev *tsdev; |
378 | struct class_device *cdev; | 377 | struct class_device *cdev; |
378 | dev_t devt; | ||
379 | int minor, delta; | 379 | int minor, delta; |
380 | int error; | ||
380 | 381 | ||
381 | for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++); | 382 | for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++); |
382 | if (minor >= TSDEV_MINORS / 2) { | 383 | if (minor >= TSDEV_MINORS / 2) { |
383 | printk(KERN_ERR | 384 | printk(KERN_ERR |
384 | "tsdev: You have way too many touchscreens\n"); | 385 | "tsdev: You have way too many touchscreens\n"); |
385 | return NULL; | 386 | return -ENFILE; |
386 | } | 387 | } |
387 | 388 | ||
388 | if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL))) | 389 | tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL); |
389 | return NULL; | 390 | if (!tsdev) |
391 | return -ENOMEM; | ||
390 | 392 | ||
391 | INIT_LIST_HEAD(&tsdev->list); | 393 | INIT_LIST_HEAD(&tsdev->list); |
392 | init_waitqueue_head(&tsdev->wait); | 394 | init_waitqueue_head(&tsdev->wait); |
@@ -415,15 +417,35 @@ static struct input_handle *tsdev_connect(struct input_handler *handler, | |||
415 | 417 | ||
416 | tsdev_table[minor] = tsdev; | 418 | tsdev_table[minor] = tsdev; |
417 | 419 | ||
418 | cdev = class_device_create(&input_class, &dev->cdev, | 420 | devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), |
419 | MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), | 421 | |
420 | dev->cdev.dev, tsdev->name); | 422 | cdev = class_device_create(&input_class, &dev->cdev, devt, |
423 | dev->cdev.dev, tsdev->name); | ||
424 | if (IS_ERR(cdev)) { | ||
425 | error = PTR_ERR(cdev); | ||
426 | goto err_free_tsdev; | ||
427 | } | ||
421 | 428 | ||
422 | /* temporary symlink to keep userspace happy */ | 429 | /* temporary symlink to keep userspace happy */ |
423 | sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, | 430 | error = sysfs_create_link(&input_class.subsys.kset.kobj, |
424 | tsdev->name); | 431 | &cdev->kobj, tsdev->name); |
432 | if (error) | ||
433 | goto err_cdev_destroy; | ||
425 | 434 | ||
426 | return &tsdev->handle; | 435 | error = input_register_handle(&tsdev->handle); |
436 | if (error) | ||
437 | goto err_remove_link; | ||
438 | |||
439 | return 0; | ||
440 | |||
441 | err_remove_link: | ||
442 | sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name); | ||
443 | err_cdev_destroy: | ||
444 | class_device_destroy(&input_class, devt); | ||
445 | err_free_tsdev: | ||
446 | tsdev_table[minor] = NULL; | ||
447 | kfree(tsdev); | ||
448 | return error; | ||
427 | } | 449 | } |
428 | 450 | ||
429 | static void tsdev_disconnect(struct input_handle *handle) | 451 | static void tsdev_disconnect(struct input_handle *handle) |
@@ -431,6 +453,8 @@ static void tsdev_disconnect(struct input_handle *handle) | |||
431 | struct tsdev *tsdev = handle->private; | 453 | struct tsdev *tsdev = handle->private; |
432 | struct tsdev_list *list; | 454 | struct tsdev_list *list; |
433 | 455 | ||
456 | input_unregister_handle(handle); | ||
457 | |||
434 | sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name); | 458 | sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name); |
435 | class_device_destroy(&input_class, | 459 | class_device_destroy(&input_class, |
436 | MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor)); | 460 | MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor)); |