From: Marvin Raaijmakers <[EMAIL PROTECTED]>

Currently it isn't possible to assign keycodes to keys of USB keyboards
by usign a userspace application. This is because USB keyboards do not
send scancodes, but HID usage codes. I have modified the hid-input
driver so that keycodes can be set to HID usage codes in exactly the
same way as keycodes are set to scancodes.
To make this possible I had to modify the input_dev structure (in
<linux/input.h>) by adding a "setkeycodes" member to it. This member is
a pointer to a function that sets the keycodes to scancodes (and HID
usage codes). Each driver has its own "setkeycodes" function and if a
driver does not provide the functionality to set keycodes, the pointer
will be NULL. The evdev_ioctl function will call the "setkeycode"
function if its cmd parameter is equal to EVIOCSKEYCODE.
All keyboard drivers now have a setkeycode function, including the
hid-input driver. Note that hid-usage codes are handled the same way as
scancodes.
The keycodemax, keycodesize and keycode member are not removed from the
input_dev structure so that the old way of setting a keycode (by using
the setkeycodes program) can still be used.

Below you can see a simple application for setting keycodes:
- - - - - - - - - - - - - - - - - - -
#include <linux/input.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

int
main (int argc, char **argv)
{
        int fd;
        struct input_keycode2scancode scan2key;

        if (argc < 4)
        {
                printf ("Usage: %s /dev/input/eventX scancode keycode\n", 
argv[0]);
                printf ("Where X = input device number\n");
                return 1;
        }

        if ((fd = open(argv[1], O_RDONLY)) < 0)
        {
                perror (argv[0]);
                return 1;
        }

        scan2key.scancode = (unsigned) strtol(argv[2], NULL, 0);
        scan2key.keycode = (unsigned) strtol(argv[3], NULL, 0);
        ioctl (fd, EVIOCSKEYCODE, &scan2key);

        return 0;
}
- - - - - - - - - - - - - - - - - - -

I hope my code will be implemented in the kernel, because with the
current code a lot of extra function keys on USB keyboards do not work
because they do not have a keycode. My code makes it possible to set a
keycode to such key, so that it will work.

Signed-off-by: Marvin Raaijmakers <[EMAIL PROTECTED]>
---

diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/evdev.c 
linux-source-2.6.15/drivers/input/evdev.c
--- linux-source-2.6.15-vanilla/drivers/input/evdev.c   2006-01-03 
04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/evdev.c   2006-06-04 17:17:16.000000000 
+0200
@@ -7,6 +7,12 @@
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  */
+ 
+/*
+ * 04 June 2006, Marvin Raaijmakers:
+ *   The setkeycode member function (of the input_dev struct) will be used in
+ *   the EVIOCSKEYCODE case in evdev_ioctl().
+ */
 
 #define EVDEV_MINOR_BASE       64
 #define EVDEV_MINORS           32
@@ -22,6 +28,8 @@
 #include <linux/device.h>
 #include <linux/compat.h>
 
+#define DEBUG
+
 struct evdev {
        int exist;
        int open;
@@ -296,6 +304,7 @@ static long evdev_ioctl(struct file *fil
        struct evdev *evdev = list->evdev;
        struct input_dev *dev = evdev->handle.dev;
        struct input_absinfo abs;
+       struct input_keycode2scancode keycode2scancode;
        void __user *p = (void __user *)arg;
        int __user *ip = (int __user *)arg;
        int i, t, u, v;
@@ -317,7 +326,16 @@ static long evdev_ioctl(struct file *fil
                        return 0;
 
                case EVIOCSKEYCODE:
-                       if (get_user(t, ip)) return -EFAULT;
+                       if (copy_from_user (&keycode2scancode, (const void 
__user *) arg, sizeof(struct input_keycode2scancode)))
+                       {
+                               return -EFAULT;
+                       }
+                       if (dev->setkeycode)
+                       {
+                               return EINVAL * (*dev->setkeycode)(dev, 
&keycode2scancode);
+                       }
+                       return 0;
+                       /*if (get_user(t, ip)) return -EFAULT;
                        if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) 
return -EINVAL;
                        if (get_user(v, ip + 1)) return -EFAULT;
                        if (v < 0 || v > KEY_MAX) return -EINVAL;
@@ -328,7 +346,7 @@ static long evdev_ioctl(struct file *fil
                        for (i = 0; i < dev->keycodemax; i++)
                                if (INPUT_KEYCODE(dev,i) == u)
                                        set_bit(u, dev->keybit);
-                       return 0;
+                       return 0;*/
 
                case EVIOCSFF:
                        if (dev->upload_effect) {
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/amikbd.c 
linux-source-2.6.15/drivers/input/keyboard/amikbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/amikbd.c 2006-01-03 
04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/amikbd.c 2006-06-04 
17:06:05.000000000 +0200
@@ -8,6 +8,10 @@
  */
 
 /*
+ * 04 June 2006, Marvin Raaijmakers: added amikbd_setkeycode()
+ */
+
+/*
  * Amiga keyboard driver for Linux/m68k
  */
 
@@ -157,6 +161,41 @@ static const char *amikbd_messages[8] = 
 
 static struct input_dev *amikbd_dev;
 
+
+static int
+amikbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       unsigned char   *keycode = dev->private;
+       unsigned int    keycode_max = ARRAY_SIZE(amikbd_keycode),
+                       i;
+       unsigned char   old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= keycode_max ||
+           keycode2scancode->keycode > 0xFF)
+       {
+               return -1;
+       }
+       old_keycode = keycode[keycode2scancode->scancode];
+       keycode[keycode2scancode->scancode] =  keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif 
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < keycode_max; i++)
+       {
+               if (keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
+
 static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
        unsigned char scancode, down;
@@ -217,6 +256,8 @@ static int __init amikbd_init(void)
        amikbd_dev->keycode = amikbd_keycode;
        amikbd_dev->keycodesize = sizeof(unsigned char);
        amikbd_dev->keycodemax = ARRAY_SIZE(amikbd_keycode);
+       amikbd_dev->private = amikbd_keycode;
+       amikbd_dev->setkeycode = amikbd_setkeycode;
 
        for (i = 0; i < 0x78; i++)
                if (amikbd_keycode[i])
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/atkbd.c 
linux-source-2.6.15/drivers/input/keyboard/atkbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/atkbd.c  2006-01-03 
04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/atkbd.c  2006-06-04 
17:05:44.000000000 +0200
@@ -5,6 +5,10 @@
  */
 
 /*
+ * 04 June 2006, Marvin Raaijmakers: added atkbd_setkeycode()
+ */
+
+/*
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
@@ -187,6 +191,7 @@ static struct {
  */
 
 struct atkbd {
+       struct default_keytable keytable;
 
        struct ps2dev ps2dev;
        struct input_dev *dev;
@@ -245,6 +250,40 @@ ATKBD_DEFINE_ATTR(softrepeat);
 ATKBD_DEFINE_ATTR(softraw);
 
 
+static int
+atkbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       struct atkbd    *keyboard = dev->private;
+       unsigned int    keycode_max = ARRAY_SIZE(atkbd_set2_keycode),
+                       i;
+       unsigned char   old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= keycode_max ||
+           keycode2scancode->keycode > 0xFF)
+       {
+               return -1;
+       }
+       old_keycode = keyboard->keycode[keycode2scancode->scancode];
+       keyboard->keycode[keycode2scancode->scancode] =  
keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif 
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < keycode_max; i++)
+       {
+               if (keyboard->keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
+
 static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int 
code, int value)
 {
        input_regs(dev, regs);
@@ -819,6 +858,12 @@ static void atkbd_set_device_attrs(struc
        input_dev->keycode = atkbd->keycode;
        input_dev->keycodesize = sizeof(unsigned char);
        input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
+       
+       atkbd->keytable.keycode = atkbd->keycode;
+       atkbd->keytable.keycodesize = sizeof(unsigned char);
+       atkbd->keytable.keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
+       
+       input_dev->setkeycode = atkbd_setkeycode;
 
        for (i = 0; i < 512; i++)
                if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/corgikbd.c 
linux-source-2.6.15/drivers/input/keyboard/corgikbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/corgikbd.c       
2006-01-03 04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/corgikbd.c       2006-06-04 
17:06:37.000000000 +0200
@@ -11,6 +11,10 @@
  *
  */
 
+/*
+ * 04 June 2006, Marvin Raaijmakers: added corgikbd_setkeycode()
+ */
+
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
@@ -83,6 +87,41 @@ struct corgikbd {
 #define KB_DISCHARGE_DELAY     10
 #define KB_ACTIVATE_DELAY      10
 
+
+static int
+corgikbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       struct corgikbd *keyboard = dev->private;
+       unsigned int    keycode_max = ARRAY_SIZE(corgikbd_keycode),
+                       i;
+       unsigned char   old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= keycode_max ||
+           keycode2scancode->keycode > 0xFF)
+       {
+               return -1;
+       }
+       old_keycode = keyboard->keycode[keycode2scancode->scancode];
+       keyboard->keycode[keycode2scancode->scancode] =  
keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif 
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < keycode_max; i++)
+       {
+               if (keyboard->keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
+
 /* Helper functions for reading the keyboard matrix
  * Note: We should really be using pxa_gpio_mode to alter GPDR but it
  *       requires a function call per GPIO bit which is excessive
@@ -328,6 +367,7 @@ static int __init corgikbd_probe(struct 
        input_dev->keycode = corgikbd->keycode;
        input_dev->keycodesize = sizeof(unsigned char);
        input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
+       input_dev->setkeycode = corgikbd_setkeycode;
 
        for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
                set_bit(corgikbd->keycode[i], input_dev->keybit);
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/hil_kbd.c 
linux-source-2.6.15/drivers/input/keyboard/hil_kbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/hil_kbd.c        
2006-01-03 04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/hil_kbd.c        2006-06-04 
17:07:24.000000000 +0200
@@ -31,6 +31,10 @@
  *
  */
 
+/*
+ * 04 June 2006, Marvin Raaijmakers: added hil_kbd_setkeycode()
+ */
+
 #include <linux/hil.h>
 #include <linux/input.h>
 #include <linux/serio.h>
@@ -69,6 +73,7 @@ struct hil_kbd {
        struct input_dev dev;
        struct serio *serio;
 
+       unsigned int *keycode;
        /* Input buffer and index for packets from HIL bus. */
        hil_packet data[HIL_KBD_MAX_LENGTH];
        int idx4; /* four counts per packet */
@@ -83,6 +88,39 @@ struct hil_kbd {
        struct semaphore sem;
 };
 
+
+static int
+hil_kbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       struct hil_kbd  *keyboard = dev->private;
+       unsigned int    i, old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= HIL_KEYCODES_SET1_TBLSIZE ||
+           keycode2scancode->keycode > KEY_MAX)
+       {
+               return -1;
+       }
+       old_keycode = keyboard->keycode[keycode2scancode->scancode];
+       keyboard->keycode[keycode2scancode->scancode] =  
keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif 
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
+       {
+               if (keyboard->keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
+
 /* Process a complete packet after transfer from the HIL */
 static void hil_kbd_process_record(struct hil_kbd *kbd)
 {
@@ -316,6 +354,9 @@ static int hil_kbd_connect(struct serio 
        kbd->dev.keycodemax     = HIL_KEYCODES_SET1_TBLSIZE;
        kbd->dev.keycodesize    = sizeof(hil_kbd_set1[0]);
        kbd->dev.keycode        = hil_kbd_set1;
+       kbd->keycode            = hil_kbd_set1;
+       kbd->setkeycode         = hil_kbd_setkeycode;
+       
        kbd->dev.name           = strlen(kbd->rnm) ? kbd->rnm : 
HIL_GENERIC_NAME;
        kbd->dev.phys           = "hpkbd/input0";       /* XXX */
 
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/lkkbd.c 
linux-source-2.6.15/drivers/input/keyboard/lkkbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/lkkbd.c  2006-01-03 
04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/lkkbd.c  2006-06-04 
17:09:35.000000000 +0200
@@ -7,6 +7,10 @@
  */
 
 /*
+ * 04 June 2006, Marvin Raaijmakers: added lkkbd_setkeycode()
+ */
+
+/*
  * DEC LK201 and LK401 keyboard driver for Linux (primary for DECstations
  * and VAXstations, but can also be used on any standard RS232 with an
  * adaptor).
@@ -334,6 +338,40 @@ response_name (unsigned char value)
 }
 #endif /* LKKBD_DEBUG */
 
+
+static int
+lkkbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       struct lkkbd    *keyboard = dev->private;
+       unsigned int    i;
+       lk_keycode_t    old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= LK_NUM_KEYCODES ||
+           keycode2scancode->keycode > KEY_MAX)
+       {
+               return -1;
+       }
+       old_keycode = keyboard->keycode[keycode2scancode->scancode];
+       keyboard->keycode[keycode2scancode->scancode] =  
keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif 
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < LK_NUM_KEYCODES; i++)
+       {
+               if (keyboard->keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
+
 /*
  * Calculate volume parameter byte for a given volume.
  */
@@ -689,6 +727,7 @@ lkkbd_connect (struct serio *serio, stru
        input_dev->keycode = lk->keycode;
        input_dev->keycodesize = sizeof (lk_keycode_t);
        input_dev->keycodemax = LK_NUM_KEYCODES;
+       input_dev->setkeycode = lkkbd_setkeycode;
        for (i = 0; i < LK_NUM_KEYCODES; i++)
                set_bit (lk->keycode[i], input_dev->keybit);
 
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/locomokbd.c 
linux-source-2.6.15/drivers/input/keyboard/locomokbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/locomokbd.c      
2006-01-03 04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/locomokbd.c      2006-06-04 
17:10:01.000000000 +0200
@@ -5,6 +5,10 @@
  */
 
 /*
+ * 04 June 2006, Marvin Raaijmakers: added locomokbd_setkeycode()
+ */
+
+/*
  * LoCoMo keyboard driver for Linux/ARM
  */
 
@@ -86,6 +90,39 @@ struct locomokbd {
        struct timer_list timer;
 };
 
+
+static int
+locomokbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       struct locomokbd        *keyboard = dev->private;
+       unsigned int            i;
+       unsigned char           old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= LOCOMOKBD_NUMKEYS ||
+           keycode2scancode->keycode > 0xFF)
+       {
+               return -1;
+       }
+       old_keycode = keyboard->keycode[keycode2scancode->scancode];
+       keyboard->keycode[keycode2scancode->scancode] =  
keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif 
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
+       {
+               if (keyboard->keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
 /* helper functions for reading the keyboard matrix */
 static inline void locomokbd_charge_all(unsigned long membase)
 {
@@ -240,6 +277,7 @@ static int locomokbd_probe(struct locomo
        input_dev->keycode = locomokbd->keycode;
        input_dev->keycodesize = sizeof(unsigned char);
        input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode);
+       input_dev->setkeycode = locomokbd_setkeycode;
 
        memcpy(locomokbd->keycode, locomokbd_keycode, 
sizeof(locomokbd->keycode));
        for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/maple_keyb.c 
linux-source-2.6.15/drivers/input/keyboard/maple_keyb.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/maple_keyb.c     
2006-01-03 04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/maple_keyb.c     2006-06-04 
14:58:40.000000000 +0200
@@ -112,6 +112,8 @@ static int dc_kbd_connect(struct maple_d
        for (i = 0; i < 255; i++)
                set_bit(dc_kbd_keycode[i], input_dev->keybit);
        clear_bit(0, input_dev->keybit);
+       
+       input_dev->setkeycode = NULL; /* There is no function to keycodes */
 
        input_register_device(kbd->dev);
 
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/newtonkbd.c 
linux-source-2.6.15/drivers/input/keyboard/newtonkbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/newtonkbd.c      
2006-01-03 04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/newtonkbd.c      2006-06-04 
17:10:38.000000000 +0200
@@ -3,6 +3,10 @@
  */
 
 /*
+ * 04 June 2006, Marvin Raaijmakers: added nkbd_setkeycode()
+ */
+
+/*
  * Newton keyboard driver for Linux
  */
 
@@ -64,6 +68,40 @@ struct nkbd {
        char phys[32];
 };
 
+
+static int
+nkbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       struct nkbd     *keyboard = dev->private;
+       unsigned int    i, keycode_max = ARRAY_SIZE(nkbd_keycode);
+       unsigned char   old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= keycode_max ||
+           keycode2scancode->keycode > 0xFF)
+       {
+               return -1;
+       }
+       old_keycode = keyboard->keycode[keycode2scancode->scancode];
+       keyboard->keycode[keycode2scancode->scancode] =  
keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < keycode_max; i++)
+       {
+               if (keyboard->keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
+
 static irqreturn_t nkbd_interrupt(struct serio *serio,
                unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
@@ -112,6 +150,7 @@ static int nkbd_connect(struct serio *se
        input_dev->keycode = nkbd->keycode;
        input_dev->keycodesize = sizeof(unsigned char);
        input_dev->keycodemax = ARRAY_SIZE(nkbd_keycode);
+       input_dev->setkeycode = nkbd_setkeycode;
        for (i = 0; i < 128; i++)
                set_bit(nkbd->keycode[i], input_dev->keybit);
        clear_bit(0, input_dev->keybit);
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/spitzkbd.c 
linux-source-2.6.15/drivers/input/keyboard/spitzkbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/spitzkbd.c       
2006-01-03 04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/spitzkbd.c       2006-06-04 
17:10:58.000000000 +0200
@@ -11,6 +11,10 @@
  *
  */
 
+/*
+ * 04 June 2006, Marvin Raaijmakers: added spitzkbd_setkeycode()
+ */
+
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
@@ -99,6 +103,41 @@ struct spitzkbd {
 #define KB_DISCHARGE_DELAY     10
 #define KB_ACTIVATE_DELAY      10
 
+
+static int
+spitzkbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       struct spitzkbd *keyboard = dev->private;
+       unsigned int    keycode_max = ARRAY_SIZE(spitzkbd_keycode),
+                       i;
+       unsigned char   old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= keycode_max ||
+           keycode2scancode->keycode > 0xFF)
+       {
+               return -1;
+       }
+       old_keycode = keyboard->keycode[keycode2scancode->scancode];
+       keyboard->keycode[keycode2scancode->scancode] =  
keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif 
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < keycode_max; i++)
+       {
+               if (keyboard->keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
+
 /* Helper functions for reading the keyboard matrix
  * Note: We should really be using pxa_gpio_mode to alter GPDR but it
  *       requires a function call per GPIO bit which is excessive
@@ -391,6 +430,7 @@ static int __init spitzkbd_probe(struct 
        input_dev->keycode = spitzkbd->keycode;
        input_dev->keycodesize = sizeof(unsigned char);
        input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode);
+       input_dev->setkeycode = spitzkbd_setkeycode;
 
        memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
        for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/sunkbd.c 
linux-source-2.6.15/drivers/input/keyboard/sunkbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/sunkbd.c 2006-01-03 
04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/sunkbd.c 2006-06-04 
17:11:18.000000000 +0200
@@ -5,6 +5,10 @@
  */
 
 /*
+ * 04 June 2006, Marvin Raaijmakers: added sunkbd_setkeycode()
+ */
+
+/*
  * Sun keyboard driver for Linux
  */
 
@@ -88,6 +92,41 @@ struct sunkbd {
        volatile s8 layout;
 };
 
+
+static int
+sunkbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       struct sunkbd   *keyboard = dev->private;
+       unsigned int    keycode_max = ARRAY_SIZE(sunkbd_keycode),
+                       i;
+       unsigned char   old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= keycode_max ||
+           keycode2scancode->keycode > 0xFF)
+       {
+               return -1;
+       }
+       old_keycode = keyboard->keycode[keycode2scancode->scancode];
+       keyboard->keycode[keycode2scancode->scancode] =  
keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif 
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < keycode_max; i++)
+       {
+               if (keyboard->keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
+
 /*
  * sunkbd_interrupt() is called by the low level driver when a character
  * is received.
@@ -283,6 +322,7 @@ static int sunkbd_connect(struct serio *
        input_dev->keycode = sunkbd->keycode;
        input_dev->keycodesize = sizeof(unsigned char);
        input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode);
+       input_dev->setkeycode = sunkbd_setkeycode;
        for (i = 0; i < 128; i++)
                set_bit(sunkbd->keycode[i], input_dev->keybit);
        clear_bit(0, input_dev->keybit);
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/input/keyboard/xtkbd.c 
linux-source-2.6.15/drivers/input/keyboard/xtkbd.c
--- linux-source-2.6.15-vanilla/drivers/input/keyboard/xtkbd.c  2006-01-03 
04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/input/keyboard/xtkbd.c  2006-06-04 
17:11:30.000000000 +0200
@@ -5,6 +5,10 @@
  */
 
 /*
+ * 04 June 2006, Marvin Raaijmakers: added xtkbd_setkeycode()
+ */
+
+/*
  * XT keyboard driver for Linux
  */
 
@@ -63,6 +67,41 @@ struct xtkbd {
        char phys[32];
 };
 
+
+static int
+xtkbd_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+{
+       struct xtkbd    *keyboard = dev->private;
+       unsigned int    keycode_max = ARRAY_SIZE(xtkbd_keycode),
+                       i;
+       unsigned char   old_keycode;
+       
+       if (keycode2scancode->scancode < 0 ||
+           keycode2scancode->scancode >= keycode_max ||
+           keycode2scancode->keycode > 0xFF)
+       {
+               return -1;
+       }
+       old_keycode = keyboard->keycode[keycode2scancode->scancode];
+       keyboard->keycode[keycode2scancode->scancode] =  
keycode2scancode->keycode;
+#ifdef DEBUG
+       printk (KERN_DEBUG "Assigned keycode %d to scancode %x\n",
+               keycode2scancode->keycode, keycode2scancode->scancode);
+#endif 
+       clear_bit (old_keycode, dev->keybit);
+       set_bit (keycode2scancode->keycode, dev->keybit);
+       for (i = 0; i < keycode_max; i++)
+       {
+               if (keyboard->keycode[i] == old_keycode)
+               {
+                       set_bit(old_keycode, dev->keybit);
+                       break;
+               }
+       }
+       return 0;
+}
+
+
 static irqreturn_t xtkbd_interrupt(struct serio *serio,
        unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
@@ -116,6 +155,7 @@ static int xtkbd_connect(struct serio *s
        input_dev->keycode = xtkbd->keycode;
        input_dev->keycodesize = sizeof(unsigned char);
        input_dev->keycodemax = ARRAY_SIZE(xtkbd_keycode);
+       input_dev->setkeycode = xtkbd_setkeycode;
 
        for (i = 0; i < 255; i++)
                set_bit(xtkbd->keycode[i], input_dev->keybit);
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/drivers/usb/input/hid-input.c 
linux-source-2.6.15/drivers/usb/input/hid-input.c
--- linux-source-2.6.15-vanilla/drivers/usb/input/hid-input.c   2006-01-03 
04:21:10.000000000 +0100
+++ linux-source-2.6.15/drivers/usb/input/hid-input.c   2006-06-04 
17:21:30.000000000 +0200
@@ -26,6 +26,10 @@
  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
+/*
+ * Marvin Raaijmakers March 2006: Added hidinput_setkeycode()
+ */
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
@@ -73,6 +77,90 @@ static struct {
 #define map_key_clear(c)       do { map_key(c); clear_bit(c, bit); } while (0)
 #define map_ff_effect(c)       do { set_bit(c, input->ffbit); } while (0)
 
+
+/* The for_each_hid_usage() marco can be used for iteration over all
+ * hid usages in all fields in all reports of the hid_device pointed
+ * to by hid_ptr.
+ * usage_ptr   - hid_usage to use as a loop counter. Type: struct hid_usage *
+ * hid_ptr     - Points to the hid_device to read the usages from.
+ *               Type: struct hid_device *
+ * i,j,k       - Integers that will be used internally by this macro. Type: int
+ * report_ptr  - A pointer that will be used internally by this macro.
+ *               Type: struct hid_report *
+ */
+#define for_each_hid_usage(usage_ptr, hid_ptr, i, j, k, report_ptr) \
+       for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) \
+               list_for_each_entry (report, 
&hid_ptr->report_enum[k].report_list, list)\
+                       for (i = 0; i < report->maxfield; i++) \
+                               for ( j = 0, usage_ptr = 
report->field[i]->usage; j < report->field[i]->maxusage; j++, usage_ptr++)
+
+
+
+static int
+hidinput_setkeycode (struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode)
+/*
+Input:
+       dev                     - Must point to a input_dev structure of an HID
+                                 device
+       keycode2scancode        - The address of the structure that contains the
+                                 scancode and the keycode
+Output:
+       dev->private            - The keycode will be set to the hid_usage with 
the
+                                 correct scancode.
+Returns:
+       -1 whe no matching key was found, keycode2scancode->keycode >= KEY_MAX 
or
+       the matching key is not of type EV_KEY (so it is not really a key). 0 is
+       returned when the keycode was successfully set.
+Description:
+       The keycode in the structure, pointed to by keycode2scancode, will be 
set to
+       the key of the hid_device, pointed to by dev->private, from which the 
hid
+       usage code is equal to keycode2scancode->scancode.
+*/
+{
+       struct hid_device *hid = dev->private;
+       struct hid_report *report;
+       struct hid_usage *usage;
+       int i, j, k;
+       _KEYCODE old_keycode;
+       
+       if (keycode2scancode->keycode >= KEY_MAX)
+       {
+               return -1;
+       }
+       for_each_hid_usage (usage, hid, i, j, k, report)
+       {
+               if ((usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == 
keycode2scancode->scancode)
+               {
+                       if (usage->type != EV_KEY)
+                       {
+                               return -1;
+                       }
+                       old_keycode = usage->code;
+                       usage->code = keycode2scancode->keycode;
+                       
+                       clear_bit (old_keycode, dev->keybit);
+                       set_bit (usage->code, dev->keybit);
+#ifdef DEBUG
+                       printk (KERN_DEBUG "Assigned keycode %d to HID usage 
code %x\n",
+                               keycode2scancode->keycode, 
keycode2scancode->scancode);
+#endif
+                       /* Set the keybit for the old keycode if the old 
keycode is used
+                        * by another key */
+                       for_each_hid_usage (usage, hid, i, j, k, report)
+                       {
+                               if (usage->type == EV_KEY && usage->code == 
old_keycode)
+                               {
+                                       set_bit (old_keycode, dev->keybit);
+                                       return (0);
+                               }
+                       }
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+
 static void hidinput_configure_usage(struct hid_input *hidinput, struct 
hid_field *field,
                                     struct hid_usage *usage)
 {
@@ -643,7 +731,9 @@ int hidinput_connect(struct hid_device *
                                input_dev->uniq = hid->uniq;
                                usb_to_input_id(dev, &input_dev->id);
                                input_dev->cdev.dev = &hid->intf->dev;
-
+                               
+                               input_dev->setkeycode = hidinput_setkeycode;
+                               
                                hidinput->input = input_dev;
                                list_add_tail(&hidinput->list, &hid->inputs);
                        }
diff -uprN -X linux-source-2.6.15-vanilla/Documentation/dontdiff 
linux-source-2.6.15-vanilla/include/linux/input.h 
linux-source-2.6.15/include/linux/input.h
--- linux-source-2.6.15-vanilla/include/linux/input.h   2006-01-03 
04:21:10.000000000 +0100
+++ linux-source-2.6.15/include/linux/input.h   2006-06-04 15:12:55.000000000 
+0200
@@ -55,6 +55,16 @@ struct input_absinfo {
        __s32 flat;
 };
 
+/* begin new */
+typedef unsigned int _KEYCODE;
+typedef unsigned int _SCANCODE;
+
+struct input_keycode2scancode {
+       _KEYCODE        keycode;
+       _SCANCODE       scancode;
+};
+/* end new */
+
 #define EVIOCGVERSION          _IOR('E', 0x01, int)                    /* get 
driver version */
 #define EVIOCGID               _IOR('E', 0x02, struct input_id)        /* get 
device ID */
 #define EVIOCGKEYCODE          _IOR('E', 0x04, int[2])                 /* get 
keycode */
@@ -833,6 +843,13 @@ struct ff_effect {
                }                                               \
                __old; })
 
+
+struct default_keytable {
+       unsigned int keycodemax;
+       unsigned int keycodesize;
+       void *keycode;
+};
+
 struct input_dev {
 
        void *private;
@@ -856,6 +873,7 @@ struct input_dev {
        unsigned int keycodemax;
        unsigned int keycodesize;
        void *keycode;
+       int (*setkeycode)(struct input_dev *dev, struct input_keycode2scancode 
*keycode2scancode); /* new */
 
        unsigned int repeat_key;
        struct timer_list timer;



-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to