diff options
-rw-r--r-- | drivers/char/keyboard.c | 39 | ||||
-rw-r--r-- | drivers/input/input.c | 12 | ||||
-rw-r--r-- | include/linux/input.h | 21 |
3 files changed, 51 insertions, 21 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 056ebe84b81d..38de44b87506 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -988,7 +988,7 @@ static inline unsigned char getleds(void) | |||
988 | * interrupt routines for this thing allows us to easily mask | 988 | * interrupt routines for this thing allows us to easily mask |
989 | * this when we don't want any of the above to happen. | 989 | * this when we don't want any of the above to happen. |
990 | * This allows for easy and efficient race-condition prevention | 990 | * This allows for easy and efficient race-condition prevention |
991 | * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ... | 991 | * for kbd_start => input_event(dev, EV_LED, ...) => ... |
992 | */ | 992 | */ |
993 | 993 | ||
994 | static void kbd_bh(unsigned long dummy) | 994 | static void kbd_bh(unsigned long dummy) |
@@ -1011,23 +1011,6 @@ static void kbd_bh(unsigned long dummy) | |||
1011 | 1011 | ||
1012 | DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); | 1012 | DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); |
1013 | 1013 | ||
1014 | /* | ||
1015 | * This allows a newly plugged keyboard to pick the LED state. | ||
1016 | */ | ||
1017 | static void kbd_refresh_leds(struct input_handle *handle) | ||
1018 | { | ||
1019 | unsigned char leds = ledstate; | ||
1020 | |||
1021 | tasklet_disable(&keyboard_tasklet); | ||
1022 | if (leds != 0xff) { | ||
1023 | input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); | ||
1024 | input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); | ||
1025 | input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); | ||
1026 | input_sync(handle->dev); | ||
1027 | } | ||
1028 | tasklet_enable(&keyboard_tasklet); | ||
1029 | } | ||
1030 | |||
1031 | #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ | 1014 | #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ |
1032 | defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ | 1015 | defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ |
1033 | defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ | 1016 | defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ |
@@ -1307,7 +1290,6 @@ static struct input_handle *kbd_connect(struct input_handler *handler, | |||
1307 | handle->name = "kbd"; | 1290 | handle->name = "kbd"; |
1308 | 1291 | ||
1309 | input_open_device(handle); | 1292 | input_open_device(handle); |
1310 | kbd_refresh_leds(handle); | ||
1311 | 1293 | ||
1312 | return handle; | 1294 | return handle; |
1313 | } | 1295 | } |
@@ -1318,6 +1300,24 @@ static void kbd_disconnect(struct input_handle *handle) | |||
1318 | kfree(handle); | 1300 | kfree(handle); |
1319 | } | 1301 | } |
1320 | 1302 | ||
1303 | /* | ||
1304 | * Start keyboard handler on the new keyboard by refreshing LED state to | ||
1305 | * match the rest of the system. | ||
1306 | */ | ||
1307 | static void kbd_start(struct input_handle *handle) | ||
1308 | { | ||
1309 | unsigned char leds = ledstate; | ||
1310 | |||
1311 | tasklet_disable(&keyboard_tasklet); | ||
1312 | if (leds != 0xff) { | ||
1313 | input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); | ||
1314 | input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); | ||
1315 | input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); | ||
1316 | input_sync(handle->dev); | ||
1317 | } | ||
1318 | tasklet_enable(&keyboard_tasklet); | ||
1319 | } | ||
1320 | |||
1321 | static struct input_device_id kbd_ids[] = { | 1321 | static struct input_device_id kbd_ids[] = { |
1322 | { | 1322 | { |
1323 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, | 1323 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, |
@@ -1338,6 +1338,7 @@ static struct input_handler kbd_handler = { | |||
1338 | .event = kbd_event, | 1338 | .event = kbd_event, |
1339 | .connect = kbd_connect, | 1339 | .connect = kbd_connect, |
1340 | .disconnect = kbd_disconnect, | 1340 | .disconnect = kbd_disconnect, |
1341 | .start = kbd_start, | ||
1341 | .name = "kbd", | 1342 | .name = "kbd", |
1342 | .id_table = kbd_ids, | 1343 | .id_table = kbd_ids, |
1343 | }; | 1344 | }; |
diff --git a/drivers/input/input.c b/drivers/input/input.c index c2e4d9bdcabf..7aeebb9071c2 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -209,8 +209,13 @@ EXPORT_SYMBOL(input_grab_device); | |||
209 | 209 | ||
210 | void input_release_device(struct input_handle *handle) | 210 | void input_release_device(struct input_handle *handle) |
211 | { | 211 | { |
212 | if (handle->dev->grab == handle) | 212 | if (handle->dev->grab == handle) { |
213 | handle->dev->grab = NULL; | 213 | handle->dev->grab = NULL; |
214 | |||
215 | list_for_each_entry(handle, &handle->dev->h_list, d_node) | ||
216 | if (handle->handler->start) | ||
217 | handle->handler->start(handle); | ||
218 | } | ||
214 | } | 219 | } |
215 | EXPORT_SYMBOL(input_release_device); | 220 | EXPORT_SYMBOL(input_release_device); |
216 | 221 | ||
@@ -954,8 +959,11 @@ int input_register_device(struct input_dev *dev) | |||
954 | list_for_each_entry(handler, &input_handler_list, node) | 959 | list_for_each_entry(handler, &input_handler_list, node) |
955 | if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) | 960 | if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) |
956 | if ((id = input_match_device(handler->id_table, dev))) | 961 | if ((id = input_match_device(handler->id_table, dev))) |
957 | if ((handle = handler->connect(handler, dev, id))) | 962 | if ((handle = handler->connect(handler, dev, id))) { |
958 | input_link_handle(handle); | 963 | input_link_handle(handle); |
964 | if (handler->start) | ||
965 | handler->start(handle); | ||
966 | } | ||
959 | 967 | ||
960 | input_wakeup_procfs_readers(); | 968 | input_wakeup_procfs_readers(); |
961 | 969 | ||
diff --git a/include/linux/input.h b/include/linux/input.h index 6e3afad26fa9..55e628e8805b 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
@@ -960,6 +960,26 @@ struct input_dev { | |||
960 | 960 | ||
961 | struct input_handle; | 961 | struct input_handle; |
962 | 962 | ||
963 | /** | ||
964 | * struct input_handler - implements one of interfaces for input devices | ||
965 | * @private: driver-specific data | ||
966 | * @event: event handler | ||
967 | * @connect: called when attaching a handler to an input device | ||
968 | * @disconnect: disconnects a handler from input device | ||
969 | * @start: starts handler for given handle. This function is called by | ||
970 | * input core right after connect() method and also when a process | ||
971 | * that "grabbed" a device releases it | ||
972 | * @fops: file operations this driver implements | ||
973 | * @minor: beginning of range of 32 minors for devices this driver | ||
974 | * can provide | ||
975 | * @name: name of the handler, to be shown in /proc/bus/input/handlers | ||
976 | * @id_table: pointer to a table of input_device_ids this driver can | ||
977 | * handle | ||
978 | * @blacklist: prointer to a table of input_device_ids this driver should | ||
979 | * ignore even if they match @id_table | ||
980 | * @h_list: list of input handles associated with the handler | ||
981 | * @node: for placing the driver onto input_handler_list | ||
982 | */ | ||
963 | struct input_handler { | 983 | struct input_handler { |
964 | 984 | ||
965 | void *private; | 985 | void *private; |
@@ -967,6 +987,7 @@ struct input_handler { | |||
967 | void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); | 987 | void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); |
968 | struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id); | 988 | struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id); |
969 | void (*disconnect)(struct input_handle *handle); | 989 | void (*disconnect)(struct input_handle *handle); |
990 | void (*start)(struct input_handle *handle); | ||
970 | 991 | ||
971 | const struct file_operations *fops; | 992 | const struct file_operations *fops; |
972 | int minor; | 993 | int minor; |