basic modification from way back
[powerpc.git] / drivers / char / keyboard.c
index c654a3e..1b09450 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/input.h>
 #include <linux/reboot.h>
 
-static void kbd_disconnect(struct input_handle *handle);
 extern void ctrl_alt_del(void);
 
 /*
@@ -110,7 +109,7 @@ struct kbd_struct kbd_table[MAX_NR_CONSOLES];
 static struct kbd_struct *kbd = kbd_table;
 
 struct vt_spawn_console vt_spawn_con = {
-       .lock = SPIN_LOCK_UNLOCKED,
+       .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
        .pid  = NULL,
        .sig  = 0,
 };
@@ -159,65 +158,41 @@ static int sysrq_alt_use;
 static int sysrq_alt;
 
 /*
- * Translation of scancodes to keycodes. We set them on only the first attached
- * keyboard - for per-keyboard setting, /dev/input/event is more useful.
+ * Translation of scancodes to keycodes. We set them on only the first
+ * keyboard in the list that accepts the scancode and keycode.
+ * Explanation for not choosing the first attached keyboard anymore:
+ *  USB keyboards for example have two event devices: one for all "normal"
+ *  keys and one for extra function keys (like "volume up", "make coffee",
+ *  etc.). So this means that scancodes for the extra function keys won't
+ *  be valid for the first event device, but will be for the second.
  */
 int getkeycode(unsigned int scancode)
 {
-       struct list_head *node;
-       struct input_dev *dev = NULL;
+       struct input_handle *handle;
+       int keycode;
+       int error = -ENODEV;
 
-       list_for_each(node, &kbd_handler.h_list) {
-               struct input_handle *handle = to_handle_h(node);
-               if (handle->dev->keycodesize) {
-                       dev = handle->dev;
-                       break;
-               }
+       list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
+               error = handle->dev->getkeycode(handle->dev, scancode, &keycode);
+               if (!error)
+                       return keycode;
        }
 
-       if (!dev)
-               return -ENODEV;
-
-       if (scancode >= dev->keycodemax)
-               return -EINVAL;
-
-       return INPUT_KEYCODE(dev, scancode);
+       return error;
 }
 
 int setkeycode(unsigned int scancode, unsigned int keycode)
 {
-       struct list_head *node;
-       struct input_dev *dev = NULL;
-       unsigned int i, oldkey;
+       struct input_handle *handle;
+       int error = -ENODEV;
 
-       list_for_each(node, &kbd_handler.h_list) {
-               struct input_handle *handle = to_handle_h(node);
-               if (handle->dev->keycodesize) {
-                       dev = handle->dev;
+       list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
+               error = handle->dev->setkeycode(handle->dev, scancode, keycode);
+               if (!error)
                        break;
-               }
        }
 
-       if (!dev)
-               return -ENODEV;
-
-       if (scancode >= dev->keycodemax)
-               return -EINVAL;
-       if (keycode < 0 || keycode > KEY_MAX)
-               return -EINVAL;
-       if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
-               return -EINVAL;
-
-       oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
-
-       clear_bit(oldkey, dev->keybit);
-       set_bit(keycode, dev->keybit);
-
-       for (i = 0; i < dev->keycodemax; i++)
-               if (INPUT_KEYCODE(dev,i) == oldkey)
-                       set_bit(oldkey, dev->keybit);
-
-       return 0;
+       return error;
 }
 
 /*
@@ -225,10 +200,9 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
  */
 static void kd_nosound(unsigned long ignored)
 {
-       struct list_head *node;
+       struct input_handle *handle;
 
-       list_for_each(node, &kbd_handler.h_list) {
-               struct input_handle *handle = to_handle_h(node);
+       list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
                if (test_bit(EV_SND, handle->dev->evbit)) {
                        if (test_bit(SND_TONE, handle->dev->sndbit))
                                input_inject_event(handle, EV_SND, SND_TONE, 0);
@@ -596,7 +570,6 @@ static void fn_spawn_con(struct vc_data *vc)
 static void fn_SAK(struct vc_data *vc)
 {
        struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
-       PREPARE_WORK(SAK_work, vc_SAK);
        schedule_work(SAK_work);
 }
 
@@ -1162,7 +1135,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
 
        if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
                if (emulate_raw(vc, keycode, !down << 7))
-                       if (keycode < BTN_MISC)
+                       if (keycode < BTN_MISC && printk_ratelimit())
                                printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
 
 #ifdef CONFIG_MAGIC_SYSRQ             /* Handle the SysRq Hack */
@@ -1286,11 +1259,11 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
  * likes it, it can open it and get events from it. In this (kbd_connect)
  * function, we should decide which VT to bind that keyboard to initially.
  */
-static struct input_handle *kbd_connect(struct input_handler *handler,
-                                       struct input_dev *dev,
-                                       const struct input_device_id *id)
+static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
+                       const struct input_device_id *id)
 {
        struct input_handle *handle;
+       int error;
        int i;
 
        for (i = KEY_RESERVED; i < BTN_MISC; i++)
@@ -1298,24 +1271,37 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
                        break;
 
        if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
-               return NULL;
+               return -ENODEV;
 
        handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
        if (!handle)
-               return NULL;
+               return -ENOMEM;
 
        handle->dev = dev;
        handle->handler = handler;
        handle->name = "kbd";
 
-       input_open_device(handle);
+       error = input_register_handle(handle);
+       if (error)
+               goto err_free_handle;
+
+       error = input_open_device(handle);
+       if (error)
+               goto err_unregister_handle;
+
+       return 0;
 
-       return handle;
+ err_unregister_handle:
+       input_unregister_handle(handle);
+ err_free_handle:
+       kfree(handle);
+       return error;
 }
 
 static void kbd_disconnect(struct input_handle *handle)
 {
        input_close_device(handle);
+       input_unregister_handle(handle);
        kfree(handle);
 }