Parent repository is bk://kernel.bkbits.net/vojtech/input ======== ChangeSet 1.1636 ======== D 1.1636 04/03/02 17:54:08-08:00 akpm@mnm.(none) 37865 37862 0/0/1 P ChangeSet C Merge mnm.(none):/usr/src/bk25 into mnm.(none):/usr/src/bk-input ------------------------------------------------ diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Tue Mar 2 17:55:37 2004 +++ b/Documentation/kernel-parameters.txt Tue Mar 2 17:55:37 2004 @@ -174,11 +174,18 @@ atascsi= [HW,SCSI] Atari SCSI - atkbd.set= [HW] Select keyboard code set - Format: + atkbd.extra= [HW] Enable extra LEDs and keys on IBM RapidAccess, EzKey + and similar keyboards + + atkbd.reset= [HW] Reset keyboard during initialization + + atkbd.set= [HW] Select keyboard code set + Format: (2 = AT (default) 3 = PS/2) + + atkbd.scroll= [HW] Enable scroll wheel on MS Office and similar keyboards + atkbd.softrepeat= [HW] Use software keyboard repeat - atkbd.reset= [HW] Reset keyboard during initialization autotest [IA64] diff -Nru a/Documentation/usb/acm.txt b/Documentation/usb/acm.txt --- a/Documentation/usb/acm.txt Tue Mar 2 17:55:37 2004 +++ b/Documentation/usb/acm.txt Tue Mar 2 17:55:37 2004 @@ -28,7 +28,7 @@ 1. Usage ~~~~~~~~ - The drivers/usb/acm.c drivers works with USB modems and USB ISDN terminal + The drivers/usb/class/cdc-acm.c drivers works with USB modems and USB ISDN terminal adapters that conform to the Universal Serial Bus Communication Device Class Abstract Control Model (USB CDC ACM) specification. @@ -65,9 +65,9 @@ To use the modems you need these modules loaded: - usbcore.o - usb-[uo]hci.o or uhci.o - acm.o + usbcore.ko + uhci-hcd.ko ohci-hcd.ko or ehci-hcd.ko + cdc-acm.ko After that, the modem[s] should be accessible. You should be able to use minicom, ppp and mgetty with them. diff -Nru a/arch/arm26/Kconfig b/arch/arm26/Kconfig --- a/arch/arm26/Kconfig Tue Mar 2 17:55:37 2004 +++ b/arch/arm26/Kconfig Tue Mar 2 17:55:37 2004 @@ -198,11 +198,6 @@ source "drivers/char/Kconfig" -config KBDMOUSE - bool - depends on ARCH_ACORN && BUSMOUSE=y - default y - source "drivers/media/Kconfig" source "fs/Kconfig" diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig --- a/drivers/char/Kconfig Tue Mar 2 17:55:37 2004 +++ b/drivers/char/Kconfig Tue Mar 2 17:55:37 2004 @@ -599,30 +599,6 @@ bool "Support for console on line printer" depends on PC9800_OLDLP - -menu "Mice" - -config BUSMOUSE - tristate "Bus Mouse Support" - ---help--- - Say Y here if your machine has a bus mouse as opposed to a serial - mouse. Most people have a regular serial MouseSystem or - Microsoft mouse (made by Logitech) that plugs into a COM port - (rectangular with 9 or 25 pins). These people say N here. - - If you have a laptop, you either have to check the documentation or - experiment a bit to find out whether the trackball is a serial mouse - or not; it's best to say Y here for you. - - This is the generic bus mouse driver code. If you have a bus mouse, - you will have to say Y here and also to the specific driver for your - mouse below. - - To compile this driver as a module, choose M here: the - module will be called busmouse. - -endmenu - config QIC02_TAPE tristate "QIC-02 tape support" help diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile Tue Mar 2 17:55:37 2004 +++ b/drivers/char/Makefile Tue Mar 2 17:55:37 2004 @@ -49,7 +49,6 @@ obj-$(CONFIG_TIPAR) += tipar.o obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o -obj-$(CONFIG_BUSMOUSE) += busmouse.o obj-$(CONFIG_DTLK) += dtlk.o obj-$(CONFIG_R3964) += n_r3964.o obj-$(CONFIG_APPLICOM) += applicom.o diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c --- a/drivers/input/evdev.c Tue Mar 2 17:55:37 2004 +++ b/drivers/input/evdev.c Tue Mar 2 17:55:37 2004 @@ -209,7 +209,7 @@ struct evdev *evdev = list->evdev; struct input_dev *dev = evdev->handle.dev; struct input_absinfo abs; - int t, u, v; + int i, t, u, v; if (!evdev->exist) return -ENODEV; @@ -234,6 +234,9 @@ u = SET_INPUT_KEYCODE(dev, t, v); clear_bit(u, dev->keybit); set_bit(v, dev->keybit); + for (i = 0; i < dev->keycodemax; i++) + if (INPUT_KEYCODE(dev,i) == u) + set_bit(u, dev->keybit); return 0; case EVIOCSFF: diff -Nru a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c --- a/drivers/input/gameport/ns558.c Tue Mar 2 17:55:37 2004 +++ b/drivers/input/gameport/ns558.c Tue Mar 2 17:55:37 2004 @@ -77,7 +77,7 @@ * No one should be using this address. */ - if (check_region(io, 1)) + if (!request_region(io, 1, "ns558-isa")) return; /* @@ -89,7 +89,8 @@ outb(~c & ~3, io); if (~(u = v = inb(io)) & 3) { outb(c, io); - return; + i = 0; + goto out; } /* * After a trigger, there must be at least some bits changing. @@ -99,7 +100,8 @@ if (u == v) { outb(c, io); - return; + i = 0; + goto out; } wait_ms(3); /* @@ -110,7 +112,8 @@ for (i = 0; i < 1000; i++) if ((u ^ inb(io)) & 0xf) { outb(c, io); - return; + i = 0; + goto out; } /* * And now find the number of mirrors of the port. @@ -118,7 +121,9 @@ for (i = 1; i < 5; i++) { - if (check_region(io & (-1 << i), (1 << i))) /* Don't disturb anyone */ + release_region(io & (-1 << (i-1)), (1 << (i-1))); + + if (!request_region(io & (-1 << i), (1 << i), "ns558-isa")) /* Don't disturb anyone */ break; outb(0xff, io & (-1 << i)); @@ -126,18 +131,25 @@ if (inb(io & (-1 << i)) != inb((io & (-1 << i)) + (1 << i) - 1)) b++; wait_ms(3); - if (b > 300) /* We allow 30% difference */ + if (b > 300) { /* We allow 30% difference */ + release_region(io & (-1 << i), (1 << i)); break; + } } i--; + if (i != 4) { + if (!request_region(io & (-1 << i), (1 << i), "ns558-isa")) + return; + } + if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) { printk(KERN_ERR "ns558: Memory allocation failed.\n"); - return; + goto out; } - memset(port, 0, sizeof(struct ns558)); - + memset(port, 0, sizeof(struct ns558)); + port->type = NS558_ISA; port->size = (1 << i); port->gameport.io = io; @@ -148,8 +160,6 @@ sprintf(port->phys, "isa%04x/gameport0", io & (-1 << i)); sprintf(port->name, "NS558 ISA"); - request_region(io & (-1 << i), (1 << i), "ns558-isa"); - gameport_register_port(&port->gameport); printk(KERN_INFO "gameport: NS558 ISA at %#x", port->gameport.io); @@ -157,6 +167,9 @@ printk(" speed %d kHz\n", port->gameport.speed); list_add(&port->node, &ns558_list); + return; +out: + release_region(io & (-1 << i), (1 << i)); } #ifdef CONFIG_PNP diff -Nru a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig --- a/drivers/input/keyboard/Kconfig Tue Mar 2 17:55:37 2004 +++ b/drivers/input/keyboard/Kconfig Tue Mar 2 17:55:37 2004 @@ -17,6 +17,7 @@ depends on INPUT && INPUT_KEYBOARD select SERIO select SERIO_I8042 if PC + select SERIO_GSCPS2 if GSC help Say Y here if you want to use a standard AT or PS/2 keyboard. Usually you'll need this, unless you have a different type keyboard (USB, ADB diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c --- a/drivers/input/keyboard/atkbd.c Tue Mar 2 17:55:37 2004 +++ b/drivers/input/keyboard/atkbd.c Tue Mar 2 17:55:37 2004 @@ -37,14 +37,13 @@ static int atkbd_set = 2; module_param_named(set, atkbd_set, int, 0); -MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3, 4)"); +MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)"); + #if defined(__i386__) || defined(__x86_64__) || defined(__hppa__) static int atkbd_reset; #else static int atkbd_reset = 1; #endif -static int atkbd_softrepeat; - module_param_named(reset, atkbd_reset, bool, 0); MODULE_PARM_DESC(reset, "Reset keyboard during initialization"); @@ -52,6 +51,14 @@ module_param_named(softrepeat, atkbd_softrepeat, bool, 0); MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat"); +static int atkbd_scroll; +module_param_named(scroll, atkbd_scroll, bool, 0); +MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards"); + +static int atkbd_extra; +module_param_named(extra, atkbd_extra, bool, 0); +MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards"); + /* * Scancode to keycode tables. These are just the default setting, and * are loadable via an userland utility. @@ -127,11 +134,11 @@ #define ATKBD_CMD_EX_SETLEDS 0x20eb #define ATKBD_CMD_OK_GETID 0x02e8 + #define ATKBD_RET_ACK 0xfa #define ATKBD_RET_NAK 0xfe #define ATKBD_RET_BAT 0xaa #define ATKBD_RET_EMUL0 0xe0 -#define ATKBD_RET_EMULX 0x80 #define ATKBD_RET_EMUL1 0xe1 #define ATKBD_RET_RELEASE 0xf0 #define ATKBD_RET_HANGUEL 0xf1 @@ -141,6 +148,22 @@ #define ATKBD_KEY_UNKNOWN 0 #define ATKBD_KEY_NULL 255 +#define ATKBD_SCR_1 254 +#define ATKBD_SCR_2 253 +#define ATKBD_SCR_4 252 +#define ATKBD_SCR_8 251 +#define ATKBD_SCR_CLICK 250 + +#define ATKBD_SPECIAL 250 + +static unsigned char atkbd_scroll_keys[5][2] = { + { ATKBD_SCR_1, 0x45 }, + { ATKBD_SCR_2, 0x29 }, + { ATKBD_SCR_4, 0x36 }, + { ATKBD_SCR_8, 0x27 }, + { ATKBD_SCR_CLICK, 0x60 }, +}; + /* * The atkbd control structure */ @@ -155,6 +178,7 @@ unsigned char cmdbuf[4]; unsigned char cmdcnt; unsigned char set; + unsigned char extra; unsigned char release; int lastkey; volatile signed char ack; @@ -189,6 +213,7 @@ { struct atkbd *atkbd = serio->private; unsigned int code = data; + int scroll = 0, click = -1; int value; #ifdef ATKBD_DEBUG @@ -284,6 +309,21 @@ else printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x ' to make it known.\n", code & 0x80 ? "e0" : "", code & 0x7f); break; + case ATKBD_SCR_1: + scroll = 1 - atkbd->release * 2; + break; + case ATKBD_SCR_2: + scroll = 2 - atkbd->release * 4; + break; + case ATKBD_SCR_4: + scroll = 4 - atkbd->release * 8; + break; + case ATKBD_SCR_8: + scroll = 8 - atkbd->release * 16; + break; + case ATKBD_SCR_CLICK: + click = !atkbd->release; + break; default: value = atkbd->release ? 0 : (1 + (!atkbd_softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); @@ -305,6 +345,13 @@ atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value); } + if (scroll || click != -1) { + input_regs(&atkbd->dev, regs); + input_report_key(&atkbd->dev, BTN_MIDDLE, click); + input_report_rel(&atkbd->dev, REL_WHEEL, scroll); + input_sync(&atkbd->dev); + } + atkbd->release = 0; out: return IRQ_HANDLED; @@ -420,7 +467,7 @@ | (test_bit(LED_CAPSL, dev->led) ? 4 : 0); atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS); - if (atkbd->set == 4) { + if (atkbd->extra) { param[0] = 0; param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0) | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0) @@ -529,21 +576,22 @@ return 3; } - if (atkbd_set != 2) - if (!atkbd_command(atkbd, param, ATKBD_CMD_OK_GETID)) { - atkbd->id = param[0] << 8 | param[1]; + if (atkbd_extra) { + param[0] = 0x71; + if (!atkbd_command(atkbd, param, ATKBD_CMD_EX_ENABLE)) { + atkbd->extra = 1; return 2; } - - if (atkbd_set == 4) { - param[0] = 0x71; - if (!atkbd_command(atkbd, param, ATKBD_CMD_EX_ENABLE)) - return 4; } if (atkbd_set != 3) return 2; + if (!atkbd_command(atkbd, param, ATKBD_CMD_OK_GETID)) { + atkbd->id = param[0] << 8 | param[1]; + return 2; + } + param[0] = 3; if (atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET)) return 2; @@ -696,24 +744,32 @@ atkbd->id = 0xab00; } - if (atkbd->set == 4) { + if (atkbd->extra) { atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC); - sprintf(atkbd->name, "AT Set 2 Extended keyboard"); + sprintf(atkbd->name, "AT Set 2 Extra keyboard"); } else sprintf(atkbd->name, "AT %s Set %d keyboard", atkbd->translated ? "Translated" : "Raw", atkbd->set); sprintf(atkbd->phys, "%s/input0", serio->phys); + if (atkbd_scroll) { + for (i = 0; i < 5; i++) + atkbd_set2_keycode[atkbd_scroll_keys[i][1]] = atkbd_scroll_keys[i][0]; + atkbd->dev.evbit[0] |= BIT(EV_REL); + atkbd->dev.relbit[0] = BIT(REL_WHEEL); + set_bit(BTN_MIDDLE, atkbd->dev.keybit); + } + if (atkbd->translated) { for (i = 0; i < 128; i++) { atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80]; } - } else if (atkbd->set == 2) { - memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode)); - } else { + } else if (atkbd->set == 3) { memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode)); + } else { + memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode)); } atkbd->dev.name = atkbd->name; @@ -724,7 +780,7 @@ atkbd->dev.id.version = atkbd->id; for (i = 0; i < 512; i++) - if (atkbd->keycode[i] && atkbd->keycode[i] < 255) + if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) set_bit(atkbd->keycode[i], atkbd->dev.keybit); input_register_device(&atkbd->dev); @@ -741,45 +797,19 @@ { struct atkbd *atkbd = serio->private; struct serio_dev *dev = serio->dev; - int i; - if (!dev) { - printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); - return -1; - } + if (!dev) { + printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); + return -1; + } if (atkbd->write) { if (atkbd_probe(atkbd)) return -1; - - atkbd->set = atkbd_set_3(atkbd); + if (atkbd->set != atkbd_set_3(atkbd)) + return -1; atkbd_enable(atkbd); - } else { - atkbd->set = 2; - atkbd->id = 0xab00; - } - - /* - * Here we probably should check if the keyboard has the same set that - * it had before and bail out if it's different. But this will most likely - * cause new keyboard device be created... and for the user it will look - * like keyboard is lost - */ - - if (atkbd->translated) { - for (i = 0; i < 128; i++) { - atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; - atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80]; - } - } else if (atkbd->set == 2) { - memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode)); - } else { - memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode)); } - - for (i = 0; i < 512; i++) - if (atkbd->keycode[i] && atkbd->keycode[i] < 255) - set_bit(atkbd->keycode[i], atkbd->dev.keybit); return 0; } diff -Nru a/drivers/input/keyboard/hpps2atkbd.h b/drivers/input/keyboard/hpps2atkbd.h --- a/drivers/input/keyboard/hpps2atkbd.h Tue Mar 2 17:55:37 2004 +++ b/drivers/input/keyboard/hpps2atkbd.h Tue Mar 2 17:55:37 2004 @@ -4,14 +4,9 @@ * Copyright (c) 2004 Helge Deller * Copyright (c) 2002 Laurent Canet * Copyright (c) 2002 Thibaut Varene + * Copyright (c) 2000 Xavier Debacker * - * based on linux-2.4's hp_mouse.c & hp_keyb.c - * Copyright (c) 1999 Alex deVries - * Copyright (c) 1999-2000 Philipp Rumpf - * Copyright (c) 2000 Xavier Debacker - * Copyright (c) 2000-2001 Thomas Marteau - * - * HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations + * HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations & Laptops * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -19,87 +14,100 @@ */ -#define KBD_UNKNOWN 0 - -/* Raw SET 2 scancode table */ +/* undefine if you have a RDI PRECISIONBOOK */ +#define STANDARD_KEYBOARD -#if 0 - /* conflicting keys between a RDI Precisionbook keyboard and a normal HP keyboard */ - keytable[0x07] = KEY_F1; /* KEY_F12 */ - keytable[0x11] = KEY_LEFTCTRL; /* KEY_LEFTALT */ - keytable[0x14] = KEY_CAPSLOCK; /* KEY_LEFTCTRL */ - keytable[0x61] = KEY_LEFT; /* KEY_102ND */ +#if defined(STANDARD_KEYBOARD) +# define CONFLICT(x,y) x +#else +# define CONFLICT(x,y) y #endif +/* sadly RDI (Tadpole) decided to ship a different keyboard layout + than HP for their PS/2 laptop keyboard which leads to conflicting + keycodes between a normal HP PS/2 keyboard and a RDI Precisionbook. + HP: RDI: */ +#define C_07 CONFLICT( KEY_F12, KEY_F1 ) +#define C_11 CONFLICT( KEY_LEFTALT, KEY_LEFTCTRL ) +#define C_14 CONFLICT( KEY_LEFTCTRL, KEY_CAPSLOCK ) +#define C_58 CONFLICT( KEY_CAPSLOCK, KEY_RIGHTCTRL ) +#define C_61 CONFLICT( KEY_102ND, KEY_LEFT ) -static unsigned char atkbd_set2_keycode[512] = { +/* Raw SET 2 scancode table */ - /* 00 */ KBD_UNKNOWN, KEY_F9, KBD_UNKNOWN, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F1, - /* 08 */ KEY_ESC, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_GRAVE, KEY_F2, - /* 10 */ KBD_UNKNOWN, KEY_LEFTCTRL, KEY_LEFTSHIFT, KBD_UNKNOWN, KEY_CAPSLOCK, KEY_Q, KEY_1, KEY_F3, - /* 18 */ KBD_UNKNOWN, KEY_LEFTALT, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_F4, - /* 20 */ KBD_UNKNOWN, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_F5, - /* 28 */ KBD_UNKNOWN, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_F6, - /* 30 */ KBD_UNKNOWN, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_F7, - /* 38 */ KBD_UNKNOWN, KEY_RIGHTALT, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_F8, - /* 40 */ KBD_UNKNOWN, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_F9, - /* 48 */ KBD_UNKNOWN, KEY_DOT, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_F10, - /* 50 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_APOSTROPHE,KBD_UNKNOWN, KEY_LEFTBRACE, KEY_EQUAL, KEY_F11, KEY_SYSRQ, - /* 58 */ KEY_CAPSLOCK, KEY_RIGHTSHIFT,KEY_ENTER, KEY_RIGHTBRACE,KEY_BACKSLASH, KEY_BACKSLASH,KEY_F12, KEY_SCROLLLOCK, - /* 60 */ KEY_DOWN, KEY_LEFT, KEY_PAUSE, KEY_UP, KEY_DELETE, KEY_END, KEY_BACKSPACE, KEY_INSERT, - /* 68 */ KBD_UNKNOWN, KEY_KP1, KEY_RIGHT, KEY_KP4, KEY_KP7, KEY_PAGEDOWN, KEY_HOME, KEY_PAGEUP, - /* 70 */ KEY_KP0, KEY_KPDOT, KEY_KP2, KEY_KP5, KEY_KP6, KEY_KP8, KEY_ESC, KEY_NUMLOCK, - /* 78 */ KEY_F11, KEY_KPPLUS, KEY_KP3, KEY_KPMINUS, KEY_KPASTERISK,KEY_KP9, KEY_SCROLLLOCK,KEY_103RD, - /* 80 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 88 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 90 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 98 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* a0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* a8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* b0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* b8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* c0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* c8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* d0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* d8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* e0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* e8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* f0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* f8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - - /* These are offset for escaped keycodes: */ - - /* 00 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KEY_F7, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 08 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KEY_LEFTMETA, KEY_RIGHTMETA, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 10 */ KBD_UNKNOWN, KEY_RIGHTALT, KBD_UNKNOWN, KBD_UNKNOWN, KEY_RIGHTCTRL, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 18 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 20 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 28 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 30 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 38 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 40 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 48 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_KPSLASH, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 50 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 58 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_KPENTER, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 60 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 68 */ KBD_UNKNOWN, KEY_END, KBD_UNKNOWN, KEY_LEFT, KEY_HOME, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 70 */ KEY_INSERT, KEY_DELETE, KEY_DOWN, KBD_UNKNOWN, KEY_RIGHT, KEY_UP, KBD_UNKNOWN, KBD_UNKNOWN, - /* 78 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_PAGEDOWN, KBD_UNKNOWN, KEY_SYSRQ, KEY_PAGEUP, KBD_UNKNOWN, KBD_UNKNOWN, - /* 80 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 88 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 90 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 98 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* a0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* a8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* b0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* b8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* c0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* c8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* d0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* d8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* e0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* e8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* f0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* f8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN +/* 00 */ KEY_RESERVED, KEY_F9, KEY_RESERVED, KEY_F5, KEY_F3, KEY_F1, KEY_F2, C_07, +/* 08 */ KEY_ESC, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_GRAVE, KEY_F2, +/* 10 */ KEY_RESERVED, C_11, KEY_LEFTSHIFT, KEY_RESERVED, C_14, KEY_Q, KEY_1, KEY_F3, +/* 18 */ KEY_RESERVED, KEY_LEFTALT, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_F4, +/* 20 */ KEY_RESERVED, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_F5, +/* 28 */ KEY_RESERVED, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_F6, +/* 30 */ KEY_RESERVED, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_F7, +/* 38 */ KEY_RESERVED, KEY_RIGHTALT, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_F8, +/* 40 */ KEY_RESERVED, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_F9, +/* 48 */ KEY_RESERVED, KEY_DOT, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_F10, +/* 50 */ KEY_RESERVED, KEY_RESERVED, KEY_APOSTROPHE,KEY_RESERVED, KEY_LEFTBRACE, KEY_EQUAL, KEY_F11, KEY_SYSRQ, +/* 58 */ C_58, KEY_RIGHTSHIFT,KEY_ENTER, KEY_RIGHTBRACE,KEY_BACKSLASH, KEY_BACKSLASH,KEY_F12, KEY_SCROLLLOCK, +/* 60 */ KEY_DOWN, C_61, KEY_PAUSE, KEY_UP, KEY_DELETE, KEY_END, KEY_BACKSPACE, KEY_INSERT, +/* 68 */ KEY_RESERVED, KEY_KP1, KEY_RIGHT, KEY_KP4, KEY_KP7, KEY_PAGEDOWN, KEY_HOME, KEY_PAGEUP, +/* 70 */ KEY_KP0, KEY_KPDOT, KEY_KP2, KEY_KP5, KEY_KP6, KEY_KP8, KEY_ESC, KEY_NUMLOCK, +/* 78 */ KEY_F11, KEY_KPPLUS, KEY_KP3, KEY_KPMINUS, KEY_KPASTERISK,KEY_KP9, KEY_SCROLLLOCK,KEY_103RD, +/* 80 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 88 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 90 */ KEY_RESERVED, KEY_RIGHTALT, KEY_SYSRQ, KEY_RESERVED, KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 98 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_CAPSLOCK, KEY_RESERVED, KEY_LEFTMETA, +/* a0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RIGHTMETA, +/* a8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_COMPOSE, +/* b0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* b8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* c0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* c8 */ KEY_RESERVED, KEY_RESERVED, KEY_KPSLASH, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* d0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* d8 */ KEY_RESERVED, KEY_RESERVED, KEY_KPENTER, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* e0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* e8 */ KEY_RESERVED, KEY_END, KEY_RESERVED, KEY_LEFT, KEY_HOME, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* f0 */ KEY_INSERT, KEY_DELETE, KEY_DOWN, KEY_RESERVED, KEY_RIGHT, KEY_UP, KEY_RESERVED, KEY_PAUSE, +/* f8 */ KEY_RESERVED, KEY_RESERVED, KEY_PAGEDOWN, KEY_RESERVED, KEY_SYSRQ, KEY_PAGEUP, KEY_RESERVED, KEY_RESERVED, + +/* These are offset for escaped keycodes: */ + +/* 00 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_F7, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 08 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 10 */ KEY_RESERVED, KEY_RIGHTALT, KEY_RESERVED, KEY_RESERVED, KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 18 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 20 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 28 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 30 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 38 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 40 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 48 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 50 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 58 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 60 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 68 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 70 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 78 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 80 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 88 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 90 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* 98 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* a0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* a8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* b0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* b8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* c0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* c8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* d0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* d8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* e0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* e8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* f0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, +/* f8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED + +#undef STANDARD_KEYBOARD +#undef CONFLICT +#undef C_07 +#undef C_11 +#undef C_14 +#undef C_58 +#undef C_61 -}; diff -Nru a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c --- a/drivers/input/keyboard/sunkbd.c Tue Mar 2 17:55:37 2004 +++ b/drivers/input/keyboard/sunkbd.c Tue Mar 2 17:55:37 2004 @@ -77,6 +77,7 @@ struct input_dev dev; struct serio *serio; struct work_struct tq; + wait_queue_head_t wait; char name[64]; char phys[32]; char type; @@ -96,11 +97,13 @@ if (sunkbd->reset <= -1) { /* If cp[i] is 0xff, sunkbd->reset will stay -1. */ sunkbd->reset = data; /* The keyboard sends 0xff 0xff 0xID on powerup */ + wake_up_interruptible(&sunkbd->wait); goto out; } if (sunkbd->layout == -1) { sunkbd->layout = data; + wake_up_interruptible(&sunkbd->wait); goto out; } @@ -176,22 +179,19 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) { - int t; - - t = 1000; sunkbd->reset = -2; sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET); - while (sunkbd->reset < 0 && --t) mdelay(1); - if (!t) return -1; + wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); + if (sunkbd->reset <0) + return -1; sunkbd->type = sunkbd->reset; if (sunkbd->type == 4) { /* Type 4 keyboard */ - t = 250; sunkbd->layout = -2; sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT); - while (sunkbd->layout < 0 && --t) mdelay(1); - if (!t) return -1; + wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4); + if (sunkbd->layout < 0) return -1; if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5; } @@ -206,9 +206,8 @@ static void sunkbd_reinit(void *data) { struct sunkbd *sunkbd = data; - int t = 1000; - while (sunkbd->reset < 0 && --t) mdelay(1); + wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); sunkbd->serio->write(sunkbd->serio, @@ -239,6 +238,7 @@ memset(sunkbd, 0, sizeof(struct sunkbd)); init_input_dev(&sunkbd->dev); + init_waitqueue_head(&sunkbd->wait); sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP); sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML); @@ -275,7 +275,7 @@ set_bit(sunkbd->keycode[i], sunkbd->dev.keybit); clear_bit(0, sunkbd->dev.keybit); - sprintf(sunkbd->name, "%s/input", serio->phys); + sprintf(sunkbd->phys, "%s/input0", serio->phys); sunkbd->dev.name = sunkbd->name; sunkbd->dev.phys = sunkbd->phys; diff -Nru a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig --- a/drivers/input/misc/Kconfig Tue Mar 2 17:55:37 2004 +++ b/drivers/input/misc/Kconfig Tue Mar 2 17:55:37 2004 @@ -54,12 +54,3 @@ To compile this driver as a module, choose M here: the module will be called uinput. -config INPUT_GSC - tristate "PA-RISC GSC PS/2 keyboard/mouse support" - depends on GSC && INPUT && INPUT_MISC - help - Say Y here if you have a PS/2 keyboard and/or mouse attached - to your PA-RISC box. HP run the keyboard in AT mode rather than - XT mode like everyone else, so we need our own driver. - Furthermore, the GSC PS/2 controller shares IRQ between mouse and - keyboard. diff -Nru a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile --- a/drivers/input/misc/Makefile Tue Mar 2 17:55:37 2004 +++ b/drivers/input/misc/Makefile Tue Mar 2 17:55:37 2004 @@ -9,4 +9,3 @@ obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o -obj-$(CONFIG_INPUT_GSC) += gsc_ps2.o diff -Nru a/drivers/input/misc/gsc_ps2.c b/drivers/input/misc/gsc_ps2.c --- a/drivers/input/misc/gsc_ps2.c Tue Mar 2 17:55:37 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,712 +0,0 @@ -/* - * drivers/input/misc/gsc_ps2.c - * - * Copyright (c) 2002 Laurent Canet - * Copyright (c) 2002 Thibaut Varene - * - * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c - * Copyright (c) 1999 Alex deVries - * Copyright (c) 1999-2000 Philipp Rumpf - * Copyright (c) 2000 Xavier Debacker - * Copyright (c) 2000-2001 Thomas Marteau - * - * HP PS/2 Keyboard, found in PA/RISC Workstations - * very similar to AT keyboards, but without i8042 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * STATUS: - * 11/09: lc: Only basic keyboard is supported, mouse still needs to be done. - * 11/12: tv: switching iomapping; cleaning code; improving module stuff. - * 11/13: lc & tv: leds aren't working. auto_repeat/meta are. Generaly good behavior. - * 11/15: tv: 2AM: leds ARE working ! - * 11/16: tv: 3AM: escaped keycodes emulation *handled*, some keycodes are - * still deliberately ignored (18), what are they used for ? - * 11/21: lc: mouse is now working - * 11/29: tv: first try for error handling in init sequence - * - * TODO: - * Error handling in init sequence - * SysRq handling - * Pause key handling - * Intellimouse & other rodents handling (at least send an error when - * such a mouse is plugged : it will totally fault) - * Mouse: set scaling / Dino testing - * Bug chasing... - * - */ - -#include -#include -#include -#include /* interrupt.h wants struct pt_regs defined */ -#include -#include /* for request_irq/free_irq */ -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Debugging stuff */ -#undef KBD_DEBUG -#ifdef KBD_DEBUG - #define DPRINTK(fmt,args...) printk(KERN_DEBUG __FILE__ ":" fmt, ##args) -#else - #define DPRINTK(x,...) -#endif - - -/* - * Driver constants - */ - -/* PS/2 keyboard and mouse constants */ -#define AUX_RECONNECT 0xAA /* PS/2 Mouse end of test successful */ -#define AUX_REPLY_ACK 0xFA -#define AUX_ENABLE_DEV 0xF4 /* Enables aux device */ - -/* Order of the mouse bytes coming to the host */ -#define PACKET_X 1 -#define PACKET_Y 2 -#define PACKET_CTRL 0 - -#define GSC_MOUSE_OFFSET 0x0100 /* offset from keyboard to mouse port */ -#define GSC_DINO_OFFSET 0x800 /* offset for DINO controller versus LASI one */ - -#define GSC_ID 0x00 /* ID and reset port offsets */ -#define GSC_RESET 0x00 -#define GSC_RCVDATA 0x04 /* receive and transmit port offsets */ -#define GSC_XMTDATA 0x04 -#define GSC_CONTROL 0x08 /* see: control register bits */ -#define GSC_STATUS 0x0C /* see: status register bits */ - -/* Control register bits */ -#define GSC_CTRL_ENBL 0x01 /* enable interface */ -#define GSC_CTRL_LPBXR 0x02 /* loopback operation */ -#define GSC_CTRL_DIAG 0x20 /* directly control clock/data line */ -#define GSC_CTRL_DATDIR 0x40 /* data line direct control */ -#define GSC_CTRL_CLKDIR 0x80 /* clock line direct control */ - -/* Status register bits */ -#define GSC_STAT_RBNE 0x01 /* Receive Buffer Not Empty */ -#define GSC_STAT_TBNE 0x02 /* Transmit Buffer Not Empty */ -#define GSC_STAT_TERR 0x04 /* Timeout Error */ -#define GSC_STAT_PERR 0x08 /* Parity Error */ -#define GSC_STAT_CMPINTR 0x10 /* Composite Interrupt */ -#define GSC_STAT_DATSHD 0x40 /* Data Line Shadow */ -#define GSC_STAT_CLKSHD 0x80 /* Clock Line Shadow */ - -/* Keycode map */ -#define KBD_ESCAPE0 0xe0 -#define KBD_ESCAPE1 0xe1 -#define KBD_RELEASE 0xf0 -#define KBD_ACK 0xfa -#define KBD_RESEND 0xfe -#define KBD_UNKNOWN 0 - -#define KBD_TBLSIZE 512 - -/* Mouse */ -#define MOUSE_LEFTBTN 0x1 -#define MOUSE_MIDBTN 0x4 -#define MOUSE_RIGHTBTN 0x2 -#define MOUSE_ALWAYS1 0x8 -#define MOUSE_XSIGN 0x10 -#define MOUSE_YSIGN 0x20 -#define MOUSE_XOVFLOW 0x40 -#define MOUSE_YOVFLOW 0x80 - -/* Remnant of pc_keyb.h */ -#define KBD_CMD_SET_LEDS 0xED /* Sets keyboard leds */ -#define KBD_CMD_SET_RATE 0xF3 /* Sets typematic rate */ -#define KBD_CMD_ENABLE 0xF4 /* Enables scanning */ -#define KBD_CMD_DISABLE 0xF5 -#define KBD_CMD_RESET 0xFF - -static unsigned char hpkeyb_keycode[KBD_TBLSIZE] = -{ - /* 00 */ KBD_UNKNOWN, KEY_F9, KBD_UNKNOWN, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12, - /* 08 */ KBD_UNKNOWN, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_GRAVE, KBD_UNKNOWN, - /* 10 */ KBD_UNKNOWN, KEY_LEFTALT, KEY_LEFTSHIFT, KBD_UNKNOWN, KEY_LEFTCTRL, KEY_Q, KEY_1, KBD_UNKNOWN, - /* 18 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KBD_UNKNOWN, - /* 20 */ KBD_UNKNOWN, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KBD_UNKNOWN, - /* 28 */ KBD_UNKNOWN, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KBD_UNKNOWN, - /* 30 */ KBD_UNKNOWN, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KBD_UNKNOWN, - /* 38 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KBD_UNKNOWN, - /* 40 */ KBD_UNKNOWN, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KBD_UNKNOWN, - /* 48 */ KBD_UNKNOWN, KEY_DOT, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KBD_UNKNOWN, - /* 50 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_APOSTROPHE,KBD_UNKNOWN, KEY_LEFTBRACE, KEY_EQUAL, KBD_UNKNOWN, KBD_UNKNOWN, - /* 58 */ KEY_CAPSLOCK, KEY_RIGHTSHIFT,KEY_ENTER, KEY_RIGHTBRACE,KBD_UNKNOWN, KEY_BACKSLASH,KBD_UNKNOWN, KBD_UNKNOWN, - /* 60 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KEY_BACKSPACE, KBD_UNKNOWN, - /* 68 */ KBD_UNKNOWN, KEY_KP1, KBD_UNKNOWN, KEY_KP4, KEY_KP7, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 70 */ KEY_KP0, KEY_KPDOT, KEY_KP2, KEY_KP5, KEY_KP6, KEY_KP8, KEY_ESC, KEY_NUMLOCK, - /* 78 */ KEY_F11, KEY_KPPLUS, KEY_KP3, KEY_KPMINUS, KEY_KPASTERISK,KEY_KP9, KEY_SCROLLLOCK,KEY_103RD, - /* 80 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KEY_F7, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 88 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 90 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 98 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* a0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* a8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* b0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* b8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* c0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* c8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* d0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* d8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* e0 */ KBD_ESCAPE0, KBD_ESCAPE1, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* e8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* f0 */ KBD_RELEASE, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* f8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_ACK, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_RESEND, KBD_UNKNOWN, -/* These are offset for escaped keycodes */ - /* 00 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 08 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 10 */ KBD_UNKNOWN, KEY_RIGHTALT, KBD_UNKNOWN, KBD_UNKNOWN, KEY_RIGHTCTRL, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 18 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 20 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 28 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 30 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 38 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 40 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 48 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_KPSLASH, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 50 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 58 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_KPENTER, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 60 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 68 */ KBD_UNKNOWN, KEY_END, KBD_UNKNOWN, KEY_LEFT, KEY_HOME, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 70 */ KEY_INSERT, KEY_DELETE, KEY_DOWN, KBD_UNKNOWN, KEY_RIGHT, KEY_UP, KBD_UNKNOWN, KBD_UNKNOWN, - /* 78 */ KBD_UNKNOWN, KBD_UNKNOWN, KEY_PAGEDOWN, KBD_UNKNOWN, KEY_SYSRQ, KEY_PAGEUP, KBD_UNKNOWN, KBD_UNKNOWN, - /* 80 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 88 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 90 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* 98 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* a0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* a8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* b0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* b8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* c0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* c8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* d0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* d8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* e0 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* e8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* f0 */ KBD_RELEASE, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, - /* f8 */ KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN, KBD_UNKNOWN -}; - - -/* Keyboard struct */ -static struct { - struct input_dev dev; - char * addr; - unsigned int irq; - unsigned int scancode; - unsigned int escaped; - unsigned int released; - unsigned int initialized; -} -hpkeyb = { - .escaped = 0, - .released = 0, - .initialized = 0 -}; - -/* Mouse struct */ -static struct { - struct input_dev dev; - char * addr; - unsigned long irq; - unsigned long initialized; - int nbread; - unsigned char bytes[3]; - unsigned long last; -} -hpmouse = { - .initialized = 0, - .nbread = 0 -}; - -static spinlock_t gscps2_lock = SPIN_LOCK_UNLOCKED; - - -/* - * Various HW level routines - */ - -#define gscps2_readb_input(x) readb(x+GSC_RCVDATA) -#define gscps2_readb_control(x) readb(x+GSC_CONTROL) -#define gscps2_readb_status(x) readb(x+GSC_STATUS) -#define gscps2_writeb_control(x, y) writeb(x, y+GSC_CONTROL) - -static inline void gscps2_writeb_output(u8 val, char * addr) -{ - int wait = 250; /* Keyboard is expected to react within 250ms */ - - while (gscps2_readb_status(addr) & GSC_STAT_TBNE) { - if (!--wait) - return; /* This should not happen */ - mdelay(1); - } - writeb(val, addr+GSC_XMTDATA); -} - -static inline unsigned char gscps2_wait_input(char * addr) -{ - int wait = 250; /* Keyboard is expected to react within 250ms */ - - while (!(gscps2_readb_status(addr) & GSC_STAT_RBNE)) { - if (!--wait) - return 0; /* This should not happen */ - mdelay(1); - } - return gscps2_readb_input(addr); -} - -static int gscps2_writeb_safe_output(u8 val) -{ - /* This function waits for keyboard's ACK */ - u8 scanread = KBD_UNKNOWN; - int loop = 5; - - while (hpkeyb_keycode[scanread]!=KBD_ACK && --loop > 0) { - gscps2_writeb_output(val, hpkeyb.addr); - mdelay(5); - scanread = gscps2_wait_input(hpkeyb.addr); - } - - if (loop <= 0) - return -1; - - return 0; -} - -/* Reset the PS2 port */ -static void __init gscps2_reset(char * addr) -{ - /* reset the interface */ - writeb(0xff, addr+GSC_RESET); - writeb(0x0 , addr+GSC_RESET); - - /* enable it */ - gscps2_writeb_control(gscps2_readb_control(addr) | GSC_CTRL_ENBL, addr); -} - - -/** - * gscps2_kbd_docode() - PS2 Keyboard basic handler - * - * Receives a keyboard scancode, analyses it and sends it to the input layer. - */ - -static void gscps2_kbd_docode(struct pt_regs *regs) -{ - int scancode = gscps2_readb_input(hpkeyb.addr); - DPRINTK("rel=%d scancode=%d, esc=%d ", hpkeyb.released, scancode, hpkeyb.escaped); - - /* Handle previously escaped scancodes */ - if (hpkeyb.escaped == KBD_ESCAPE0) - scancode |= 0x100; /* jump to the next 256 chars of the table */ - - switch (hpkeyb_keycode[scancode]) { - case KBD_RELEASE: - DPRINTK("release\n"); - hpkeyb.released = 1; - break; - case KBD_RESEND: - DPRINTK("resend request\n"); - break; - case KBD_ACK: - DPRINTK("ACK\n"); - break; - case KBD_ESCAPE0: - case KBD_ESCAPE1: - DPRINTK("escape code %d\n", hpkeyb_keycode[scancode]); - hpkeyb.escaped = hpkeyb_keycode[scancode]; - break; - case KBD_UNKNOWN: - DPRINTK("received unknown scancode %d, escape %d.\n", - scancode, hpkeyb.escaped); /* This is a DPRINTK atm since we do not handle escaped scancodes cleanly */ - if (hpkeyb.escaped) - hpkeyb.escaped = 0; - if (hpkeyb.released) - hpkeyb.released = 0; - return; - default: - hpkeyb.scancode = scancode; - DPRINTK("sent=%d, rel=%d\n",hpkeyb.scancode, hpkeyb.released); - /*input_regs(regs);*/ - input_report_key(&hpkeyb.dev, hpkeyb_keycode[hpkeyb.scancode], !hpkeyb.released); - input_sync(&hpkeyb.dev); - if (hpkeyb.escaped) - hpkeyb.escaped = 0; - if (hpkeyb.released) - hpkeyb.released = 0; - break; - } -} - - -/** - * gscps2_mouse_docode() - PS2 Mouse basic handler - * - * Receives mouse codes, processes them by packets of three, and sends - * correct events to the input layer. - */ - -static void gscps2_mouse_docode(struct pt_regs *regs) -{ - int xrel, yrel; - - /* process BAT (end of basic tests) command */ - if ((hpmouse.nbread == 1) && (hpmouse.bytes[0] == AUX_RECONNECT)) - hpmouse.nbread--; - - /* stolen from psmouse.c */ - if (hpmouse.nbread && time_after(jiffies, hpmouse.last + HZ/2)) { - printk(KERN_DEBUG "%s:%d : Lost mouse synchronization, throwing %d bytes away.\n", __FILE__, __LINE__, - hpmouse.nbread); - hpmouse.nbread = 0; - } - - hpmouse.last = jiffies; - hpmouse.bytes[hpmouse.nbread++] = gscps2_readb_input(hpmouse.addr); - - /* process packet */ - if (hpmouse.nbread == 3) { - - if (!(hpmouse.bytes[PACKET_CTRL] & MOUSE_ALWAYS1)) - DPRINTK("Mouse: error on packet always1 bit checking\n"); - /* XXX should exit now, bad data on the line! */ - - if ((hpmouse.bytes[PACKET_CTRL] & (MOUSE_XOVFLOW | MOUSE_YOVFLOW))) - DPRINTK("Mouse: position overflow\n"); - - /*input_regs(regs);*/ - - input_report_key(&hpmouse.dev, BTN_LEFT, hpmouse.bytes[PACKET_CTRL] & MOUSE_LEFTBTN); - input_report_key(&hpmouse.dev, BTN_MIDDLE, hpmouse.bytes[PACKET_CTRL] & MOUSE_MIDBTN); - input_report_key(&hpmouse.dev, BTN_RIGHT, hpmouse.bytes[PACKET_CTRL] & MOUSE_RIGHTBTN); - - xrel = hpmouse.bytes[PACKET_X]; - yrel = hpmouse.bytes[PACKET_Y]; - - /* Data sent by mouse are 9-bit signed, the sign bit is in the control packet */ - if (xrel && (hpmouse.bytes[PACKET_CTRL] & MOUSE_XSIGN)) - xrel = xrel - 0x100; - if (yrel && (hpmouse.bytes[PACKET_CTRL] & MOUSE_YSIGN)) - yrel = yrel - 0x100; - - input_report_rel(&hpmouse.dev, REL_X, xrel); - input_report_rel(&hpmouse.dev, REL_Y, -yrel); /* Y axis is received upside-down */ - - input_sync(&hpmouse.dev); - - hpmouse.nbread = 0; - } -} - - -/** - * gscps2_interrupt() - Interruption service routine - * - * This processes the list of scancodes queued and sends appropriate - * key value to the system. - */ - -static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *reg) -{ - /* process mouse actions */ - while (gscps2_readb_status(hpmouse.addr) & GSC_STAT_RBNE) - gscps2_mouse_docode(reg); - - /* process keyboard scancode */ - while (gscps2_readb_status(hpkeyb.addr) & GSC_STAT_RBNE) - gscps2_kbd_docode(reg); - - return IRQ_HANDLED; -} - - -/** - * gscps2_hpkeyb_event() - Event handler - * @return: success/error report - * - * Currently only updates leds on keyboard - */ - -int gscps2_hpkeyb_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) -{ - DPRINTK("Calling %s, type=%d, code=%d, value=%d\n", - __FUNCTION__, type, code, value); - - if (!hpkeyb.initialized) - return -1; - - if (type == EV_LED) { - u8 leds[2]; - - if (gscps2_writeb_safe_output(KBD_CMD_SET_LEDS)) { - printk(KERN_ERR "gsckbd_leds: timeout\n"); - return -1; - } - DPRINTK("KBD_CMD_SET_LEDS\n"); - - *leds = (test_bit(LED_SCROLLL, dev->led) ? LED_SCR : 0) - | (test_bit(LED_NUML, dev->led) ? LED_NUM : 0) - | (test_bit(LED_CAPSL, dev->led) ? LED_CAP : 0); - DPRINTK("Sending leds=%x\n", *leds); - - if (gscps2_writeb_safe_output(*leds)) { - printk(KERN_ERR "gsckbd_leds: timeout\n"); - return -1; - } - DPRINTK("leds sent\n"); - - if (gscps2_writeb_safe_output(KBD_CMD_ENABLE)) { - printk(KERN_ERR "gsckbd_leds: timeout\n"); - return -1; - } - DPRINTK("End\n"); - - return 0; - - } - return -1; -} - - -/** - * gscps2_kbd_probe() - Probes keyboard device and init input_dev structure - * @return: number of device initialized (1, 0 on error) - */ - -static int __init gscps2_kbd_probe(void) -{ - int i, res = 0; - unsigned long flags; - - if (hpkeyb.initialized) { - printk(KERN_ERR "GSC PS/2 keyboard driver already registered\n"); - return 0; - } - - spin_lock_irqsave(&gscps2_lock, flags); - - if (!gscps2_writeb_safe_output(KBD_CMD_SET_LEDS) && - !gscps2_writeb_safe_output(0) && - !gscps2_writeb_safe_output(KBD_CMD_ENABLE)) - res = 1; - - spin_unlock_irqrestore(&gscps2_lock, flags); - - if (!res) - printk(KERN_ERR "Keyboard initialization sequence failled\n"); - - init_input_dev(&hpkeyb.dev); - - for (i = 0; i < KBD_TBLSIZE; i++) - if (hpkeyb_keycode[i] != KBD_UNKNOWN) - set_bit(hpkeyb_keycode[i], hpkeyb.dev.keybit); - - hpkeyb.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); - hpkeyb.dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); - hpkeyb.dev.keycode = hpkeyb_keycode; - hpkeyb.dev.keycodesize = sizeof(unsigned char); - hpkeyb.dev.keycodemax = KBD_TBLSIZE; - hpkeyb.dev.name = "GSC Keyboard"; - hpkeyb.dev.phys = "hpkbd/input0"; - - hpkeyb.dev.event = gscps2_hpkeyb_event; - - /* TODO These need some adjustement, are they really useful ? */ - hpkeyb.dev.id.bustype = BUS_GSC; - hpkeyb.dev.id.vendor = PCI_VENDOR_ID_HP; - hpkeyb.dev.id.product = 0x0001; - hpkeyb.dev.id.version = 0x0010; - hpkeyb.initialized = 1; - - return 1; -} - - -/** - * gscps2_mouse_probe() - Probes mouse device and init input_dev structure - * @return: number of device initialized (1, 0 on error) - * - * Currently no check on initialization is performed - */ - -static int __init gscps2_mouse_probe(void) -{ - if (hpmouse.initialized) { - printk(KERN_ERR "GSC PS/2 Mouse driver already registered\n"); - return 0; - } - - init_input_dev(&hpmouse.dev); - - hpmouse.dev.name = "GSC Mouse"; - hpmouse.dev.phys = "hpmouse/input0"; - hpmouse.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - hpmouse.dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); - hpmouse.dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); - hpmouse.last = 0; - - gscps2_writeb_output(AUX_ENABLE_DEV, hpmouse.addr); - /* Try it a second time, this will give status if the device is available */ - gscps2_writeb_output(AUX_ENABLE_DEV, hpmouse.addr); - - /* TODO These need some adjustement, are they really useful ? */ - hpmouse.dev.id.bustype = BUS_GSC; - hpmouse.dev.id.vendor = 0x0001; - hpmouse.dev.id.product = 0x0001; - hpmouse.dev.id.version = 0x0010; - hpmouse.initialized = 1; - return 1; /* XXX: we don't check if initialization failed */ -} - - -/** - * gscps2_probe() - Probes PS2 devices - * @return: success/error report - */ - -static int __init gscps2_probe(struct parisc_device *dev) -{ - u8 id; - char *addr, *name; - int ret = 0, device_found = 0; - unsigned long hpa = dev->hpa; - - if (!dev->irq) - goto fail_pitifully; - - /* Offset for DINO PS/2. Works with LASI even */ - if (dev->id.sversion == 0x96) - hpa += GSC_DINO_OFFSET; - - addr = ioremap(hpa, 256); - - if (!hpmouse.initialized || !hpkeyb.initialized) - gscps2_reset(addr); - - ret = -EINVAL; - id = readb(addr+GSC_ID) & 0x0f; - switch (id) { - case 0: /* keyboard */ - hpkeyb.addr = addr; - name = "keyboard"; - device_found = gscps2_kbd_probe(); - break; - case 1: /* mouse */ - hpmouse.addr = addr; - name = "mouse"; - device_found = gscps2_mouse_probe(); - break; - default: - printk(KERN_WARNING "%s: Unsupported PS/2 port (id=%d) ignored\n", - __FUNCTION__, id); - goto fail_miserably; - } - - /* No valid device found */ - ret = -ENODEV; - if (!device_found) - goto fail_miserably; - - /* Here we claim only if we have a device attached */ - /* Allocate the irq and memory region for that device */ - ret = -EBUSY; - if (request_irq(dev->irq, gscps2_interrupt, 0, name, NULL)) - goto fail_miserably; - - if (!request_mem_region(hpa, GSC_STATUS + 4, name)) - goto fail_request_mem; - - /* Finalize input struct and register it */ - switch (id) { - case 0: /* keyboard */ - hpkeyb.irq = dev->irq; - input_register_device(&hpkeyb.dev); - break; - case 1: /* mouse */ - hpmouse.irq = dev->irq; - input_register_device(&hpmouse.dev); - break; - default: - break; - } - - printk(KERN_INFO "input: PS/2 %s port at 0x%08lx (irq %d) found and attached\n", - name, hpa, dev->irq); - - return 0; - -fail_request_mem: free_irq(dev->irq, NULL); -fail_miserably: iounmap(addr); -fail_pitifully: return ret; -} - - - -static struct parisc_device_id gscps2_device_tbl[] = { - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */ -/* { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, DINO PS/2 (XXX Not yet tested) */ - { 0, } /* 0 terminated list */ -}; - -static struct parisc_driver gscps2_driver = { - .name = "GSC PS2", - .id_table = gscps2_device_tbl, - .probe = gscps2_probe, -}; - -static int __init gscps2_init(void) -{ - if (register_parisc_driver(&gscps2_driver)) - return -EBUSY; - return 0; -} - -static void __exit gscps2_exit(void) -{ - /* TODO this is probably not very good and needs to be checked */ - if (hpkeyb.initialized) { - free_irq(hpkeyb.irq, gscps2_interrupt); - iounmap(hpkeyb.addr); - hpkeyb.initialized = 0; - input_unregister_device(&hpkeyb.dev); - } - if (hpmouse.initialized) { - free_irq(hpmouse.irq, gscps2_interrupt); - iounmap(hpmouse.addr); - hpmouse.initialized = 0; - input_unregister_device(&hpmouse.dev); - } - unregister_parisc_driver(&gscps2_driver); -} - - -MODULE_AUTHOR("Laurent Canet , Thibaut Varene "); -MODULE_DESCRIPTION("GSC PS/2 keyboard/mouse driver"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl); - - -module_init(gscps2_init); -module_exit(gscps2_exit); diff -Nru a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig --- a/drivers/input/mouse/Kconfig Tue Mar 2 17:55:37 2004 +++ b/drivers/input/mouse/Kconfig Tue Mar 2 17:55:37 2004 @@ -17,6 +17,7 @@ depends on INPUT && INPUT_MOUSE select SERIO select SERIO_I8042 if PC + select SERIO_GSCPS2 if GSC ---help--- Say Y here if you have a PS/2 mouse connected to your system. This includes the standard 2 or 3-button PS/2 mouse, as well as PS/2 diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig --- a/drivers/input/serio/Kconfig Tue Mar 2 17:55:37 2004 +++ b/drivers/input/serio/Kconfig Tue Mar 2 17:55:37 2004 @@ -20,6 +20,7 @@ tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 default y select SERIO + depends on !PARISC ---help--- i8042 is the chip over which the standard AT keyboard and PS/2 mouse are connected to the computer. If you use these devices, @@ -48,6 +49,7 @@ config SERIO_CT82C710 tristate "ct82c710 Aux port controller" depends on SERIO + depends on !PARISC ---help--- Say Y here if you have a Texas Instruments TravelMate notebook equipped with the ct82c710 chip and want to use a mouse connected @@ -104,6 +106,20 @@ To compile this driver as a module, choose M here: the module will be called 98kbd-io. + +config SERIO_GSCPS2 + tristate "HP GSC PS/2 keyboard and PS/2 mouse controller" + depends on GSC && SERIO + default y + help + This driver provides support for the PS/2 ports on PA-RISC machines + over which HP PS/2 keyboards and PS/2 mice may be connected. + If you use these devices, you'll need to say Y here. + + It's safe to enable this driver, so if unsure, say Y. + + To compile this driver as a module, choose M here: the + module will be called gscps2. config SERIO_PCIPS2 tristate "PCI PS/2 keyboard and PS/2 mouse controller" diff -Nru a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile --- a/drivers/input/serio/Makefile Tue Mar 2 17:55:37 2004 +++ b/drivers/input/serio/Makefile Tue Mar 2 17:55:37 2004 @@ -14,4 +14,5 @@ obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o +obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o diff -Nru a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/input/serio/gscps2.c Tue Mar 2 17:55:37 2004 @@ -0,0 +1,470 @@ +/* + * drivers/input/serio/gscps2.c + * + * Copyright (c) 2004 Helge Deller + * Copyright (c) 2002 Laurent Canet + * Copyright (c) 2002 Thibaut Varene + * + * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c + * Copyright (c) 1999 Alex deVries + * Copyright (c) 1999-2000 Philipp Rumpf + * Copyright (c) 2000 Xavier Debacker + * Copyright (c) 2000-2001 Thomas Marteau + * + * HP GSC PS/2 port driver, found in PA/RISC Workstations + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * TODO: + * - Dino testing (did HP ever shipped a machine on which this port + * was usable/enabled ?) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +MODULE_AUTHOR("Laurent Canet , Thibaut Varene , Helge Deller "); +MODULE_DESCRIPTION("HP GSC PS/2 port driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl); + +#define PFX "gscps2.c: " + +/* + * Driver constants + */ + +/* various constants */ +#define ENABLE 1 +#define DISABLE 0 + +#define GSC_DINO_OFFSET 0x0800 /* offset for DINO controller versus LASI one */ + +/* PS/2 IO port offsets */ +#define GSC_ID 0x00 /* device ID offset (see: GSC_ID_XXX) */ +#define GSC_RESET 0x00 /* reset port offset */ +#define GSC_RCVDATA 0x04 /* receive port offset */ +#define GSC_XMTDATA 0x04 /* transmit port offset */ +#define GSC_CONTROL 0x08 /* see: Control register bits */ +#define GSC_STATUS 0x0C /* see: Status register bits */ + +/* Control register bits */ +#define GSC_CTRL_ENBL 0x01 /* enable interface */ +#define GSC_CTRL_LPBXR 0x02 /* loopback operation */ +#define GSC_CTRL_DIAG 0x20 /* directly control clock/data line */ +#define GSC_CTRL_DATDIR 0x40 /* data line direct control */ +#define GSC_CTRL_CLKDIR 0x80 /* clock line direct control */ + +/* Status register bits */ +#define GSC_STAT_RBNE 0x01 /* Receive Buffer Not Empty */ +#define GSC_STAT_TBNE 0x02 /* Transmit Buffer Not Empty */ +#define GSC_STAT_TERR 0x04 /* Timeout Error */ +#define GSC_STAT_PERR 0x08 /* Parity Error */ +#define GSC_STAT_CMPINTR 0x10 /* Composite Interrupt = irq on any port */ +#define GSC_STAT_DATSHD 0x40 /* Data Line Shadow */ +#define GSC_STAT_CLKSHD 0x80 /* Clock Line Shadow */ + +/* IDs returned by GSC_ID port register */ +#define GSC_ID_KEYBOARD 0 /* device ID values */ +#define GSC_ID_MOUSE 1 + + +static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs); + +#define BUFFER_SIZE 0x0f + +/* GSC PS/2 port device struct */ +struct gscps2port { + struct list_head node; + struct parisc_device *padev; + struct serio port; + spinlock_t lock; + char *addr; + u8 act, append; /* position in buffer[] */ + struct { + u8 data; + u8 str; + } buffer[BUFFER_SIZE+1]; + int id; + char name[32]; +}; + +/* + * Various HW level routines + */ + +#define gscps2_readb_input(x) readb((x)+GSC_RCVDATA) +#define gscps2_readb_control(x) readb((x)+GSC_CONTROL) +#define gscps2_readb_status(x) readb((x)+GSC_STATUS) +#define gscps2_writeb_control(x, y) writeb((x), (y)+GSC_CONTROL) + + +/* + * wait_TBE() - wait for Transmit Buffer Empty + */ + +static int wait_TBE(char *addr) +{ + int timeout = 25000; /* device is expected to react within 250 msec */ + while (gscps2_readb_status(addr) & GSC_STAT_TBNE) { + if (!--timeout) + return 0; /* This should not happen */ + udelay(10); + } + return 1; +} + + +/* + * gscps2_flush() - flush the receive buffer + */ + +static void gscps2_flush(struct gscps2port *ps2port) +{ + while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE) + gscps2_readb_input(ps2port->addr); + ps2port->act = ps2port->append = 0; +} + +/* + * gscps2_writeb_output() - write a byte to the port + * + * returns 1 on sucess, 0 on error + */ + +static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) +{ + unsigned long flags; + char *addr = ps2port->addr; + + if (!wait_TBE(addr)) { + printk(KERN_DEBUG PFX "timeout - could not write byte %#x\n", data); + return 0; + } + + while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE) + /* wait */; + + spin_lock_irqsave(&ps2port->lock, flags); + writeb(data, addr+GSC_XMTDATA); + spin_unlock_irqrestore(&ps2port->lock, flags); + + /* this is ugly, but due to timing of the port it seems to be necessary. */ + mdelay(6); + + /* make sure any received data is returned as fast as possible */ + /* this is important e.g. when we set the LEDs on the keyboard */ + gscps2_interrupt(0, NULL, NULL); + + return 1; +} + + +/* + * gscps2_enable() - enables or disables the port + */ + +static void gscps2_enable(struct gscps2port *ps2port, int enable) +{ + unsigned long flags; + u8 data; + + /* now enable/disable the port */ + spin_lock_irqsave(&ps2port->lock, flags); + gscps2_flush(ps2port); + data = gscps2_readb_control(ps2port->addr); + if (enable) + data |= GSC_CTRL_ENBL; + else + data &= ~GSC_CTRL_ENBL; + gscps2_writeb_control(data, ps2port->addr); + spin_unlock_irqrestore(&ps2port->lock, flags); + wait_TBE(ps2port->addr); + gscps2_flush(ps2port); +} + +/* + * gscps2_reset() - resets the PS/2 port + */ + +static void gscps2_reset(struct gscps2port *ps2port) +{ + char *addr = ps2port->addr; + unsigned long flags; + + /* reset the interface */ + spin_lock_irqsave(&ps2port->lock, flags); + gscps2_flush(ps2port); + writeb(0xff, addr+GSC_RESET); + gscps2_flush(ps2port); + spin_unlock_irqrestore(&ps2port->lock, flags); + + /* enable it */ + gscps2_enable(ps2port, ENABLE); +} + +static LIST_HEAD(ps2port_list); + +/** + * gscps2_interrupt() - Interruption service routine + * + * This function reads received PS/2 bytes and processes them on + * all interfaces. + * The problematic part here is, that the keyboard and mouse PS/2 port + * share the same interrupt and it's not possible to send data if any + * one of them holds input data. To solve this problem we try to receive + * the data as fast as possible and handle the reporting to the upper layer + * later. + */ + +static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + struct gscps2port *ps2port; + + list_for_each_entry(ps2port, &ps2port_list, node) { + + unsigned long flags; + spin_lock_irqsave(&ps2port->lock, flags); + + while ( (ps2port->buffer[ps2port->append].str = + gscps2_readb_status(ps2port->addr)) & GSC_STAT_RBNE ) { + ps2port->buffer[ps2port->append].data = + gscps2_readb_input(ps2port->addr); + ps2port->append = ((ps2port->append+1) & BUFFER_SIZE); + } + + spin_unlock_irqrestore(&ps2port->lock, flags); + + } /* list_for_each_entry */ + + /* all data was read from the ports - now report the data to upper layer */ + + list_for_each_entry(ps2port, &ps2port_list, node) { + + while (ps2port->act != ps2port->append) { + + unsigned int rxflags; + u8 data, status; + + /* Did new data arrived while we read existing data ? + If yes, exit now and let the new irq handler start over again */ + if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR) + return IRQ_HANDLED; + + status = ps2port->buffer[ps2port->act].str; + data = ps2port->buffer[ps2port->act].data; + + ps2port->act = ((ps2port->act+1) & BUFFER_SIZE); + rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) | + ((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 ); + + serio_interrupt(&ps2port->port, data, rxflags, regs); + + } /* while() */ + + } /* list_for_each_entry */ + + return IRQ_HANDLED; +} + + +/* + * gscps2_write() - send a byte out through the aux interface. + */ + +static int gscps2_write(struct serio *port, unsigned char data) +{ + struct gscps2port *ps2port = port->driver; + + if (!gscps2_writeb_output(ps2port, data)) { + printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data); + return -1; + } + return 0; +} + +/* + * gscps2_open() is called when a port is opened by the higher layer. + * It resets and enables the port. + */ + +static int gscps2_open(struct serio *port) +{ + struct gscps2port *ps2port = port->driver; + + gscps2_reset(ps2port); + + gscps2_interrupt(0, NULL, NULL); + + return 0; +} + +/* + * gscps2_close() disables the port + */ + +static void gscps2_close(struct serio *port) +{ + struct gscps2port *ps2port = port->driver; + gscps2_enable(ps2port, DISABLE); +} + +static struct serio gscps2_serio_port = +{ + .name = "GSC PS/2", + .idbus = BUS_GSC, + .idvendor = PCI_VENDOR_ID_HP, + .idproduct = 0x0001, + .idversion = 0x0010, + .type = SERIO_8042, + .write = gscps2_write, + .open = gscps2_open, + .close = gscps2_close, +}; + +/** + * gscps2_probe() - Probes PS2 devices + * @return: success/error report + */ + +static int __init gscps2_probe(struct parisc_device *dev) +{ + struct gscps2port *ps2port; + unsigned long hpa = dev->hpa; + int ret; + + if (!dev->irq) + return -ENODEV; + + /* Offset for DINO PS/2. Works with LASI even */ + if (dev->id.sversion == 0x96) + hpa += GSC_DINO_OFFSET; + + ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL); + if (!ps2port) + return -ENOMEM; + + dev_set_drvdata(&dev->dev, ps2port); + + memset(ps2port, 0, sizeof(struct gscps2port)); + ps2port->padev = dev; + ps2port->addr = ioremap(hpa, GSC_STATUS + 4); + spin_lock_init(&ps2port->lock); + + gscps2_reset(ps2port); + ps2port->id = readb(ps2port->addr+GSC_ID) & 0x0f; + snprintf(ps2port->name, sizeof(ps2port->name)-1, "%s %s", + gscps2_serio_port.name, + (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse" ); + + memcpy(&ps2port->port, &gscps2_serio_port, sizeof(gscps2_serio_port)); + ps2port->port.driver = ps2port; + ps2port->port.name = ps2port->name; + ps2port->port.phys = dev->dev.bus_id; + + list_add_tail(&ps2port->node, &ps2port_list); + + ret = -EBUSY; + if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->name, ps2port)) + goto fail_miserably; + + if ( (ps2port->id != GSC_ID_KEYBOARD) && (ps2port->id != GSC_ID_MOUSE) ) { + printk(KERN_WARNING PFX "Unsupported PS/2 port at 0x%08lx (id=%d) ignored\n", + hpa, ps2port->id); + ret = -ENODEV; + goto fail; + } + +#if 0 + if (!request_mem_region(hpa, GSC_STATUS + 4, ps2port->port.name)) + goto fail; +#endif + + printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n", + ps2port->name, + ps2port->addr, + ps2port->padev->irq, + ps2port->port.phys); + + serio_register_port(&ps2port->port); + + return 0; + +fail: + free_irq(dev->irq, ps2port); + +fail_miserably: + list_del(&ps2port->node); + iounmap(ps2port->addr); + release_mem_region(dev->hpa, GSC_STATUS + 4); + kfree(ps2port); + return ret; +} + +/** + * gscps2_remove() - Removes PS2 devices + * @return: success/error report + */ + +static int __devexit gscps2_remove(struct parisc_device *dev) +{ + struct gscps2port *ps2port = dev_get_drvdata(&dev->dev); + + serio_unregister_port(&ps2port->port); + free_irq(dev->irq, ps2port); + gscps2_flush(ps2port); + list_del(&ps2port->node); + iounmap(ps2port->addr); +#if 0 + release_mem_region(dev->hpa, GSC_STATUS + 4); +#endif + dev_set_drvdata(&dev->dev, NULL); + kfree(ps2port); + return 0; +} + + +static struct parisc_device_id gscps2_device_tbl[] = { + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */ +#ifdef DINO_TESTED + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, /* DINO PS/2 */ +#endif + { 0, } /* 0 terminated list */ +}; + +static struct parisc_driver parisc_ps2_driver = { + .name = "GSC PS/2", + .id_table = gscps2_device_tbl, + .probe = gscps2_probe, + .remove = gscps2_remove, +}; + +static int __init gscps2_init(void) +{ + register_parisc_driver(&parisc_ps2_driver); + return 0; +} + +static void __exit gscps2_exit(void) +{ + unregister_parisc_driver(&parisc_ps2_driver); +} + + +module_init(gscps2_init); +module_exit(gscps2_exit); + diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c --- a/drivers/input/serio/i8042.c Tue Mar 2 17:55:37 2004 +++ b/drivers/input/serio/i8042.c Tue Mar 2 17:55:37 2004 @@ -379,6 +379,8 @@ unsigned int dfl; int ret; + mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); + spin_lock_irqsave(&i8042_lock, flags); str = i8042_read_status(); if (str & I8042_STR_OBF) @@ -433,7 +435,6 @@ irq_ret: ret = 1; out: - mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); return IRQ_RETVAL(ret); } diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c --- a/drivers/usb/input/hid-core.c Tue Mar 2 17:55:37 2004 +++ b/drivers/usb/input/hid-core.c Tue Mar 2 17:55:37 2004 @@ -224,6 +224,9 @@ offset = report->size; report->size += parser->global.report_size * parser->global.report_count; + if (usages < parser->global.report_count) + usages = parser->global.report_count; + if (usages == 0) return 0; /* ignore padding fields */ @@ -235,9 +238,13 @@ field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); for (i = 0; i < usages; i++) { - field->usage[i].hid = parser->local.usage[i]; + int j = i; + /* Duplicate the last usage we parsed if we have excess values */ + if (i >= parser->local.usage_index) + j = parser->local.usage_index - 1; + field->usage[i].hid = parser->local.usage[j]; field->usage[i].collection_index = - parser->local.collection_index[i]; + parser->local.collection_index[j]; } field->maxusage = usages; @@ -1317,7 +1324,6 @@ #define USB_VENDOR_ID_KBGEAR 0x084e #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 - #define USB_VENDOR_ID_AIPTEK 0x08ca #define USB_DEVICE_ID_AIPTEK_6000 0x0020 @@ -1356,17 +1362,40 @@ #define USB_VENDOR_ID_A4TECH 0x09DA #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 +#define USB_VENDOR_ID_CYPRESS 0x04b4 +#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 + #define USB_VENDOR_ID_BERKSHIRE 0x0c98 #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 #define USB_VENDOR_ID_ALPS 0x0433 #define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 +#define USB_VENDOR_ID_SAITEK 0x06a3 +#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 + struct hid_blacklist { __u16 idVendor; __u16 idProduct; unsigned quirks; } hid_blacklist[] = { + + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_6000, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, + + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE }, @@ -1388,32 +1417,24 @@ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_6000, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK }, - { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK }, + { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, + { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, + { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, + { 0, 0 } }; diff -Nru a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c --- a/drivers/usb/input/hid-input.c Tue Mar 2 17:55:37 2004 +++ b/drivers/usb/input/hid-input.c Tue Mar 2 17:55:37 2004 @@ -432,20 +432,21 @@ input_regs(input, regs); if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK) - && (usage->code == BTN_BACK)) { + && (usage->code == BTN_BACK || usage->code == BTN_EXTRA)) { if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; return; } + if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { input_event(input, usage->type, REL_HWHEEL, value); return; } - if (usage->hat_min != usage->hat_max) { + if (usage->hat_min != usage->hat_max ) { /* FIXME: hat_max can be 0 and hat_min 1 */ value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; if (value < 0 || value > 8) value = 0; input_event(input, usage->type, usage->code , hid_hat_to_axis[value].x); @@ -484,7 +485,7 @@ return; } - if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */ + if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ return; input_event(input, usage->type, usage->code, value); diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c --- a/drivers/usb/input/hiddev.c Tue Mar 2 17:55:37 2004 +++ b/drivers/usb/input/hiddev.c Tue Mar 2 17:55:37 2004 @@ -403,7 +403,8 @@ struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; struct hiddev_field_info finfo; - struct hiddev_usage_ref uref; + struct hiddev_usage_ref_multi uref_multi; + struct hiddev_usage_ref *uref = &uref_multi.uref; struct hiddev_devinfo dinfo; struct hid_report *report; struct hid_field *field; @@ -575,68 +576,98 @@ return 0; case HIDIOCGUCODE: - if (copy_from_user(&uref, (void *) arg, sizeof(uref))) + if (copy_from_user(uref, (void *) arg, sizeof(*uref))) return -EFAULT; - rinfo.report_type = uref.report_type; - rinfo.report_id = uref.report_id; + rinfo.report_type = uref->report_type; + rinfo.report_id = uref->report_id; if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) return -EINVAL; - if (uref.field_index >= report->maxfield) + if (uref->field_index >= report->maxfield) return -EINVAL; - field = report->field[uref.field_index]; - if (uref.usage_index >= field->maxusage) + field = report->field[uref->field_index]; + if (uref->usage_index >= field->maxusage) return -EINVAL; - uref.usage_code = field->usage[uref.usage_index].hid; + uref->usage_code = field->usage[uref->usage_index].hid; - if (copy_to_user((void *) arg, &uref, sizeof(uref))) + if (copy_to_user((void *) arg, uref, sizeof(*uref))) return -EFAULT; return 0; case HIDIOCGUSAGE: case HIDIOCSUSAGE: + case HIDIOCGUSAGES: + case HIDIOCSUSAGES: case HIDIOCGCOLLECTIONINDEX: - if (copy_from_user(&uref, (void *) arg, sizeof(uref))) - return -EFAULT; + if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { + if (copy_from_user(&uref_multi, (void *) arg, + sizeof(uref_multi))) + return -EFAULT; + } else { + if (copy_from_user(uref, (void *) arg, sizeof(*uref))) + return -EFAULT; + } - if (cmd != HIDIOCGUSAGE && uref.report_type == HID_REPORT_TYPE_INPUT) - return -EINVAL; + if (cmd != HIDIOCGUSAGE && + cmd != HIDIOCGUSAGES && + uref->report_type == HID_REPORT_TYPE_INPUT) + return -EINVAL; - if (uref.report_id == HID_REPORT_ID_UNKNOWN) { - field = hiddev_lookup_usage(hid, &uref); + if (uref->report_id == HID_REPORT_ID_UNKNOWN) { + field = hiddev_lookup_usage(hid, uref); if (field == NULL) return -EINVAL; } else { - rinfo.report_type = uref.report_type; - rinfo.report_id = uref.report_id; + rinfo.report_type = uref->report_type; + rinfo.report_id = uref->report_id; if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) return -EINVAL; - if (uref.field_index >= report->maxfield) + if (uref->field_index >= report->maxfield) return -EINVAL; - field = report->field[uref.field_index]; - if (uref.usage_index >= field->maxusage) + field = report->field[uref->field_index]; + if (uref->usage_index >= field->maxusage) return -EINVAL; + + if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { + if (uref_multi.num_values >= HID_MAX_USAGES || + uref->usage_index >= field->maxusage || + (uref->usage_index + uref_multi.num_values) >= field->maxusage) + return -EINVAL; + } } switch (cmd) { case HIDIOCGUSAGE: - uref.value = field->value[uref.usage_index]; - if (copy_to_user((void *) arg, &uref, sizeof(uref))) + uref->value = field->value[uref->usage_index]; + if (copy_to_user((void *) arg, uref, sizeof(*uref))) return -EFAULT; return 0; case HIDIOCSUSAGE: - field->value[uref.usage_index] = uref.value; + field->value[uref->usage_index] = uref->value; return 0; case HIDIOCGCOLLECTIONINDEX: - return field->usage[uref.usage_index].collection_index; + return field->usage[uref->usage_index].collection_index; + case HIDIOCGUSAGES: + for (i = 0; i < uref_multi.num_values; i++) + uref_multi.values[i] = + field->value[uref->usage_index + i]; + if (copy_to_user((void *) arg, &uref_multi, + sizeof(uref_multi))) + return -EFAULT; + return 0; + case HIDIOCSUSAGES: + for (i = 0; i < uref_multi.num_values; i++) + field->value[uref->usage_index + i] = + uref_multi.values[i]; + return 0; } return 0; diff -Nru a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c --- a/drivers/usb/input/wacom.c Tue Mar 2 17:55:37 2004 +++ b/drivers/usb/input/wacom.c Tue Mar 2 17:55:37 2004 @@ -1,7 +1,7 @@ /* * USB Wacom Graphire and Wacom Intuos tablet support * - * Copyright (c) 2000-2002 Vojtech Pavlik + * Copyright (c) 2000-2004 Vojtech Pavlik * Copyright (c) 2000 Andreas Bach Aaen * Copyright (c) 2000 Clifford Wolf * Copyright (c) 2000 Sam Mosel @@ -9,6 +9,7 @@ * Copyright (c) 2000 Daniel Egger * Copyright (c) 2001 Frederic Lepied * Copyright (c) 2002 Ping Cheng + * Copyright (c) 2004 Panagiotis Issaris * * ChangeLog: * v0.1 (vp) - Initial release @@ -48,6 +49,7 @@ * v1.30 (vp) - Merge 2.4 and 2.5 drivers * - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse * - Cleanups here and there + * v1.30.1 (pi) - Added Graphire3 support */ /* diff -Nru a/include/linux/hiddev.h b/include/linux/hiddev.h --- a/include/linux/hiddev.h Tue Mar 2 17:55:37 2004 +++ b/include/linux/hiddev.h Tue Mar 2 17:55:37 2004 @@ -39,33 +39,33 @@ }; struct hiddev_devinfo { - unsigned int bustype; - unsigned int busnum; - unsigned int devnum; - unsigned int ifnum; - short vendor; - short product; - short version; - unsigned num_applications; + __u32 bustype; + __u32 busnum; + __u32 devnum; + __u32 ifnum; + __s16 vendor; + __s16 product; + __s16 version; + __u32 num_applications; }; struct hiddev_collection_info { - unsigned index; - unsigned type; - unsigned usage; - unsigned level; + __u32 index; + __u32 type; + __u32 usage; + __u32 level; }; #define HID_STRING_SIZE 256 struct hiddev_string_descriptor { - int index; + __s32 index; char value[HID_STRING_SIZE]; }; struct hiddev_report_info { - unsigned report_type; - unsigned report_id; - unsigned num_fields; + __u32 report_type; + __u32 report_id; + __u32 num_fields; }; /* To do a GUSAGE/SUSAGE, fill in at least usage_code, report_type and @@ -88,20 +88,20 @@ #define HID_REPORT_TYPE_MAX 3 struct hiddev_field_info { - unsigned report_type; - unsigned report_id; - unsigned field_index; - unsigned maxusage; - unsigned flags; - unsigned physical; /* physical usage for this field */ - unsigned logical; /* logical usage for this field */ - unsigned application; /* application usage for this field */ + __u32 report_type; + __u32 report_id; + __u32 field_index; + __u32 maxusage; + __u32 flags; + __u32 physical; /* physical usage for this field */ + __u32 logical; /* logical usage for this field */ + __u32 application; /* application usage for this field */ __s32 logical_minimum; __s32 logical_maximum; __s32 physical_minimum; __s32 physical_maximum; - unsigned unit_exponent; - unsigned unit; + __u32 unit_exponent; + __u32 unit; }; /* Fill in report_type, report_id and field_index to get the information on a @@ -118,14 +118,22 @@ #define HID_FIELD_BUFFERED_BYTE 0x100 struct hiddev_usage_ref { - unsigned report_type; - unsigned report_id; - unsigned field_index; - unsigned usage_index; - unsigned usage_code; + __u32 report_type; + __u32 report_id; + __u32 field_index; + __u32 usage_index; + __u32 usage_code; __s32 value; }; +/* hiddev_usage_ref_multi is used for sending multiple bytes to a control. + * It really manifests itself as setting the value of consecutive usages */ +struct hiddev_usage_ref_multi { + struct hiddev_usage_ref uref; + __u32 num_values; + __s32 values[HID_MAX_USAGES]; +}; + /* FIELD_INDEX_NONE is returned in read() data from the kernel when flags * is set to (HIDDEV_FLAG_UREF | HIDDEV_FLAG_REPORT) and a new report has * been sent by the device @@ -160,6 +168,10 @@ #define HIDIOCGCOLLECTIONINDEX _IOW('H', 0x10, struct hiddev_usage_ref) #define HIDIOCGCOLLECTIONINFO _IOWR('H', 0x11, struct hiddev_collection_info) #define HIDIOCGPHYS(len) _IOC(_IOC_READ, 'H', 0x12, len) + +/* For writing/reading to multiple/consecutive usages */ +#define HIDIOCGUSAGES _IOWR('H', 0x13, struct hiddev_usage_ref_multi) +#define HIDIOCSUSAGES _IOW('H', 0x14, struct hiddev_usage_ref_multi) /* * Flags to be used in HIDIOCSFLAG diff -Nru a/include/linux/miscdevice.h b/include/linux/miscdevice.h --- a/include/linux/miscdevice.h Tue Mar 2 17:55:37 2004 +++ b/include/linux/miscdevice.h Tue Mar 2 17:55:37 2004 @@ -3,7 +3,6 @@ #include #include -#define BUSMOUSE_MINOR 0 #define PSMOUSE_MINOR 1 #define MS_BUSMOUSE_MINOR 2 #define ATIXL_BUSMOUSE_MINOR 3