aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/keyboard.c39
-rw-r--r--drivers/input/input.c12
-rw-r--r--include/linux/input.h21
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
994static void kbd_bh(unsigned long dummy) 994static void kbd_bh(unsigned long dummy)
@@ -1011,23 +1011,6 @@ static void kbd_bh(unsigned long dummy)
1011 1011
1012DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); 1012DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
1013 1013
1014/*
1015 * This allows a newly plugged keyboard to pick the LED state.
1016 */
1017static 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 */
1307static 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
1321static struct input_device_id kbd_ids[] = { 1321static 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
210void input_release_device(struct input_handle *handle) 210void 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}
215EXPORT_SYMBOL(input_release_device); 220EXPORT_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
961struct input_handle; 961struct 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 */
963struct input_handler { 983struct 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;