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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel