Hi Ralf, This patch fixes the arrow keys (and all other keys that generate E0/E1 scancode prefixes on AT keyboards) by adding support for E0/E1 scancode prefixes to the dummy keyboard driver if CONFIG_INPUT=y. Rationale: When using the new input layer (i.e. with a USB keyboard or a custom input device), the input layer relies on kbd_translate() in the low-level keyboard driver to convert from AT-style scancodes to keycodes. If you don't have a PS/2 keyboard interface and don't compile in the PS/2 keyboard driver, you have to enable the dummy keyboard driver, which naively assumes that keycodes and scancodes are interchangeable. This is correct if you do not have a keyboard, but fails for prefixed scancodes if you do have a keyboard which uses the new input layer. --- linux-mips-2.4.x/drivers/char/dummy_keyb.c Tue Apr 1 16:33:31 2003 +++ linux/drivers/char/dummy_keyb.c Wed Apr 30 08:12:19 2003 @@ -23,9 +23,12 @@ * CONFIG_VT. * */ + +#include <linux/config.h> #include <linux/sched.h> #include <linux/errno.h> #include <linux/init.h> +#include <linux/input.h> void kbd_leds(unsigned char leds) { @@ -41,6 +44,84 @@ return scancode; } +#ifdef CONFIG_INPUT +static unsigned char e0_keys[128] = { + 0, 0, 0, KEY_KPCOMMA, 0, KEY_INTL3, 0, 0, /* 0x00-0x07 */ + 0, 0, 0, 0, KEY_LANG1, KEY_LANG2, 0, 0, /* 0x08-0x0f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ + 0, 0, 0, 0, KEY_KPENTER, KEY_RIGHTCTRL, KEY_VOLUMEUP, 0,/* 0x18-0x1f */ + 0, 0, 0, 0, 0, KEY_VOLUMEDOWN, KEY_MUTE, 0, /* 0x20-0x27 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ + 0, 0, 0, 0, 0, KEY_KPSLASH, 0, KEY_SYSRQ, /* 0x30-0x37 */ + KEY_RIGHTALT, KEY_BRIGHTNESSUP, KEY_BRIGHTNESSDOWN, + KEY_EJECTCD, 0, 0, 0, 0, /* 0x38-0x3f */ + 0, 0, 0, 0, 0, 0, 0, KEY_HOME, /* 0x40-0x47 */ + KEY_UP, KEY_PAGEUP, 0, KEY_LEFT, 0, KEY_RIGHT, 0, KEY_END, /* 0x48-0x4f */ + KEY_DOWN, KEY_PAGEDOWN, KEY_INSERT, KEY_DELETE, 0, 0, 0, 0, /* 0x50-0x57 */ + 0, 0, 0, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_COMPOSE, KEY_POWER, 0, /* 0x58-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, 0, 0, KEY_MACRO, /* 0x68-0x6f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ + 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ +}; + +int kbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + /* This code was copied from char/pc_keyb.c and will be + * superflous when the input layer is fully integrated. + * We don't need the high_keys handling, so this part + * has been removed. + */ + static int prev_scancode = 0; + + /* special prefix scancodes.. */ + if (scancode == 0xe0 || scancode == 0xe1) { + prev_scancode = scancode; + return 0; + } + + scancode &= 0x7f; + + if (prev_scancode) { + if (prev_scancode != 0xe0) { + if (prev_scancode == 0xe1 && scancode == 0x1d) { + prev_scancode = 0x100; + return 0; + } else if (prev_scancode == 0x100 && scancode == 0x45) { + *keycode = KEY_PAUSE; + prev_scancode = 0; + } else { + if (!raw_mode) + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n"); + prev_scancode = 0; + return 0; + } + } else { + prev_scancode = 0; + if (scancode == 0x2a || scancode == 0x36) + return 0; + } + if (e0_keys[scancode]) + *keycode = e0_keys[scancode]; + else { + if (!raw_mode) + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n", + scancode); + return 0; + } + } else { + switch (scancode) { + case 91: scancode = KEY_LINEFEED; break; + case 92: scancode = KEY_KPEQUAL; break; + case 125: scancode = KEY_INTL1; break; + } + *keycode = scancode; + } + return 1; +} + +#else int kbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) { @@ -48,6 +129,7 @@ return 1; } +#endif char kbd_unexpected_up(unsigned char keycode) { Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds