diff -u b/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- b/Documentation/kernel-parameters.txt 2005-02-09 19:00:45 -08:00 +++ b/Documentation/kernel-parameters.txt 2005-02-09 18:51:40 -08:00 @@ -73,7 +73,6 @@ SWSUSP Software suspension is enabled. TS Appropriate touchscreen support is enabled. USB USB support is enabled. - USBHID USB Human Interface Device support is enabled. V4L Video For Linux support is enabled. VGA The VGA console has been enabled. VT Virtual terminal support is enabled. @@ -1397,9 +1396,6 @@ Format: , usb-handoff [HW] Enable early USB BIOS -> OS handoff - - usbhid.mousepoll= - [USBHID] The interval which mice are to be polled at. video= [FB] Frame buffer configuration See Documentation/fb/modedb.txt. reverted: --- b/drivers/char/keyboard.c 2005-02-09 19:00:45 -08:00 +++ a/drivers/char/keyboard.c 2005-02-09 19:00:45 -08:00 @@ -173,7 +173,7 @@ if (!dev) return -ENODEV; + if (scancode < 0 || scancode >= dev->keycodemax) - if (scancode >= dev->keycodemax) return -EINVAL; return INPUT_KEYCODE(dev, scancode); @@ -183,7 +183,7 @@ { struct list_head * node; struct input_dev *dev = NULL; + int i, oldkey; - unsigned int i, oldkey; list_for_each(node,&kbd_handler.h_list) { struct input_handle *handle = to_handle_h(node); @@ -196,7 +196,7 @@ if (!dev) return -ENODEV; + if (scancode < 0 || scancode >= dev->keycodemax) - if (scancode >= dev->keycodemax) return -EINVAL; oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode); @@ -353,7 +353,7 @@ */ void compute_shiftstate(void) { + int i, j, k, sym, val; - unsigned int i, j, k, sym, val; shift_state = 0; memset(shift_down, 0, sizeof(shift_down)); @@ -394,7 +394,7 @@ static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) { int d = diacr; + int i; - unsigned int i; diacr = 0; diff -u b/drivers/input/evdev.c b/drivers/input/evdev.c --- b/drivers/input/evdev.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/evdev.c 2005-02-09 18:51:40 -08:00 @@ -199,8 +199,9 @@ { struct evdev_list *list = file->private_data; poll_wait(file, &list->evdev->wait, wait); - return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | - (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); + if (list->head != list->tail) + return POLLIN | POLLRDNORM; + return 0; } static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -440,7 +441,6 @@ static void evdev_disconnect(struct input_handle *handle) { struct evdev *evdev = handle->private; - struct evdev_list *list; class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor)); devfs_remove("input/event%d", evdev->minor); @@ -449,8 +449,6 @@ if (evdev->open) { input_close_device(handle); wake_up_interruptible(&evdev->wait); - list_for_each_entry(list, &evdev->list, node) - kill_fasync(&list->fasync, SIGIO, POLL_HUP); } else evdev_free(evdev); } diff -u b/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c --- b/drivers/input/gameport/cs461x.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/gameport/cs461x.c 2005-02-09 18:51:40 -08:00 @@ -16,7 +16,7 @@ #include #include -MODULE_AUTHOR("Victor Krapivin"); +MODULE_AUTHOR("Victor Krapivin "); MODULE_LICENSE("GPL"); /* diff -u b/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c --- b/drivers/input/gameport/ns558.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/gameport/ns558.c 2005-02-09 18:51:40 -08:00 @@ -44,6 +44,9 @@ MODULE_DESCRIPTION("Classic gameport (ISA/PnP) driver"); MODULE_LICENSE("GPL"); +#define NS558_ISA 1 +#define NS558_PNP 2 + static int ns558_isa_portlist[] = { 0x201, 0x200, 0x202, 0x203, 0x204, 0x205, 0x207, 0x209, 0x20b, 0x20c, 0x20e, 0x20f, 0x211, 0x219, 0x101, 0 }; @@ -121,15 +124,15 @@ release_region(io & (-1 << (i-1)), (1 << (i-1))); - if (!request_region(io & (-1 << i), (1 << i), "ns558-isa")) - break; /* Don't disturb anyone */ + if (!request_region(io & (-1 << i), (1 << i), "ns558-isa")) /* Don't disturb anyone */ + break; outb(0xff, io & (-1 << i)); for (j = b = 0; j < 1000; j++) if (inb(io & (-1 << i)) != inb((io & (-1 << i)) + (1 << i) - 1)) b++; msleep(3); - if (b > 300) { /* We allow 30% difference */ + if (b > 300) { /* We allow 30% difference */ release_region(io & (-1 << i), (1 << i)); break; } @@ -148,6 +151,7 @@ } memset(port, 0, sizeof(struct ns558)); + port->type = NS558_ISA; port->size = (1 << i); port->gameport.io = io; port->gameport.phys = port->phys; @@ -221,6 +225,7 @@ } memset(port, 0, sizeof(struct ns558)); + port->type = NS558_PNP; port->size = iolen; port->dev = dev; @@ -256,25 +261,19 @@ #endif -static int pnp_registered = 0; - static int __init ns558_init(void) { int i = 0; /* - * Probe ISA ports first so that PnP gets to choose free port addresses - * not occupied by the ISA ports. + * Probe for ISA ports. */ while (ns558_isa_portlist[i]) ns558_isa_probe(ns558_isa_portlist[i++]); - if (pnp_register_driver(&ns558_pnp_driver) >= 0) - pnp_registered = 1; - - - return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; + pnp_register_driver(&ns558_pnp_driver); + return list_empty(&ns558_list) ? -ENODEV : 0; } static void __exit ns558_exit(void) @@ -283,12 +282,22 @@ list_for_each_entry(port, &ns558_list, node) { gameport_unregister_port(&port->gameport); - release_region(port->gameport.io & ~(port->size - 1), port->size); - kfree(port); - } + switch (port->type) { + +#ifdef CONFIG_PNP + case NS558_PNP: + /* fall through */ +#endif + case NS558_ISA: + release_region(port->gameport.io & ~(port->size - 1), port->size); + kfree(port); + break; - if (pnp_registered) - pnp_unregister_driver(&ns558_pnp_driver); + default: + break; + } + } + pnp_unregister_driver(&ns558_pnp_driver); } module_init(ns558_init); reverted: --- b/drivers/input/joydev.c 2005-02-09 19:00:45 -08:00 +++ a/drivers/input/joydev.c 2005-02-09 19:00:45 -08:00 @@ -281,8 +281,9 @@ { struct joydev_list *list = file->private_data; poll_wait(file, &list->joydev->wait, wait); + if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) + return POLLIN | POLLRDNORM; + return 0; - return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? - (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); } static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -462,18 +463,14 @@ static void joydev_disconnect(struct input_handle *handle) { struct joydev *joydev = handle->private; - struct joydev_list *list; class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); devfs_remove("input/js%d", joydev->minor); joydev->exist = 0; + if (joydev->open) - if (joydev->open) { input_close_device(handle); + else - wake_up_interruptible(&joydev->wait); - list_for_each_entry(list, &joydev->list, node) - kill_fasync(&list->fasync, SIGIO, POLL_HUP); - } else joydev_free(joydev); } diff -u b/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c --- b/drivers/input/joystick/gamecon.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/joystick/gamecon.c 2005-02-09 18:51:40 -08:00 @@ -227,8 +227,7 @@ */ #define GC_PSX_DELAY 25 /* 25 usec */ -#define GC_PSX_LENGTH 8 /* talk to the controller in bits */ -#define GC_PSX_BYTES 6 /* the maximum number of bytes to read off the controller */ +#define GC_PSX_LENGTH 8 /* talk to the controller in bytes */ #define GC_PSX_MOUSE 1 /* Mouse */ #define GC_PSX_NEGCON 2 /* NegCon */ @@ -242,7 +241,7 @@ #define GC_PSX_SELECT 0x02 /* Pin 3 */ #define GC_PSX_ID(x) ((x) >> 4) /* High nibble is device type */ -#define GC_PSX_LEN(x) (((x) & 0xf) << 1) /* Low nibble is length in bytes/2 */ +#define GC_PSX_LEN(x) ((x) & 0xf) /* Low nibble is length in words */ static int gc_psx_delay = GC_PSX_DELAY; module_param_named(psx_delay, gc_psx_delay, uint, 0); @@ -260,13 +259,13 @@ * the psx pad. */ -static void gc_psx_command(struct gc *gc, int b, unsigned char data[5]) +static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGTH]) { int i, j, cmd, read; for (i = 0; i < 5; i++) data[i] = 0; - for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) { + for (i = 0; i < 8; i++, b >>= 1) { cmd = (b & 1) ? GC_PSX_COMMAND : 0; parport_write_data(gc->pd->port, cmd | GC_PSX_POWER); udelay(gc_psx_delay); @@ -283,7 +282,7 @@ * device identifier code. */ -static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5]) +static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGTH], unsigned char id[5]) { int i, j, max_len = 0; unsigned long flags; @@ -301,12 +300,10 @@ gc_psx_command(gc, 0, data2); /* Dump status */ for (i =0; i < 5; i++) /* Find the longest pad */ - if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) - && (GC_PSX_LEN(id[i]) > max_len) - && (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES)) + if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) && (GC_PSX_LEN(id[i]) > max_len)) max_len = GC_PSX_LEN(id[i]); - for (i = 0; i < max_len; i++) { /* Read in all the data */ + for (i = 0; i < max_len * 2; i++) { /* Read in all the data */ gc_psx_command(gc, 0, data2); for (j = 0; j < 5; j++) data[j][i] = data2[j]; @@ -331,7 +328,7 @@ struct gc *gc = (void *) private; struct input_dev *dev = gc->dev; unsigned char data[GC_MAX_LENGTH]; - unsigned char data_psx[5][GC_PSX_BYTES]; + unsigned char data_psx[5][GC_PSX_LENGTH]; int i, j, s; /* diff -u b/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c --- b/drivers/input/joystick/twidjoy.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/joystick/twidjoy.c 2005-02-09 18:51:40 -08:00 @@ -58,9 +58,7 @@ #include #include -#define DRIVER_DESC "Handykey Twiddler keyboard as a joystick driver" - -MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_DESCRIPTION("Handykey Twiddler keyboard as a joystick driver"); MODULE_LICENSE("GPL"); /* diff -u b/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig --- b/drivers/input/keyboard/Kconfig 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/keyboard/Kconfig 2005-02-09 18:51:40 -08:00 @@ -13,7 +13,7 @@ if INPUT_KEYBOARD config KEYBOARD_ATKBD - tristate "AT keyboard" if !PC + tristate "AT keyboard support" if !PC default y select SERIO select SERIO_LIBPS2 @@ -30,46 +30,8 @@ To compile this driver as a module, choose M here: the module will be called atkbd. -config KEYBOARD_ATKBD_HP_KEYCODES - bool "Use HP keyboard scancodes" - depends on PARISC && KEYBOARD_ATKBD - default y - help - Say Y here if you have a PA-RISC machine and want to use an AT or - PS/2 keyboard, and your keyboard uses keycodes that are specific to - PA-RISC keyboards. - - Say N if you use a standard keyboard. - -config KEYBOARD_ATKBD_RDI_KEYCODES - bool "Use PrecisionBook keyboard scancodes" - depends on KEYBOARD_ATKBD_HP_KEYCODES - default n - help - If you have an RDI PrecisionBook, say Y here if you want to use its - built-in keyboard (as opposed to an external keyboard). - - The PrecisionBook has five keys that conflict with those used by most - AT and PS/2 keyboards. These are as follows: - - PrecisionBook Standard AT or PS/2 - - F1 F12 - Left Ctrl Left Alt - Caps Lock Left Ctrl - Right Ctrl Caps Lock - Left 102nd key (the key to the right of Left Shift) - - If you say N here, and use the PrecisionBook keyboard, then each key - in the left-hand column will be interpreted as the corresponding key - in the right-hand column. - - If you say Y here, and use an external keyboard, then each key in the - right-hand column will be interpreted as the key shown in the - left-hand column. - config KEYBOARD_SUNKBD - tristate "Sun Type 4 and Type 5 keyboard" + tristate "Sun Type 4 and Type 5 keyboard support" select SERIO help Say Y here if you want to use a Sun Type 4 or Type 5 keyboard, @@ -80,7 +42,7 @@ module will be called sunkbd. config KEYBOARD_LKKBD - tristate "DECstation/VAXstation LK201/LK401 keyboard" + tristate "DECstation/VAXstation LK201/LK401 keyboard support" select SERIO help Say Y here if you want to use a LK201 or LK401 style serial @@ -92,7 +54,7 @@ module will be called lkkbd. config KEYBOARD_XTKBD - tristate "XT keyboard" + tristate "XT Keyboard support" select SERIO help Say Y here if you want to use the old IBM PC/XT keyboard (or @@ -112,19 +74,8 @@ To compile this driver as a module, choose M here: the module will be called newtonkbd. -config KEYBOARD_CORGI - tristate "Corgi keyboard" - depends on PXA_SHARPSL - default y - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx - series of PDAs. - - To compile this driver as a module, choose M here: the - module will be called corgikbd. - config KEYBOARD_MAPLE - tristate "Maple bus keyboard" + tristate "Maple bus keyboard support" depends on SH_DREAMCAST && MAPLE help Say Y here if you have a DreamCast console running Linux and have @@ -145,32 +96,2 @@ -config KEYBOARD_HIL_OLD - tristate "HP HIL keyboard support (simple driver)" - depends on GSC - default y - help - The "Human Interface Loop" is a older, 8-channel USB-like - controller used in several Hewlett Packard models. This driver - was adapted from the one written for m68k/hp300, and implements - support for a keyboard attached to the HIL port, but not for - any other types of HIL input devices like mice or tablets. - However, it has been thoroughly tested and is stable. - - If you want full HIL support including support for multiple - keyboards, mices and tablets, you have to enable the - "HP System Device Controller i8042 Support" in the input/serio - submenu. - -config KEYBOARD_HIL - tristate "HP HIL keyboard support" - depends on GSC - default y - select HP_SDC - select HIL_MLC - select SERIO - help - The "Human Interface Loop" is a older, 8-channel USB-like - controller used in several Hewlett Packard models. - This driver implements support for HIL-keyboards attached - to your machine, so normally you should say Y here. - endif reverted: --- b/drivers/input/keyboard/Makefile 2005-02-09 19:00:45 -08:00 +++ a/drivers/input/keyboard/Makefile 2005-02-09 19:00:45 -08:00 @@ -12,7 +12,3 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o -obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o -obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o -obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o - diff -u b/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c --- b/drivers/input/keyboard/atkbd.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/keyboard/atkbd.c 2005-02-09 18:51:40 -08:00 @@ -71,15 +71,12 @@ * are loadable via an userland utility. */ -static unsigned char atkbd_set2_keycode[512] = { - -#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES - -/* XXX: need a more general approach */ +#if defined(__hppa__) +#include "hpps2atkbd.h" +#else -#include "hpps2atkbd.h" /* include the keyboard scancodes */ +static unsigned char atkbd_set2_keycode[512] = { -#else 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117, 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0, 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183, @@ -100,7 +97,8 @@ 0, 0, 0, 65, 99, -#endif }; +#endif + static unsigned char atkbd_set3_keycode[512] = { @@ -771,7 +769,7 @@ } /* - * atkbd_connect() is called when the serio module finds an interface + * atkbd_connect() is called when the serio module finds and interface * that isn't handled yet by an appropriate device driver. We check if * there is an AT keyboard out there and if yes, we register ourselves * to the input module. reverted: --- b/drivers/input/keyboard/corgikbd.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,363 +0,0 @@ -/* - * Keyboard driver for Sharp Corgi models (SL-C7xx) - * - * Copyright (c) 2004-2005 Richard Purdie - * - * Based on xtkbd.c/locomkbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define KB_ROWS 8 -#define KB_COLS 12 -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) -/* zero code, 124 scancodes + 3 hinge combinations */ -#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 ) -#define SCAN_INTERVAL (HZ/10) -#define CORGIKBD_PRESSED 1 - -#define HINGE_SCAN_INTERVAL (HZ/4) - -#define CORGI_KEY_CALENDER KEY_F1 -#define CORGI_KEY_ADDRESS KEY_F2 -#define CORGI_KEY_FN KEY_F3 -#define CORGI_KEY_OFF KEY_SUSPEND -#define CORGI_KEY_EXOK KEY_F5 -#define CORGI_KEY_EXCANCEL KEY_F6 -#define CORGI_KEY_EXJOGDOWN KEY_F7 -#define CORGI_KEY_EXJOGUP KEY_F8 -#define CORGI_KEY_JAP1 KEY_LEFTCTRL -#define CORGI_KEY_JAP2 KEY_LEFTALT -#define CORGI_KEY_OK KEY_F11 -#define CORGI_KEY_MENU KEY_F12 -#define CORGI_HINGE_0 KEY_KP0 -#define CORGI_HINGE_1 KEY_KP1 -#define CORGI_HINGE_2 KEY_KP2 - -static unsigned char corgikbd_keycode[NR_SCANCODES] = { - 0, /* 0 */ - 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */ - 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */ - KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ - CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ - CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ - KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ - KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ - CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ - CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ -}; - - -struct corgikbd { - unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)]; - struct input_dev input; - char phys[32]; - - unsigned char state[ARRAY_SIZE(corgikbd_keycode)]; - spinlock_t lock; - - struct timer_list timer; - struct timer_list htimer; -}; - -static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data) -{ - if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) { - corgikbd_data->state[scancode] |= CORGIKBD_PRESSED; - input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1); - if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) - input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); - } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) { - corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED; - input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0); - } -} - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using pxa_gpio_mode to alter GPDR but it - * requires a function call per GPIO bit which is excessive - * when we need to access 12 bits at once multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -static inline void corgikbd_discharge_all(void) -{ - // STROBE All HiZ - GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; - GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; -} - -static inline void corgikbd_activate_all(void) -{ - // STROBE ALL -> High - GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; - GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - // Clear any interrupts we may have triggered when altering the GPIO lines - GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; - GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; -} - -static inline void corgikbd_activate_col(int col) -{ - // STROBE col -> High, not col -> HiZ - GPSR2 = CORGI_GPIO_STROBE_BIT(col); - GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); -} - -static inline void corgikbd_reset_col(int col) -{ - // STROBE col -> Low - GPCR2 = CORGI_GPIO_STROBE_BIT(col); - // STROBE col -> out, not col -> HiZ - GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); -} - -#define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT)) - -/* - * The corgi keyboard only generates interrupts when a key is pressed. - * When a key is pressed, we enable a timer which then scans the - * keyboard to detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs) -{ - unsigned int row, col, rowd, scancode; - unsigned long flags; - unsigned int num_pressed; - - spin_lock_irqsave(&corgikbd_data->lock, flags); - - if (regs) - input_regs(&corgikbd_data->input, regs); - - num_pressed = 0; - for (col = 0; col < KB_COLS; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - - corgikbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - corgikbd_activate_col( col); - udelay(KB_ACTIVATE_DELAY); - - rowd = GET_ROWS_STATUS(col); - for (row = 0; row < KB_ROWS; row++ ) { - scancode = SCANCODE(row, col); - handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data); - if (rowd & KB_ROWMASK(row)) - num_pressed++; - } - corgikbd_reset_col(col); - } - - corgikbd_activate_all(); - - input_sync(&corgikbd_data->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL); - - spin_unlock_irqrestore(&corgikbd_data->lock, flags); -} - -/* - * corgi keyboard interrupt handler. - */ -static irqreturn_t corgikbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct corgikbd *corgikbd_data = dev_id; - - if (!timer_pending(&corgikbd_data->timer)) { - /** wait chattering delay **/ - udelay(20); - corgikbd_scankeyboard(corgikbd_data, regs); - } - - return IRQ_HANDLED; -} - -/* - * corgi timer checking for released keys - */ -static void corgikbd_timer_callback(unsigned long data) -{ - struct corgikbd *corgikbd_data = (struct corgikbd *) data; - corgikbd_scankeyboard(corgikbd_data, NULL); -} - -/* - * The hinge switches generate no interrupt so they need to be - * monitored by a timer. - * - * When we detect changes, we debounce it and then pass the three - * positions the system can take as keypresses to the input system. - */ - -#define HINGE_STABLE_COUNT 2 -static int sharpsl_hinge_state = 0; -static int hinge_count = 0; - -static void corgikbd_hinge_timer(unsigned long data) -{ - struct corgikbd *corgikbd_data = (struct corgikbd *) data; - unsigned long gprr; - gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); - if (gprr != sharpsl_hinge_state) { - hinge_count = 0; - sharpsl_hinge_state = gprr; - } else if (hinge_count < HINGE_STABLE_COUNT) { - hinge_count++; - if (hinge_count >= HINGE_STABLE_COUNT) { - unsigned long flags; - spin_lock_irqsave(&corgikbd_data->lock, flags); - - corgikbd_data->input.evbit[0] = BIT(EV_KEY); - handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */ - handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */ - handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed */ - corgikbd_data->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR); - input_sync(&corgikbd_data->input); - - spin_unlock_irqrestore(&corgikbd_data->lock, flags); - } - } - mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL); -} - -static int __init corgikbd_probe(struct device *dev) -{ - int i; - struct corgikbd *corgikbd; - - corgikbd = kmalloc(sizeof(struct corgikbd), GFP_KERNEL); - if (!corgikbd) - return -ENOMEM; - - memset(corgikbd, 0, sizeof(struct corgikbd)); - dev_set_drvdata(dev,corgikbd); - strcpy(corgikbd->phys, "corgikbd/input0"); - - spin_lock_init(corgikbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&corgikbd->timer); - corgikbd->timer.function = corgikbd_timer_callback; - corgikbd->timer.data = (unsigned long) corgikbd; - - /* Init Hinge Timer */ - init_timer(&corgikbd->htimer); - corgikbd->htimer.function = corgikbd_hinge_timer; - corgikbd->htimer.data = (unsigned long) corgikbd; - - init_input_dev(&corgikbd->input); - corgikbd->input.private = corgikbd; - corgikbd->input.name = "Corgi Keyboard"; - corgikbd->input.dev = dev; - corgikbd->input.phys = corgikbd->phys; - corgikbd->input.id.bustype = BUS_HOST; - corgikbd->input.id.vendor = 0x0001; - corgikbd->input.id.product = 0x0001; - corgikbd->input.id.version = 0x0100; - corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR); - corgikbd->input.keycode = corgikbd->keycode; - corgikbd->input.keycodesize = sizeof(unsigned char); - corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode); - - memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode)); - for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) - set_bit(corgikbd->keycode[i], corgikbd->input.keybit); - clear_bit(0, corgikbd->input.keybit); - - input_register_device(&corgikbd->input); - mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { - pxa_gpio_mode( CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); - if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, - SA_INTERRUPT, "corgikbd", corgikbd)) - printk("corgikbd: Can't get IRQ: %d !\n", i); - else - set_irq_type(CORGI_IRQ_GPIO_KEY_SENSE(i),IRQT_RISING); - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode( CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); - - printk(KERN_INFO "input: Corgi Keyboard Registered\n"); - - return 0; -} - -static int corgikbd_remove(struct device *dev) -{ - int i; - struct corgikbd *corgikbd = dev_get_drvdata(dev); - - for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) - free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i),corgikbd); - - del_timer(&corgikbd->htimer); - del_timer(&corgikbd->timer); - - input_unregister_device(&corgikbd->input); - - kfree(corgikbd); - - return 0; -} - -static struct device_driver corgikbd_driver = { - .name = "corgi-keyboard", - .bus = &platform_bus_type, - .probe = corgikbd_probe, - .remove = corgikbd_remove, -}; - -static int __devinit corgikbd_init(void) -{ - return driver_register(&corgikbd_driver); -} - -static void __exit corgikbd_exit(void) -{ - driver_unregister(&corgikbd_driver); -} - -module_init(corgikbd_init); -module_exit(corgikbd_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Corgi Keyboard Driver"); -MODULE_LICENSE("GPLv2"); reverted: --- b/drivers/input/keyboard/hil_kbd.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,375 +0,0 @@ -/* - * Generic linux-input device driver for keyboard devices - * - * Copyright (c) 2001 Brian S. Julin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * - * References: - * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define PREFIX "HIL KEYB: " -#define HIL_GENERIC_NAME "HIL keyboard" - -MODULE_AUTHOR("Brian S. Julin "); -MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); -MODULE_LICENSE("Dual BSD/GPL"); - -#define HIL_KBD_MAX_LENGTH 16 - -#define HIL_KBD_SET1_UPBIT 0x01 -#define HIL_KBD_SET1_SHIFT 1 -static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] = - { HIL_KEYCODES_SET1 }; - -#define HIL_KBD_SET2_UPBIT 0x01 -#define HIL_KBD_SET2_SHIFT 1 -/* Set2 is user defined */ - -#define HIL_KBD_SET3_UPBIT 0x80 -#define HIL_KBD_SET3_SHIFT 0 -static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] = - { HIL_KEYCODES_SET3 }; - -static char hil_language[][16] = { HIL_LOCALE_MAP }; - -struct hil_kbd { - struct input_dev dev; - struct serio *serio; - - /* Input buffer and index for packets from HIL bus. */ - hil_packet data[HIL_KBD_MAX_LENGTH]; - int idx4; /* four counts per packet */ - - /* Raw device info records from HIL bus, see hil.h for fields. */ - char idd[HIL_KBD_MAX_LENGTH]; /* DID byte and IDD record */ - char rsc[HIL_KBD_MAX_LENGTH]; /* RSC record */ - char exd[HIL_KBD_MAX_LENGTH]; /* EXD record */ - char rnm[HIL_KBD_MAX_LENGTH + 1]; /* RNM record + NULL term. */ - - /* Something to sleep around with. */ - struct semaphore sem; -}; - -/* Process a complete packet after transfer from the HIL */ -static void hil_kbd_process_record(struct hil_kbd *kbd) -{ - struct input_dev *dev = &kbd->dev; - hil_packet *data = kbd->data; - hil_packet p; - int idx, i, cnt; - - idx = kbd->idx4/4; - p = data[idx - 1]; - - if ((p & ~HIL_CMDCT_POL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report; - if ((p & ~HIL_CMDCT_RPL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report; - - /* Not a poll response. See if we are loading config records. */ - switch (p & HIL_PKT_DATA_MASK) { - case HIL_CMD_IDD: - for (i = 0; i < idx; i++) - kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; - for (; i < HIL_KBD_MAX_LENGTH; i++) - kbd->idd[i] = 0; - break; - case HIL_CMD_RSC: - for (i = 0; i < idx; i++) - kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK; - for (; i < HIL_KBD_MAX_LENGTH; i++) - kbd->rsc[i] = 0; - break; - case HIL_CMD_EXD: - for (i = 0; i < idx; i++) - kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; - for (; i < HIL_KBD_MAX_LENGTH; i++) - kbd->exd[i] = 0; - break; - case HIL_CMD_RNM: - for (i = 0; i < idx; i++) - kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK; - for (; i < HIL_KBD_MAX_LENGTH + 1; i++) - kbd->rnm[i] = '\0'; - break; - default: - /* These occur when device isn't present */ - if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; - /* Anything else we'd like to know about. */ - printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); - break; - } - goto out; - - report: - cnt = 1; - switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { - case HIL_POL_CHARTYPE_NONE: - break; - case HIL_POL_CHARTYPE_ASCII: - while (cnt < idx - 1) - input_report_key(dev, kbd->data[cnt++] & 0x7f, 1); - break; - case HIL_POL_CHARTYPE_RSVD1: - case HIL_POL_CHARTYPE_RSVD2: - case HIL_POL_CHARTYPE_BINARY: - while (cnt < idx - 1) - input_report_key(dev, kbd->data[cnt++], 1); - break; - case HIL_POL_CHARTYPE_SET1: - while (cnt < idx - 1) { - unsigned int key; - int up; - key = kbd->data[cnt++]; - up = key & HIL_KBD_SET1_UPBIT; - key &= (~HIL_KBD_SET1_UPBIT & 0xff); - key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT]; - if (key != KEY_RESERVED) - input_report_key(dev, key, !up); - } - break; - case HIL_POL_CHARTYPE_SET2: - while (cnt < idx - 1) { - unsigned int key; - int up; - key = kbd->data[cnt++]; - up = key & HIL_KBD_SET2_UPBIT; - key &= (~HIL_KBD_SET1_UPBIT & 0xff); - key = key >> HIL_KBD_SET2_SHIFT; - if (key != KEY_RESERVED) - input_report_key(dev, key, !up); - } - break; - case HIL_POL_CHARTYPE_SET3: - while (cnt < idx - 1) { - unsigned int key; - int up; - key = kbd->data[cnt++]; - up = key & HIL_KBD_SET3_UPBIT; - key &= (~HIL_KBD_SET1_UPBIT & 0xff); - key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT]; - if (key != KEY_RESERVED) - input_report_key(dev, key, !up); - } - break; - } - out: - kbd->idx4 = 0; - up(&kbd->sem); -} - -static void hil_kbd_process_err(struct hil_kbd *kbd) { - printk(KERN_WARNING PREFIX "errored HIL packet\n"); - kbd->idx4 = 0; - up(&kbd->sem); -} - -static irqreturn_t hil_kbd_interrupt(struct serio *serio, - unsigned char data, unsigned int flags, struct pt_regs *regs) -{ - struct hil_kbd *kbd; - hil_packet packet; - int idx; - - kbd = (struct hil_kbd *)serio->private; - if (kbd == NULL) { - BUG(); - return IRQ_HANDLED; - } - - if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) { - hil_kbd_process_err(kbd); - return IRQ_HANDLED; - } - idx = kbd->idx4/4; - if (!(kbd->idx4 % 4)) kbd->data[idx] = 0; - packet = kbd->data[idx]; - packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8); - kbd->data[idx] = packet; - - /* Records of N 4-byte hil_packets must terminate with a command. */ - if ((++(kbd->idx4)) % 4) return IRQ_HANDLED; - if ((packet & 0xffff0000) != HIL_ERR_INT) { - hil_kbd_process_err(kbd); - return IRQ_HANDLED; - } - if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd); - return IRQ_HANDLED; -} - -static void hil_kbd_disconnect(struct serio *serio) -{ - struct hil_kbd *kbd; - - kbd = (struct hil_kbd *)serio->private; - if (kbd == NULL) { - BUG(); - return; - } - - input_unregister_device(&kbd->dev); - serio_close(serio); - kfree(kbd); -} - -static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv) -{ - struct hil_kbd *kbd; - uint8_t did, *idd; - int i; - - if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return; - - if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return; - memset(kbd, 0, sizeof(struct hil_kbd)); - - if (serio_open(serio, drv)) goto bail0; - - serio->private = kbd; - kbd->serio = serio; - kbd->dev.private = kbd; - - init_MUTEX_LOCKED(&(kbd->sem)); - - /* Get device info. MLC driver supplies devid/status/etc. */ - serio->write(serio, 0); - serio->write(serio, 0); - serio->write(serio, HIL_PKT_CMD >> 8); - serio->write(serio, HIL_CMD_IDD); - down(&(kbd->sem)); - - serio->write(serio, 0); - serio->write(serio, 0); - serio->write(serio, HIL_PKT_CMD >> 8); - serio->write(serio, HIL_CMD_RSC); - down(&(kbd->sem)); - - serio->write(serio, 0); - serio->write(serio, 0); - serio->write(serio, HIL_PKT_CMD >> 8); - serio->write(serio, HIL_CMD_RNM); - down(&(kbd->sem)); - - serio->write(serio, 0); - serio->write(serio, 0); - serio->write(serio, HIL_PKT_CMD >> 8); - serio->write(serio, HIL_CMD_EXD); - down(&(kbd->sem)); - - up(&(kbd->sem)); - - did = kbd->idd[0]; - idd = kbd->idd + 1; - switch (did & HIL_IDD_DID_TYPE_MASK) { - case HIL_IDD_DID_TYPE_KB_INTEGRAL: - case HIL_IDD_DID_TYPE_KB_ITF: - case HIL_IDD_DID_TYPE_KB_RSVD: - case HIL_IDD_DID_TYPE_CHAR: - printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", - did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); - break; - default: - goto bail1; - } - - if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { - printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); - goto bail1; - } - - - kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); - kbd->dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE; - kbd->dev.keycodesize = sizeof(hil_kbd_set1[0]); - kbd->dev.keycode = hil_kbd_set1; - kbd->dev.name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; - kbd->dev.phys = "hpkbd/input0"; /* XXX */ - - kbd->dev.id.bustype = BUS_HIL; - kbd->dev.id.vendor = PCI_VENDOR_ID_HP; - kbd->dev.id.product = 0x0001; /* TODO: get from kbd->rsc */ - kbd->dev.id.version = 0x0100; /* TODO: get from kbd->rsc */ - kbd->dev.dev = &serio->dev; - - for (i = 0; i < 128; i++) { - set_bit(hil_kbd_set1[i], kbd->dev.keybit); - set_bit(hil_kbd_set3[i], kbd->dev.keybit); - } - clear_bit(0, kbd->dev.keybit); - - input_register_device(&kbd->dev); - printk(KERN_INFO "input: %s, ID: %d\n", - kbd->dev.name, did); - - serio->write(serio, 0); - serio->write(serio, 0); - serio->write(serio, HIL_PKT_CMD >> 8); - serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */ - down(&(kbd->sem)); - up(&(kbd->sem)); - - return; - bail1: - serio_close(serio); - bail0: - kfree(kbd); -} - - -struct serio_driver hil_kbd_serio_drv = { - .driver = { - .name = "hil_kbd", - }, - .description = "HP HIL keyboard driver", - .connect = hil_kbd_connect, - .disconnect = hil_kbd_disconnect, - .interrupt = hil_kbd_interrupt -}; - -static int __init hil_kbd_init(void) -{ - serio_register_driver(&hil_kbd_serio_drv); - return 0; -} - -static void __exit hil_kbd_exit(void) -{ - serio_unregister_driver(&hil_kbd_serio_drv); -} - -module_init(hil_kbd_init); -module_exit(hil_kbd_exit); reverted: --- b/drivers/input/keyboard/hilkbd.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,343 +0,0 @@ -/* - * linux/drivers/hil/hilkbd.c - * - * Copyright (C) 1998 Philip Blundell - * Copyright (C) 1999 Matthew Wilcox - * Copyright (C) 1999-2003 Helge Deller - * - * Very basic HP Human Interface Loop (HIL) driver. - * This driver handles the keyboard on HP300 (m68k) and on some - * HP700 (parisc) series machines. - * - * - * This file is subject to the terms and conditions of the GNU General Public - * License version 2. See the file COPYING in the main directory of this - * archive for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller"); -MODULE_DESCRIPTION("HIL keyboard driver (basic functionality)"); -MODULE_LICENSE("GPL v2"); - - -#if defined(CONFIG_PARISC) - - #include - #include - #include - static unsigned long hil_base; /* HPA for the HIL device */ - static unsigned int hil_irq; - #define HILBASE hil_base /* HPPA (parisc) port address */ - #define HIL_DATA 0x800 - #define HIL_CMD 0x801 - #define HIL_IRQ hil_irq - #define hil_readb(p) gsc_readb(p) - #define hil_writeb(v,p) gsc_writeb((v),(p)) - -#elif defined(CONFIG_HP300) - - #define HILBASE 0xf0428000 /* HP300 (m86k) port address */ - #define HIL_DATA 0x1 - #define HIL_CMD 0x3 - #define HIL_IRQ 2 - #define hil_readb(p) readb(p) - #define hil_writeb(v,p) writeb((v),(p)) - -#else -#error "HIL is not supported on this platform" -#endif - - - -/* HIL helper functions */ - -#define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY) -#define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) -#define hil_status() (hil_readb(HILBASE + HIL_CMD)) -#define hil_command(x) do { hil_writeb((x), HILBASE + HIL_CMD); } while (0) -#define hil_read_data() (hil_readb(HILBASE + HIL_DATA)) -#define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0) - -/* HIL constants */ - -#define HIL_BUSY 0x02 -#define HIL_DATA_RDY 0x01 - -#define HIL_SETARD 0xA0 /* set auto-repeat delay */ -#define HIL_SETARR 0xA2 /* set auto-repeat rate */ -#define HIL_SETTONE 0xA3 /* set tone generator */ -#define HIL_CNMT 0xB2 /* clear nmi */ -#define HIL_INTON 0x5C /* Turn on interrupts. */ -#define HIL_INTOFF 0x5D /* Turn off interrupts. */ - -#define HIL_READKBDSADR 0xF9 -#define HIL_WRITEKBDSADR 0xE9 - -static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = - { HIL_KEYCODES_SET1 }; - -/* HIL structure */ -static struct { - struct input_dev dev; - - unsigned int curdev; - - unsigned char s; - unsigned char c; - int valid; - - unsigned char data[16]; - unsigned int ptr; - spinlock_t lock; - - void *dev_id; /* native bus device */ -} hil_dev; - - -static void poll_finished(void) -{ - int down; - int key; - unsigned char scode; - - switch (hil_dev.data[0]) { - case 0x40: - down = (hil_dev.data[1] & 1) == 0; - scode = hil_dev.data[1] >> 1; - key = hphilkeyb_keycode[scode]; - input_report_key(&hil_dev.dev, key, down); - break; - } - hil_dev.curdev = 0; -} - -static inline void handle_status(unsigned char s, unsigned char c) -{ - if (c & 0x8) { - /* End of block */ - if (c & 0x10) - poll_finished(); - } else { - if (c & 0x10) { - if (hil_dev.curdev) - poll_finished(); /* just in case */ - hil_dev.curdev = c & 7; - hil_dev.ptr = 0; - } - } -} - -static inline void handle_data(unsigned char s, unsigned char c) -{ - if (hil_dev.curdev) { - hil_dev.data[hil_dev.ptr++] = c; - hil_dev.ptr &= 15; - } -} - - -/* - * Handle HIL interrupts. - */ -static irqreturn_t hil_interrupt(int irq, void *handle, struct pt_regs *regs) -{ - unsigned char s, c; - - s = hil_status(); - c = hil_read_data(); - - switch (s >> 4) { - case 0x5: - handle_status(s, c); - break; - case 0x6: - handle_data(s, c); - break; - case 0x4: - hil_dev.s = s; - hil_dev.c = c; - mb(); - hil_dev.valid = 1; - break; - } - return IRQ_HANDLED; -} - -/* - * Send a command to the HIL - */ - -static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) -{ - unsigned long flags; - - spin_lock_irqsave(&hil_dev.lock, flags); - while (hil_busy()) - /* wait */; - hil_command(cmd); - while (len--) { - while (hil_busy()) - /* wait */; - hil_write_data(*(data++)); - } - spin_unlock_irqrestore(&hil_dev.lock, flags); -} - - -/* - * Initialise HIL. - */ - -static int __init -hil_keyb_init(void) -{ - unsigned char c; - unsigned int i, kbid; - wait_queue_head_t hil_wait; - - if (hil_dev.dev.id.bustype) { - return -ENODEV; /* already initialized */ - } - -#if defined(CONFIG_HP300) - if (!hwreg_present((void *)(HILBASE + HIL_DATA))) - return -ENODEV; - - request_region(HILBASE+HIL_DATA, 2, "hil"); -#endif - - request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); - - /* Turn on interrupts */ - hil_do(HIL_INTON, NULL, 0); - - /* Look for keyboards */ - hil_dev.valid = 0; /* clear any pending data */ - hil_do(HIL_READKBDSADR, NULL, 0); - - init_waitqueue_head(&hil_wait); - wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ); - if (!hil_dev.valid) { - printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n"); - } - - c = hil_dev.c; - hil_dev.valid = 0; - if (c == 0) { - kbid = -1; - printk(KERN_WARNING "HIL: no keyboard present.\n"); - } else { - kbid = ffz(~c); - /* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */ - } - - /* set it to raw mode */ - c = 0; - hil_do(HIL_WRITEKBDSADR, &c, 1); - - init_input_dev(&hil_dev.dev); - - for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) - if (hphilkeyb_keycode[i] != KEY_RESERVED) - set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit); - - hil_dev.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - hil_dev.dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); - hil_dev.dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE; - hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]); - hil_dev.dev.keycode = hphilkeyb_keycode; - hil_dev.dev.name = "HIL keyboard"; - hil_dev.dev.phys = "hpkbd/input0"; - - hil_dev.dev.id.bustype = BUS_HIL; - hil_dev.dev.id.vendor = PCI_VENDOR_ID_HP; - hil_dev.dev.id.product = 0x0001; - hil_dev.dev.id.version = 0x0010; - - input_register_device(&hil_dev.dev); - printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", - hil_dev.dev.name, kbid, HILBASE, HIL_IRQ); - - return 0; -} - -#if defined(CONFIG_PARISC) -static int __init -hil_init_chip(struct parisc_device *dev) -{ - if (!dev->irq) { - printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa); - return -ENODEV; - } - - hil_base = dev->hpa; - hil_irq = dev->irq; - hil_dev.dev_id = dev; - - printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq); - - return hil_keyb_init(); -} - -static struct parisc_device_id hil_tbl[] = { - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, - { 0, } -}; - -MODULE_DEVICE_TABLE(parisc, hil_tbl); - -static struct parisc_driver hil_driver = { - .name = "HIL", - .id_table = hil_tbl, - .probe = hil_init_chip, -}; -#endif /* CONFIG_PARISC */ - - - - - -static int __init hil_init(void) -{ -#if defined(CONFIG_PARISC) - return register_parisc_driver(&hil_driver); -#else - return hil_keyb_init(); -#endif -} - - -static void __exit hil_exit(void) -{ - if (HIL_IRQ) { - disable_irq(HIL_IRQ); - free_irq(HIL_IRQ, hil_dev.dev_id); - } - - /* Turn off interrupts */ - hil_do(HIL_INTOFF, NULL, 0); - - input_unregister_device(&hil_dev.dev); - -#if defined(CONFIG_PARISC) - unregister_parisc_driver(&hil_driver); -#else - release_region(HILBASE+HIL_DATA, 2); -#endif -} - -module_init(hil_init); -module_exit(hil_exit); - reverted: --- b/drivers/input/keyboard/hpps2atkbd.h 2005-02-09 19:00:45 -08:00 +++ a/drivers/input/keyboard/hpps2atkbd.h 2005-02-09 19:00:45 -08:00 @@ -14,8 +14,10 @@ */ +/* undefine if you have a RDI PRECISIONBOOK */ +#define STANDARD_KEYBOARD + +#if defined(STANDARD_KEYBOARD) -/* Is the keyboard an RDI PrecisionBook? */ -#ifndef CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES # define CONFLICT(x,y) x #else # define CONFLICT(x,y) y @@ -48,10 +50,10 @@ /* 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, -/* 78 */ KEY_F11, KEY_KPPLUS, KEY_KP3, KEY_KPMINUS, KEY_KPASTERISK,KEY_KP9, KEY_SCROLLLOCK,KEY_102ND, /* 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, -/* 90 */ KEY_RESERVED, KEY_RIGHTALT, 255, 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, @@ -101,6 +103,7 @@ /* 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 diff -u b/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig --- b/drivers/input/misc/Kconfig 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/misc/Kconfig 2005-02-09 18:51:40 -08:00 @@ -51,10 +51,2 @@ -config HP_SDC_RTC - tristate "HP SDC Real Time Clock" - depends on GSC - select HP_SDC - help - Say Y here if you want to support the built-in real time clock - of the HP SDC controller. - endif reverted: --- b/drivers/input/misc/Makefile 2005-02-09 19:00:45 -08:00 +++ a/drivers/input/misc/Makefile 2005-02-09 19:00:45 -08:00 @@ -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_HP_SDC_RTC) += hp_sdc_rtc.o reverted: --- b/drivers/input/misc/hp_sdc_rtc.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,724 +0,0 @@ -/* - * HP i8042 SDC + MSM-58321 BBRTC driver. - * - * Copyright (c) 2001 Brian S. Julin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * - * References: - * System Device Controller Microprocessor Firmware Theory of Operation - * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 - * efirtc.c by Stephane Eranian/Hewlett Packard - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Brian S. Julin "); -MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver"); -MODULE_LICENSE("Dual BSD/GPL"); - -#define RTC_VERSION "1.10d" - -static unsigned long epoch = 2000; - -static struct semaphore i8042tregs; - -static hp_sdc_irqhook hp_sdc_rtc_isr; - -static struct fasync_struct *hp_sdc_rtc_async_queue; - -static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait); - -static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin); - -static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, - size_t count, loff_t *ppos); - -static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); - -static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait); - -static int hp_sdc_rtc_open(struct inode *inode, struct file *file); -static int hp_sdc_rtc_release(struct inode *inode, struct file *file); -static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on); - -static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data); - -static void hp_sdc_rtc_isr (int irq, void *dev_id, - uint8_t status, uint8_t data) -{ - return; -} - -static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm) -{ - struct semaphore tsem; - hp_sdc_transaction t; - uint8_t tseq[91]; - int i; - - i = 0; - while (i < 91) { - tseq[i++] = HP_SDC_ACT_DATAREG | - HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN; - tseq[i++] = 0x01; /* write i8042[0x70] */ - tseq[i] = i / 7; /* BBRTC reg address */ - i++; - tseq[i++] = HP_SDC_CMD_DO_RTCR; /* Trigger command */ - tseq[i++] = 2; /* expect 1 stat/dat pair back. */ - i++; i++; /* buffer for stat/dat pair */ - } - tseq[84] |= HP_SDC_ACT_SEMAPHORE; - t.endidx = 91; - t.seq = tseq; - t.act.semaphore = &tsem; - init_MUTEX_LOCKED(&tsem); - - if (hp_sdc_enqueue_transaction(&t)) return -1; - - down_interruptible(&tsem); /* Put ourselves to sleep for results. */ - - /* Check for nonpresence of BBRTC */ - if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] | - tseq[55] | tseq[62] | tseq[34] | tseq[41] | - tseq[20] | tseq[27] | tseq[6] | tseq[13]) & 0x0f)) - return -1; - - memset(rtctm, 0, sizeof(struct rtc_time)); - rtctm->tm_year = (tseq[83] & 0x0f) + (tseq[90] & 0x0f) * 10; - rtctm->tm_mon = (tseq[69] & 0x0f) + (tseq[76] & 0x0f) * 10; - rtctm->tm_mday = (tseq[55] & 0x0f) + (tseq[62] & 0x0f) * 10; - rtctm->tm_wday = (tseq[48] & 0x0f); - rtctm->tm_hour = (tseq[34] & 0x0f) + (tseq[41] & 0x0f) * 10; - rtctm->tm_min = (tseq[20] & 0x0f) + (tseq[27] & 0x0f) * 10; - rtctm->tm_sec = (tseq[6] & 0x0f) + (tseq[13] & 0x0f) * 10; - - return 0; -} - -static int hp_sdc_rtc_read_bbrtc (struct rtc_time *rtctm) -{ - struct rtc_time tm, tm_last; - int i = 0; - - /* MSM-58321 has no read latch, so must read twice and compare. */ - - if (hp_sdc_rtc_do_read_bbrtc(&tm_last)) return -1; - if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1; - - while (memcmp(&tm, &tm_last, sizeof(struct rtc_time))) { - if (i++ > 4) return -1; - memcpy(&tm_last, &tm, sizeof(struct rtc_time)); - if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1; - } - - memcpy(rtctm, &tm, sizeof(struct rtc_time)); - - return 0; -} - - -static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg) -{ - hp_sdc_transaction t; - uint8_t tseq[26] = { - HP_SDC_ACT_PRECMD | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, - 0, - HP_SDC_CMD_READ_T1, 2, 0, 0, - HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, - HP_SDC_CMD_READ_T2, 2, 0, 0, - HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, - HP_SDC_CMD_READ_T3, 2, 0, 0, - HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, - HP_SDC_CMD_READ_T4, 2, 0, 0, - HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, - HP_SDC_CMD_READ_T5, 2, 0, 0 - }; - - t.endidx = numreg * 5; - - tseq[1] = loadcmd; - tseq[t.endidx - 4] |= HP_SDC_ACT_SEMAPHORE; /* numreg assumed > 1 */ - - t.seq = tseq; - t.act.semaphore = &i8042tregs; - - down_interruptible(&i8042tregs); /* Sleep if output regs in use. */ - - if (hp_sdc_enqueue_transaction(&t)) return -1; - - down_interruptible(&i8042tregs); /* Sleep until results come back. */ - up(&i8042tregs); - - return (tseq[5] | - ((uint64_t)(tseq[10]) << 8) | ((uint64_t)(tseq[15]) << 16) | - ((uint64_t)(tseq[20]) << 24) | ((uint64_t)(tseq[25]) << 32)); -} - - -/* Read the i8042 real-time clock */ -static inline int hp_sdc_rtc_read_rt(struct timeval *res) { - int64_t raw; - uint32_t tenms; - unsigned int days; - - raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_RT, 5); - if (raw < 0) return -1; - - tenms = (uint32_t)raw & 0xffffff; - days = (unsigned int)(raw >> 24) & 0xffff; - - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100) + days * 86400; - - return 0; -} - - -/* Read the i8042 fast handshake timer */ -static inline int hp_sdc_rtc_read_fhs(struct timeval *res) { - uint64_t raw; - unsigned int tenms; - - raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2); - if (raw < 0) return -1; - - tenms = (unsigned int)raw & 0xffff; - - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100); - - return 0; -} - - -/* Read the i8042 match timer (a.k.a. alarm) */ -static inline int hp_sdc_rtc_read_mt(struct timeval *res) { - int64_t raw; - uint32_t tenms; - - raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_MT, 3); - if (raw < 0) return -1; - - tenms = (uint32_t)raw & 0xffffff; - - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100); - - return 0; -} - - -/* Read the i8042 delay timer */ -static inline int hp_sdc_rtc_read_dt(struct timeval *res) { - int64_t raw; - uint32_t tenms; - - raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_DT, 3); - if (raw < 0) return -1; - - tenms = (uint32_t)raw & 0xffffff; - - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100); - - return 0; -} - - -/* Read the i8042 cycle timer (a.k.a. periodic) */ -static inline int hp_sdc_rtc_read_ct(struct timeval *res) { - int64_t raw; - uint32_t tenms; - - raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_CT, 3); - if (raw < 0) return -1; - - tenms = (uint32_t)raw & 0xffffff; - - res->tv_usec = (suseconds_t)(tenms % 100) * 10000; - res->tv_sec = (time_t)(tenms / 100); - - return 0; -} - - -/* Set the i8042 real-time clock */ -static int hp_sdc_rtc_set_rt (struct timeval *setto) -{ - uint32_t tenms; - unsigned int days; - hp_sdc_transaction t; - uint8_t tseq[11] = { - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, - HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0, - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, - HP_SDC_CMD_SET_RTD, 2, 0, 0 - }; - - t.endidx = 10; - - if (0xffff < setto->tv_sec / 86400) return -1; - days = setto->tv_sec / 86400; - if (0xffff < setto->tv_usec / 1000000 / 86400) return -1; - days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400; - if (days > 0xffff) return -1; - - if (0xffffff < setto->tv_sec) return -1; - tenms = setto->tv_sec * 100; - if (0xffffff < setto->tv_usec / 10000) return -1; - tenms += setto->tv_usec / 10000; - if (tenms > 0xffffff) return -1; - - tseq[3] = (uint8_t)(tenms & 0xff); - tseq[4] = (uint8_t)((tenms >> 8) & 0xff); - tseq[5] = (uint8_t)((tenms >> 16) & 0xff); - - tseq[9] = (uint8_t)(days & 0xff); - tseq[10] = (uint8_t)((days >> 8) & 0xff); - - t.seq = tseq; - - if (hp_sdc_enqueue_transaction(&t)) return -1; - return 0; -} - -/* Set the i8042 fast handshake timer */ -static int hp_sdc_rtc_set_fhs (struct timeval *setto) -{ - uint32_t tenms; - hp_sdc_transaction t; - uint8_t tseq[5] = { - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, - HP_SDC_CMD_SET_FHS, 2, 0, 0 - }; - - t.endidx = 4; - - if (0xffff < setto->tv_sec) return -1; - tenms = setto->tv_sec * 100; - if (0xffff < setto->tv_usec / 10000) return -1; - tenms += setto->tv_usec / 10000; - if (tenms > 0xffff) return -1; - - tseq[3] = (uint8_t)(tenms & 0xff); - tseq[4] = (uint8_t)((tenms >> 8) & 0xff); - - t.seq = tseq; - - if (hp_sdc_enqueue_transaction(&t)) return -1; - return 0; -} - - -/* Set the i8042 match timer (a.k.a. alarm) */ -#define hp_sdc_rtc_set_mt (setto) \ - hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT) - -/* Set the i8042 delay timer */ -#define hp_sdc_rtc_set_dt (setto) \ - hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT) - -/* Set the i8042 cycle timer (a.k.a. periodic) */ -#define hp_sdc_rtc_set_ct (setto) \ - hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT) - -/* Set one of the i8042 3-byte wide timers */ -static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd) -{ - uint32_t tenms; - hp_sdc_transaction t; - uint8_t tseq[6] = { - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, - 0, 3, 0, 0, 0 - }; - - t.endidx = 6; - - if (0xffffff < setto->tv_sec) return -1; - tenms = setto->tv_sec * 100; - if (0xffffff < setto->tv_usec / 10000) return -1; - tenms += setto->tv_usec / 10000; - if (tenms > 0xffffff) return -1; - - tseq[1] = setcmd; - tseq[3] = (uint8_t)(tenms & 0xff); - tseq[4] = (uint8_t)((tenms >> 8) & 0xff); - tseq[5] = (uint8_t)((tenms >> 16) & 0xff); - - t.seq = tseq; - - if (hp_sdc_enqueue_transaction(&t)) { - return -1; - } - return 0; -} - -static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - -static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, - size_t count, loff_t *ppos) { - ssize_t retval; - - if (count < sizeof(unsigned long)) - return -EINVAL; - - retval = put_user(68, (unsigned long *)buf); - return retval; -} - -static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait) -{ - unsigned long l; - - l = 0; - if (l != 0) - return POLLIN | POLLRDNORM; - return 0; -} - -static int hp_sdc_rtc_open(struct inode *inode, struct file *file) -{ - return 0; -} - -static int hp_sdc_rtc_release(struct inode *inode, struct file *file) -{ - /* Turn off interrupts? */ - - if (file->f_flags & FASYNC) { - hp_sdc_rtc_fasync (-1, file, 0); - } - - return 0; -} - -static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on) -{ - return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue); -} - -static int hp_sdc_rtc_proc_output (char *buf) -{ -#define YN(bit) ("no") -#define NY(bit) ("yes") - char *p; - struct rtc_time tm; - struct timeval tv; - - memset(&tm, 0, sizeof(struct rtc_time)); - - p = buf; - - if (hp_sdc_rtc_read_bbrtc(&tm)) { - p += sprintf(p, "BBRTC\t\t: READ FAILED!\n"); - } else { - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n" - "rtc_epoch\t: %04lu\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900, tm.tm_mon + 1, - tm.tm_mday, epoch); - } - - if (hp_sdc_rtc_read_rt(&tv)) { - p += sprintf(p, "i8042 rtc\t: READ FAILED!\n"); - } else { - p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n", - tv.tv_sec, tv.tv_usec/1000); - } - - if (hp_sdc_rtc_read_fhs(&tv)) { - p += sprintf(p, "handshake\t: READ FAILED!\n"); - } else { - p += sprintf(p, "handshake\t: %ld.%02d seconds\n", - tv.tv_sec, tv.tv_usec/1000); - } - - if (hp_sdc_rtc_read_mt(&tv)) { - p += sprintf(p, "alarm\t\t: READ FAILED!\n"); - } else { - p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n", - tv.tv_sec, tv.tv_usec/1000); - } - - if (hp_sdc_rtc_read_dt(&tv)) { - p += sprintf(p, "delay\t\t: READ FAILED!\n"); - } else { - p += sprintf(p, "delay\t\t: %ld.%02d seconds\n", - tv.tv_sec, tv.tv_usec/1000); - } - - if (hp_sdc_rtc_read_ct(&tv)) { - p += sprintf(p, "periodic\t: READ FAILED!\n"); - } else { - p += sprintf(p, "periodic\t: %ld.%02d seconds\n", - tv.tv_sec, tv.tv_usec/1000); - } - - p += sprintf(p, - "DST_enable\t: %s\n" - "BCD\t\t: %s\n" - "24hr\t\t: %s\n" - "square_wave\t: %s\n" - "alarm_IRQ\t: %s\n" - "update_IRQ\t: %s\n" - "periodic_IRQ\t: %s\n" - "periodic_freq\t: %ld\n" - "batt_status\t: %s\n", - YN(RTC_DST_EN), - NY(RTC_DM_BINARY), - YN(RTC_24H), - YN(RTC_SQWE), - YN(RTC_AIE), - YN(RTC_UIE), - YN(RTC_PIE), - 1UL, - 1 ? "okay" : "dead"); - - return p - buf; -#undef YN -#undef NY -} - -static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = hp_sdc_rtc_proc_output (page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; -} - -static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ -#if 1 - return -EINVAL; -#else - - struct rtc_time wtime; - struct timeval ttime; - int use_wtime = 0; - - /* This needs major work. */ - - switch (cmd) { - - case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ - case RTC_AIE_ON: /* Allow alarm interrupts. */ - case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ - case RTC_PIE_ON: /* Allow periodic ints */ - case RTC_UIE_ON: /* Allow ints for RTC updates. */ - case RTC_UIE_OFF: /* Allow ints for RTC updates. */ - { - /* We cannot mask individual user timers and we - cannot tell them apart when they occur, so it - would be disingenuous to succeed these IOCTLs */ - return -EINVAL; - } - case RTC_ALM_READ: /* Read the present alarm time */ - { - if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT; - if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; - - wtime.tm_hour = ttime.tv_sec / 3600; ttime.tv_sec %= 3600; - wtime.tm_min = ttime.tv_sec / 60; ttime.tv_sec %= 60; - wtime.tm_sec = ttime.tv_sec; - - break; - } - case RTC_IRQP_READ: /* Read the periodic IRQ rate. */ - { - return put_user(hp_sdc_rtc_freq, (unsigned long *)arg); - } - case RTC_IRQP_SET: /* Set periodic IRQ rate. */ - { - /* - * The max we can do is 100Hz. - */ - - if ((arg < 1) || (arg > 100)) return -EINVAL; - ttime.tv_sec = 0; - ttime.tv_usec = 1000000 / arg; - if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT; - hp_sdc_rtc_freq = arg; - return 0; - } - case RTC_ALM_SET: /* Store a time into the alarm */ - { - /* - * This expects a struct hp_sdc_rtc_time. Writing 0xff means - * "don't care" or "match all" for PC timers. The HP SDC - * does not support that perk, but it could be emulated fairly - * easily. Only the tm_hour, tm_min and tm_sec are used. - * We could do it with 10ms accuracy with the HP SDC, if the - * rtc interface left us a way to do that. - */ - struct hp_sdc_rtc_time alm_tm; - - if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg, - sizeof(struct hp_sdc_rtc_time))) - return -EFAULT; - - if (alm_tm.tm_hour > 23) return -EINVAL; - if (alm_tm.tm_min > 59) return -EINVAL; - if (alm_tm.tm_sec > 59) return -EINVAL; - - ttime.sec = alm_tm.tm_hour * 3600 + - alm_tm.tm_min * 60 + alm_tm.tm_sec; - ttime.usec = 0; - if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT; - return 0; - } - case RTC_RD_TIME: /* Read the time/date from RTC */ - { - if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; - break; - } - case RTC_SET_TIME: /* Set the RTC */ - { - struct rtc_time hp_sdc_rtc_tm; - unsigned char mon, day, hrs, min, sec, leap_yr; - unsigned int yrs; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - yrs = hp_sdc_rtc_tm.tm_year + 1900; - mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ - day = hp_sdc_rtc_tm.tm_mday; - hrs = hp_sdc_rtc_tm.tm_hour; - min = hp_sdc_rtc_tm.tm_min; - sec = hp_sdc_rtc_tm.tm_sec; - - if (yrs < 1970) - return -EINVAL; - - leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); - - if ((mon > 12) || (day == 0)) - return -EINVAL; - if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) - return -EINVAL; - if ((hrs >= 24) || (min >= 60) || (sec >= 60)) - return -EINVAL; - - if ((yrs -= eH) > 255) /* They are unsigned */ - return -EINVAL; - - - return 0; - } - case RTC_EPOCH_READ: /* Read the epoch. */ - { - return put_user (epoch, (unsigned long *)arg); - } - case RTC_EPOCH_SET: /* Set the epoch. */ - { - /* - * There were no RTC clocks before 1900. - */ - if (arg < 1900) - return -EINVAL; - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - epoch = arg; - return 0; - } - default: - return -EINVAL; - } - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -#endif -} - -static struct file_operations hp_sdc_rtc_fops = { - .owner = THIS_MODULE, - .llseek = hp_sdc_rtc_llseek, - .read = hp_sdc_rtc_read, - .poll = hp_sdc_rtc_poll, - .ioctl = hp_sdc_rtc_ioctl, - .open = hp_sdc_rtc_open, - .release = hp_sdc_rtc_release, - .fasync = hp_sdc_rtc_fasync, -}; - -static struct miscdevice hp_sdc_rtc_dev = { - .minor = RTC_MINOR, - .name = "rtc_HIL", - .fops = &hp_sdc_rtc_fops -}; - -static int __init hp_sdc_rtc_init(void) -{ - int ret; - - init_MUTEX(&i8042tregs); - - if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr))) - return ret; - misc_register(&hp_sdc_rtc_dev); - create_proc_read_entry ("driver/rtc", 0, 0, - hp_sdc_rtc_read_proc, NULL); - - printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded " - "(RTC v " RTC_VERSION ")\n"); - - return 0; -} - -static void __exit hp_sdc_rtc_exit(void) -{ - remove_proc_entry ("driver/rtc", NULL); - misc_deregister(&hp_sdc_rtc_dev); - hp_sdc_release_timer_irq(hp_sdc_rtc_isr); - printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n"); -} - -module_init(hp_sdc_rtc_init); -module_exit(hp_sdc_rtc_exit); diff -u b/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c --- b/drivers/input/misc/pcspkr.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/misc/pcspkr.c 2005-02-09 18:51:40 -08:00 @@ -89,8 +89,6 @@ static void __exit pcspkr_exit(void) { input_unregister_device(&pcspkr_dev); - /* turn off the speaker */ - pcspkr_event(NULL, EV_SND, SND_BELL, 0); } module_init(pcspkr_init); diff -u b/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig --- b/drivers/input/mouse/Kconfig 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/mouse/Kconfig 2005-02-09 18:51:40 -08:00 @@ -129,10 +129,2 @@ -config MOUSE_HIL - tristate "HIL pointers (mice etc)." - depends on GSC - select HP_SDC - select HIL_MLC - help - Say Y here to support HIL pointers. - endif reverted: --- b/drivers/input/mouse/Makefile 2005-02-09 19:00:45 -08:00 +++ a/drivers/input/mouse/Makefile 2005-02-09 19:00:45 -08:00 @@ -12,7 +12,6 @@ obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o obj-$(CONFIG_MOUSE_PS2) += psmouse.o obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o -obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o diff -u b/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c --- b/drivers/input/mouse/alps.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/mouse/alps.c 2005-02-09 18:51:40 -08:00 @@ -198,8 +198,8 @@ return PSMOUSE_BAD_DATA; /* Bytes 2 - 6 should have 0 in the highest bit */ - if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) + if (psmouse->pktcnt > 1 && psmouse->pktcnt <= 6 && + (psmouse->packet[psmouse->pktcnt] & 0x80)) return PSMOUSE_BAD_DATA; if (psmouse->pktcnt == 6) { reverted: --- b/drivers/input/mouse/hil_ptr.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,414 +0,0 @@ -/* - * Generic linux-input device driver for axis-bearing devices - * - * Copyright (c) 2001 Brian S. Julin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * - * References: - * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define PREFIX "HIL PTR: " -#define HIL_GENERIC_NAME "HIL pointer device" - -MODULE_AUTHOR("Brian S. Julin "); -MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); -MODULE_LICENSE("Dual BSD/GPL"); - - -#define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */ -#undef TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */ - - -#define HIL_PTR_MAX_LENGTH 16 - -struct hil_ptr { - struct input_dev dev; - struct serio *serio; - - /* Input buffer and index for packets from HIL bus. */ - hil_packet data[HIL_PTR_MAX_LENGTH]; - int idx4; /* four counts per packet */ - - /* Raw device info records from HIL bus, see hil.h for fields. */ - char idd[HIL_PTR_MAX_LENGTH]; /* DID byte and IDD record */ - char rsc[HIL_PTR_MAX_LENGTH]; /* RSC record */ - char exd[HIL_PTR_MAX_LENGTH]; /* EXD record */ - char rnm[HIL_PTR_MAX_LENGTH + 1]; /* RNM record + NULL term. */ - - /* Extra device details not contained in struct input_dev. */ - unsigned int nbtn, naxes; - unsigned int btnmap[7]; - - /* Something to sleep around with. */ - struct semaphore sem; -}; - -/* Process a complete packet after transfer from the HIL */ -static void hil_ptr_process_record(struct hil_ptr *ptr) -{ - struct input_dev *dev = &ptr->dev; - hil_packet *data = ptr->data; - hil_packet p; - int idx, i, cnt, laxis; - int ax16, absdev; - - idx = ptr->idx4/4; - p = data[idx - 1]; - - if ((p & ~HIL_CMDCT_POL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report; - if ((p & ~HIL_CMDCT_RPL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report; - - /* Not a poll response. See if we are loading config records. */ - switch (p & HIL_PKT_DATA_MASK) { - case HIL_CMD_IDD: - for (i = 0; i < idx; i++) - ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; - for (; i < HIL_PTR_MAX_LENGTH; i++) - ptr->idd[i] = 0; - break; - case HIL_CMD_RSC: - for (i = 0; i < idx; i++) - ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK; - for (; i < HIL_PTR_MAX_LENGTH; i++) - ptr->rsc[i] = 0; - break; - case HIL_CMD_EXD: - for (i = 0; i < idx; i++) - ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; - for (; i < HIL_PTR_MAX_LENGTH; i++) - ptr->exd[i] = 0; - break; - case HIL_CMD_RNM: - for (i = 0; i < idx; i++) - ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK; - for (; i < HIL_PTR_MAX_LENGTH + 1; i++) - ptr->rnm[i] = '\0'; - break; - default: - /* These occur when device isn't present */ - if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; - /* Anything else we'd like to know about. */ - printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); - break; - } - goto out; - - report: - if ((p & HIL_CMDCT_POL) != idx - 1) { - printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx); - goto out; - } - - i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0; - laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK; - laxis += i; - - ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ - absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; - - for (cnt = 1; i < laxis; i++) { - unsigned int lo,hi,val; - lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; - hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; - if (absdev) { - val = lo + (hi<<8); -#ifdef TABLET_AUTOADJUST - if (val < ptr->dev.absmin[ABS_X + i]) - ptr->dev.absmin[ABS_X + i] = val; - if (val > ptr->dev.absmax[ABS_X + i]) - ptr->dev.absmax[ABS_X + i] = val; -#endif - if (i%3) val = ptr->dev.absmax[ABS_X + i] - val; - input_report_abs(dev, ABS_X + i, val); - } else { - val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); - if (i%3) val *= -1; - input_report_rel(dev, REL_X + i, val); - } - } - - while (cnt < idx - 1) { - unsigned int btn; - int up; - btn = ptr->data[cnt++]; - up = btn & 1; - btn &= 0xfe; - if (btn == 0x8e) { - continue; /* TODO: proximity == touch? */ - } - else if ((btn > 0x8c) || (btn < 0x80)) continue; - btn = (btn - 0x80) >> 1; - btn = ptr->btnmap[btn]; - input_report_key(dev, btn, !up); - } - input_sync(dev); - out: - ptr->idx4 = 0; - up(&ptr->sem); -} - -static void hil_ptr_process_err(struct hil_ptr *ptr) { - printk(KERN_WARNING PREFIX "errored HIL packet\n"); - ptr->idx4 = 0; - up(&ptr->sem); - return; -} - -static irqreturn_t hil_ptr_interrupt(struct serio *serio, - unsigned char data, unsigned int flags, struct pt_regs *regs) -{ - struct hil_ptr *ptr; - hil_packet packet; - int idx; - - ptr = (struct hil_ptr *)serio->private; - if (ptr == NULL) { - BUG(); - return IRQ_HANDLED; - } - - if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) { - hil_ptr_process_err(ptr); - return IRQ_HANDLED; - } - idx = ptr->idx4/4; - if (!(ptr->idx4 % 4)) ptr->data[idx] = 0; - packet = ptr->data[idx]; - packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8); - ptr->data[idx] = packet; - - /* Records of N 4-byte hil_packets must terminate with a command. */ - if ((++(ptr->idx4)) % 4) return IRQ_HANDLED; - if ((packet & 0xffff0000) != HIL_ERR_INT) { - hil_ptr_process_err(ptr); - return IRQ_HANDLED; - } - if (packet & HIL_PKT_CMD) - hil_ptr_process_record(ptr); - return IRQ_HANDLED; -} - -static void hil_ptr_disconnect(struct serio *serio) -{ - struct hil_ptr *ptr; - - ptr = (struct hil_ptr *)serio->private; - if (ptr == NULL) { - BUG(); - return; - } - - input_unregister_device(&ptr->dev); - serio_close(serio); - kfree(ptr); -} - -static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver) -{ - struct hil_ptr *ptr; - char *txt; - unsigned int i, naxsets, btntype; - uint8_t did, *idd; - - if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return; - - if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return; - memset(ptr, 0, sizeof(struct hil_ptr)); - - if (serio_open(serio, driver)) goto bail0; - - serio->private = ptr; - ptr->serio = serio; - ptr->dev.private = ptr; - - init_MUTEX_LOCKED(&(ptr->sem)); - - /* Get device info. MLC driver supplies devid/status/etc. */ - serio->write(serio, 0); - serio->write(serio, 0); - serio->write(serio, HIL_PKT_CMD >> 8); - serio->write(serio, HIL_CMD_IDD); - down(&(ptr->sem)); - - serio->write(serio, 0); - serio->write(serio, 0); - serio->write(serio, HIL_PKT_CMD >> 8); - serio->write(serio, HIL_CMD_RSC); - down(&(ptr->sem)); - - serio->write(serio, 0); - serio->write(serio, 0); - serio->write(serio, HIL_PKT_CMD >> 8); - serio->write(serio, HIL_CMD_RNM); - down(&(ptr->sem)); - - serio->write(serio, 0); - serio->write(serio, 0); - serio->write(serio, HIL_PKT_CMD >> 8); - serio->write(serio, HIL_CMD_EXD); - down(&(ptr->sem)); - - up(&(ptr->sem)); - - init_input_dev(&ptr->dev); - did = ptr->idd[0]; - idd = ptr->idd + 1; - txt = "unknown"; - if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { - ptr->dev.evbit[0] = BIT(EV_REL); - txt = "relative"; - } - - if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) { - ptr->dev.evbit[0] = BIT(EV_ABS); - txt = "absolute"; - } - if (!ptr->dev.evbit[0]) { - goto bail1; - } - - ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); - if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY); - - naxsets = HIL_IDD_NUM_AXSETS(*idd); - ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); - - printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n", - did, txt); - printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n", - ptr->nbtn, naxsets, ptr->naxes); - - btntype = BTN_MISC; - if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) -#ifdef TABLET_SIMULATES_MOUSE - btntype = BTN_TOUCH; -#else - btntype = BTN_DIGI; -#endif - if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) - btntype = BTN_TOUCH; - - if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) - btntype = BTN_MOUSE; - - for (i = 0; i < ptr->nbtn; i++) { - set_bit(btntype | i, ptr->dev.keybit); - ptr->btnmap[i] = btntype | i; - } - - if (btntype == BTN_MOUSE) { - /* Swap buttons 2 and 3 */ - ptr->btnmap[1] = BTN_MIDDLE; - ptr->btnmap[2] = BTN_RIGHT; - } - - if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { - for (i = 0; i < ptr->naxes; i++) { - set_bit(REL_X + i, ptr->dev.relbit); - } - for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { - set_bit(REL_X + i, ptr->dev.relbit); - } - } else { - for (i = 0; i < ptr->naxes; i++) { - set_bit(ABS_X + i, ptr->dev.absbit); - ptr->dev.absmin[ABS_X + i] = 0; - ptr->dev.absmax[ABS_X + i] = - HIL_IDD_AXIS_MAX((ptr->idd + 1), i); - } - for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { - set_bit(ABS_X + i, ptr->dev.absbit); - ptr->dev.absmin[ABS_X + i] = 0; - ptr->dev.absmax[ABS_X + i] = - HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3)); - } -#ifdef TABLET_AUTOADJUST - for (i = 0; i < ABS_MAX; i++) { - int diff = ptr->dev.absmax[ABS_X + i] / 10; - ptr->dev.absmin[ABS_X + i] += diff; - ptr->dev.absmax[ABS_X + i] -= diff; - } -#endif - } - - ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; - - ptr->dev.id.bustype = BUS_HIL; - ptr->dev.id.vendor = PCI_VENDOR_ID_HP; - ptr->dev.id.product = 0x0001; /* TODO: get from ptr->rsc */ - ptr->dev.id.version = 0x0100; /* TODO: get from ptr->rsc */ - ptr->dev.dev = &serio->dev; - - input_register_device(&ptr->dev); - printk(KERN_INFO "input: %s (%s), ID: %d\n", - ptr->dev.name, - (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad", - did); - - return; - bail1: - serio_close(serio); - bail0: - kfree(ptr); - return; -} - - -static struct serio_driver hil_ptr_serio_driver = { - .driver = { - .name = "hil_ptr", - }, - .description = "HP HIL mouse/tablet driver", - .connect = hil_ptr_connect, - .disconnect = hil_ptr_disconnect, - .interrupt = hil_ptr_interrupt -}; - -static int __init hil_ptr_init(void) -{ - serio_register_driver(&hil_ptr_serio_driver); - return 0; -} - -static void __exit hil_ptr_exit(void) -{ - serio_unregister_driver(&hil_ptr_serio_driver); -} - -module_init(hil_ptr_init); -module_exit(hil_ptr_exit); diff -u b/drivers/input/mousedev.c b/drivers/input/mousedev.c --- b/drivers/input/mousedev.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/mousedev.c 2005-02-09 18:51:40 -08:00 @@ -455,7 +455,7 @@ switch (list->mode) { case MOUSEDEV_EMUL_EXPS: - ps2_data[3] = mousedev_limit_delta(p->dz, 7); + ps2_data[3] = mousedev_limit_delta(p->dz, 127); p->dz -= ps2_data[3]; ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); list->bufsiz = 4; @@ -595,8 +595,9 @@ { struct mousedev_list *list = file->private_data; poll_wait(file, &list->mousedev->wait, wait); - return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) | - (list->mousedev->exist ? 0 : (POLLHUP | POLLERR)); + if (list->ready || list->buffer) + return POLLIN | POLLRDNORM; + return 0; } static struct file_operations mousedev_fops = { @@ -652,7 +653,6 @@ static void mousedev_disconnect(struct input_handle *handle) { struct mousedev *mousedev = handle->private; - struct mousedev_list *list; class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); devfs_remove("input/mouse%d", mousedev->minor); @@ -660,9 +660,6 @@ if (mousedev->open) { input_close_device(handle); - wake_up_interruptible(&mousedev->wait); - list_for_each_entry(list, &mousedev->list, node) - kill_fasync(&list->fasync, SIGIO, POLL_HUP); } else { if (mousedev_mix.open) input_close_device(handle); diff -u b/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig --- b/drivers/input/serio/Kconfig 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/serio/Kconfig 2005-02-09 18:51:40 -08:00 @@ -48,7 +48,7 @@ config SERIO_CT82C710 tristate "ct82c710 Aux port controller" - depends on X86 + 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 @@ -110,32 +110,6 @@ To compile this driver as a module, choose M here: the module will be called gscps2. -config HP_SDC - tristate "HP System Device Controller i8042 Support" - depends on GSC && SERIO - default y - ---help--- - This option enables supports for the the "System Device - Controller", an i8042 carrying microcode to manage a - few miscellanous devices on some Hewlett Packard systems. - The SDC itself contains a 10ms resolution timer/clock capable - of delivering interrupts on a periodic and one-shot basis. - The SDC may also be connected to a battery-backed real-time - clock, a basic audio waveform generator, and an HP-HIL Master - Link Controller serving up to seven input devices. - - By itself this option is rather useless, but enabling it will - enable selection of drivers for the abovementioned devices. - It is, however, incompatible with the old, reliable HIL keyboard - driver, and the new HIL driver is experimental, so if you plan - to use a HIL keyboard as your primary keyboard, you may wish - to keep using that driver until the new HIL drivers have had - more testing. - -config HIL_MLC - tristate "HIL MLC Support (needed for HIL input devices)" - depends on HP_SDC - config SERIO_PCIPS2 tristate "PCI PS/2 keyboard and PS/2 mouse controller" depends on PCI reverted: --- b/drivers/input/serio/Makefile 2005-02-09 19:00:45 -08:00 +++ a/drivers/input/serio/Makefile 2005-02-09 19:00:45 -08:00 @@ -15,8 +15,6 @@ obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o -obj-$(CONFIG_HP_SDC) += hp_sdc.o -obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o obj-$(CONFIG_SERIO_LIBPS2) += libps2.o diff -u b/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c --- b/drivers/input/serio/gscps2.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/serio/gscps2.c 2005-02-09 18:51:40 -08:00 @@ -38,7 +38,7 @@ #include MODULE_AUTHOR("Laurent Canet , Thibaut Varene , Helge Deller "); -MODULE_DESCRIPTION("HP GSC PS2 port driver"); +MODULE_DESCRIPTION("HP GSC PS/2 port driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl); @@ -444,7 +444,7 @@ }; static struct parisc_driver parisc_ps2_driver = { - .name = "GSC PS2", + .name = "GSC PS/2", .id_table = gscps2_device_tbl, .probe = gscps2_probe, .remove = gscps2_remove, reverted: --- b/drivers/input/serio/hil_mlc.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,949 +0,0 @@ -/* - * HIL MLC state machine and serio interface driver - * - * Copyright (c) 2001 Brian S. Julin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * - * References: - * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A - * - * - * Driver theory of operation: - * - * Some access methods and an ISR is defined by the sub-driver - * (e.g. hp_sdc_mlc.c). These methods are expected to provide a - * few bits of logic in addition to raw access to the HIL MLC, - * specifically, the ISR, which is entirely registered by the - * sub-driver and invoked directly, must check for record - * termination or packet match, at which point a semaphore must - * be cleared and then the hil_mlcs_tasklet must be scheduled. - * - * The hil_mlcs_tasklet processes the state machine for all MLCs - * each time it runs, checking each MLC's progress at the current - * node in the state machine, and moving the MLC to subsequent nodes - * in the state machine when appropriate. It will reschedule - * itself if output is pending. (This rescheduling should be replaced - * at some point with a sub-driver-specific mechanism.) - * - * A timer task prods the tasklet once per second to prevent - * hangups when attached devices do not return expected data - * and to initiate probes of the loop for new devices. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Brian S. Julin "); -MODULE_DESCRIPTION("HIL MLC serio"); -MODULE_LICENSE("Dual BSD/GPL"); - -EXPORT_SYMBOL(hil_mlc_register); -EXPORT_SYMBOL(hil_mlc_unregister); - -#define PREFIX "HIL MLC: " - -static LIST_HEAD(hil_mlcs); -static rwlock_t hil_mlcs_lock = RW_LOCK_UNLOCKED; -static struct timer_list hil_mlcs_kicker; -static int hil_mlcs_probe; - -static void hil_mlcs_process(unsigned long unused); -DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0); - - -/* #define HIL_MLC_DEBUG */ - -/********************** Device info/instance management **********************/ - -static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) { - int j; - for (j = val; j < 7 ; j++) { - mlc->di_map[j] = -1; - } -} - -static void hil_mlc_clear_di_scratch (hil_mlc *mlc) { - memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch)); -} - -static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) { - memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch)); -} - -static int hil_mlc_match_di_scratch (hil_mlc *mlc) { - int idx; - - for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { - int j, found; - - /* In-use slots are not eligible. */ - found = 0; - for (j = 0; j < 7 ; j++) { - if (mlc->di_map[j] == idx) found++; - } - if (found) continue; - if (!memcmp(mlc->di + idx, - &(mlc->di_scratch), - sizeof(mlc->di_scratch))) break; - } - return((idx >= HIL_MLC_DEVMEM) ? -1 : idx); -} - -static int hil_mlc_find_free_di(hil_mlc *mlc) { - int idx; - /* TODO: Pick all-zero slots first, failing that, - * randomize the slot picked among those eligible. - */ - for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { - int j, found; - found = 0; - for (j = 0; j < 7 ; j++) { - if (mlc->di_map[j] == idx) found++; - } - if (!found) break; - } - return(idx); /* Note: It is guaranteed at least one above will match */ -} - -static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) { - int idx; - for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { - int j, found; - found = 0; - for (j = 0; j < 7 ; j++) { - if (mlc->di_map[j] == idx) found++; - } - if (!found) mlc->serio_map[idx].di_revmap = -1; - } -} - -static void hil_mlc_send_polls(hil_mlc *mlc) { - int did, i, cnt; - struct serio *serio; - struct serio_driver *drv; - - i = cnt = 0; - did = (mlc->ipacket[0] & HIL_PKT_ADDR_MASK) >> 8; - serio = did ? mlc->serio[mlc->di_map[did - 1]] : NULL; - drv = (serio != NULL) ? serio->drv : NULL; - - while (mlc->icount < 15 - i) { - hil_packet p; - p = mlc->ipacket[i]; - if (did != (p & HIL_PKT_ADDR_MASK) >> 8) { - if (drv == NULL || drv->interrupt == NULL) goto skip; - - drv->interrupt(serio, 0, 0, NULL); - drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL); - drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL); - drv->interrupt(serio, HIL_CMD_POL + cnt, 0, NULL); - skip: - did = (p & HIL_PKT_ADDR_MASK) >> 8; - serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL; - drv = (serio != NULL) ? serio->drv : NULL; - cnt = 0; - } - cnt++; i++; - if (drv == NULL || drv->interrupt == NULL) continue; - drv->interrupt(serio, (p >> 24), 0, NULL); - drv->interrupt(serio, (p >> 16) & 0xff, 0, NULL); - drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0, NULL); - drv->interrupt(serio, p & 0xff, 0, NULL); - } -} - -/*************************** State engine *********************************/ - -#define HILSEN_SCHED 0x000100 /* Schedule the tasklet */ -#define HILSEN_BREAK 0x000200 /* Wait until next pass */ -#define HILSEN_UP 0x000400 /* relative node#, decrement */ -#define HILSEN_DOWN 0x000800 /* relative node#, increment */ -#define HILSEN_FOLLOW 0x001000 /* use retval as next node# */ - -#define HILSEN_MASK 0x0000ff -#define HILSEN_START 0 -#define HILSEN_RESTART 1 -#define HILSEN_DHR 9 -#define HILSEN_DHR2 10 -#define HILSEN_IFC 14 -#define HILSEN_HEAL0 16 -#define HILSEN_HEAL 18 -#define HILSEN_ACF 21 -#define HILSEN_ACF2 22 -#define HILSEN_DISC0 25 -#define HILSEN_DISC 27 -#define HILSEN_MATCH 40 -#define HILSEN_OPERATE 41 -#define HILSEN_PROBE 44 -#define HILSEN_DSR 52 -#define HILSEN_REPOLL 55 -#define HILSEN_IFCACF 58 -#define HILSEN_END 60 - -#define HILSEN_NEXT (HILSEN_DOWN | 1) -#define HILSEN_SAME (HILSEN_DOWN | 0) -#define HILSEN_LAST (HILSEN_UP | 1) - -#define HILSEN_DOZE (HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK) -#define HILSEN_SLEEP (HILSEN_SAME | HILSEN_BREAK) - -static int hilse_match(hil_mlc *mlc, int unused) { - int rc; - rc = hil_mlc_match_di_scratch(mlc); - if (rc == -1) { - rc = hil_mlc_find_free_di(mlc); - if (rc == -1) goto err; -#ifdef HIL_MLC_DEBUG - printk(KERN_DEBUG PREFIX "new in slot %i\n", rc); -#endif - hil_mlc_copy_di_scratch(mlc, rc); - mlc->di_map[mlc->ddi] = rc; - mlc->serio_map[rc].di_revmap = mlc->ddi; - hil_mlc_clean_serio_map(mlc); - serio_rescan(mlc->serio[rc]); - return -1; - } - mlc->di_map[mlc->ddi] = rc; -#ifdef HIL_MLC_DEBUG - printk(KERN_DEBUG PREFIX "same in slot %i\n", rc); -#endif - mlc->serio_map[rc].di_revmap = mlc->ddi; - hil_mlc_clean_serio_map(mlc); - return 0; - err: - printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n"); - return 1; -} - -/* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */ -static int hilse_init_lcv(hil_mlc *mlc, int unused) { - struct timeval tv; - - do_gettimeofday(&tv); - - if(mlc->lcv == 0) goto restart; /* First init, no need to dally */ - if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1; - restart: - mlc->lcv_tv = tv; - mlc->lcv = 0; - return 0; -} - -static int hilse_inc_lcv(hil_mlc *mlc, int lim) { - if (mlc->lcv++ >= lim) return -1; - return 0; -} - -#if 0 -static int hilse_set_lcv(hil_mlc *mlc, int val) { - mlc->lcv = val; - return 0; -} -#endif - -/* Management of the discovered device index (zero based, -1 means no devs) */ -static int hilse_set_ddi(hil_mlc *mlc, int val) { - mlc->ddi = val; - hil_mlc_clear_di_map(mlc, val + 1); - return 0; -} - -static int hilse_dec_ddi(hil_mlc *mlc, int unused) { - mlc->ddi--; - if (mlc->ddi <= -1) { - mlc->ddi = -1; - hil_mlc_clear_di_map(mlc, 0); - return -1; - } - hil_mlc_clear_di_map(mlc, mlc->ddi + 1); - return 0; -} - -static int hilse_inc_ddi(hil_mlc *mlc, int unused) { - if (mlc->ddi >= 6) { - BUG(); - return -1; - } - mlc->ddi++; - return 0; -} - -static int hilse_take_idd(hil_mlc *mlc, int unused) { - int i; - - /* Help the state engine: - * Is this a real IDD response or just an echo? - * - * Real IDD response does not start with a command. - */ - if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail; - /* Should have the command echoed further down. */ - for (i = 1; i < 16; i++) { - if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == - (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) && - (mlc->ipacket[i] & HIL_PKT_CMD) && - ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD)) - break; - } - if (i > 15) goto bail; - /* And the rest of the packets should still be clear. */ - while (++i < 16) { - if (mlc->ipacket[i]) break; - } - if (i < 16) goto bail; - for (i = 0; i < 16; i++) { - mlc->di_scratch.idd[i] = - mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } - /* Next step is to see if RSC supported */ - if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) - return HILSEN_NEXT; - if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) - return HILSEN_DOWN | 4; - return 0; - bail: - mlc->ddi--; - return -1; /* This should send us off to ACF */ -} - -static int hilse_take_rsc(hil_mlc *mlc, int unused) { - int i; - - for (i = 0; i < 16; i++) { - mlc->di_scratch.rsc[i] = - mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } - /* Next step is to see if EXD supported (IDD has already been read) */ - if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) - return HILSEN_NEXT; - return 0; -} - -static int hilse_take_exd(hil_mlc *mlc, int unused) { - int i; - - for (i = 0; i < 16; i++) { - mlc->di_scratch.exd[i] = - mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } - /* Next step is to see if RNM supported. */ - if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) - return HILSEN_NEXT; - return 0; -} - -static int hilse_take_rnm(hil_mlc *mlc, int unused) { - int i; - - for (i = 0; i < 16; i++) { - mlc->di_scratch.rnm[i] = - mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } - do { - char nam[17]; - snprintf(nam, 16, "%s", mlc->di_scratch.rnm); - nam[16] = '\0'; - printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam); - } while (0); - return 0; -} - -static int hilse_operate(hil_mlc *mlc, int repoll) { - - if (mlc->opercnt == 0) hil_mlcs_probe = 0; - mlc->opercnt = 1; - - hil_mlc_send_polls(mlc); - - if (!hil_mlcs_probe) return 0; - hil_mlcs_probe = 0; - mlc->opercnt = 0; - return 1; -} - -#define FUNC(funct, funct_arg, zero_rc, neg_rc, pos_rc) \ -{ HILSE_FUNC, { func: &funct }, funct_arg, zero_rc, neg_rc, pos_rc }, -#define OUT(pack) \ -{ HILSE_OUT, { packet: pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 }, -#define CTS \ -{ HILSE_CTS, { packet: 0 }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 }, -#define EXPECT(comp, to, got, got_wrong, timed_out) \ -{ HILSE_EXPECT, { packet: comp }, to, got, got_wrong, timed_out }, -#define EXPECT_LAST(comp, to, got, got_wrong, timed_out) \ -{ HILSE_EXPECT_LAST, { packet: comp }, to, got, got_wrong, timed_out }, -#define EXPECT_DISC(comp, to, got, got_wrong, timed_out) \ -{ HILSE_EXPECT_DISC, { packet: comp }, to, got, got_wrong, timed_out }, -#define IN(to, got, got_error, timed_out) \ -{ HILSE_IN, { packet: 0 }, to, got, got_error, timed_out }, -#define OUT_DISC(pack) \ -{ HILSE_OUT_DISC, { packet: pack }, 0, 0, 0, 0 }, -#define OUT_LAST(pack) \ -{ HILSE_OUT_LAST, { packet: pack }, 0, 0, 0, 0 }, - -struct hilse_node hil_mlc_se[HILSEN_END] = { - - /* 0 HILSEN_START */ - FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) - - /* 1 HILSEN_RESTART */ - FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0) - OUT(HIL_CTRL_ONLY) /* Disable APE */ - CTS - -#define TEST_PACKET(x) \ -(HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) | x << 4 | x) - - OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0x5)) - EXPECT(HIL_ERR_INT | TEST_PACKET(0x5), - 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART) - OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0xa)) - EXPECT(HIL_ERR_INT | TEST_PACKET(0xa), - 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART) - OUT(HIL_CTRL_ONLY | 0) /* Disable test mode */ - - /* 9 HILSEN_DHR */ - FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) - - /* 10 HILSEN_DHR2 */ - FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0) - FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0) - OUT(HIL_PKT_CMD | HIL_CMD_DHR) - IN(300000, HILSEN_DHR2, HILSEN_DHR2, HILSEN_NEXT) - - /* 14 HILSEN_IFC */ - OUT(HIL_PKT_CMD | HIL_CMD_IFC) - EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT, - 20000, HILSEN_DISC, HILSEN_DHR2, HILSEN_NEXT ) - - /* If devices are there, they weren't in PUP or other loopback mode. - * We're more concerned at this point with restoring operation - * to devices than discovering new ones, so we try to salvage - * the loop configuration by closing off the loop. - */ - - /* 16 HILSEN_HEAL0 */ - FUNC(hilse_dec_ddi, 0, HILSEN_NEXT, HILSEN_ACF, 0) - FUNC(hilse_inc_ddi, 0, HILSEN_NEXT, 0, 0) - - /* 18 HILSEN_HEAL */ - OUT_LAST(HIL_CMD_ELB) - EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, - 20000, HILSEN_REPOLL, HILSEN_DSR, HILSEN_NEXT) - FUNC(hilse_dec_ddi, 0, HILSEN_HEAL, HILSEN_NEXT, 0) - - /* 21 HILSEN_ACF */ - FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_DOZE, 0) - - /* 22 HILSEN_ACF2 */ - FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0) - OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1) - IN(20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT) - - /* 25 HILSEN_DISC0 */ - OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB) - EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_ELB | HIL_ERR_INT, - 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR) - - /* Only enter here if response just received */ - /* 27 HILSEN_DISC */ - OUT_DISC(HIL_PKT_CMD | HIL_CMD_IDD) - EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_IDD | HIL_ERR_INT, - 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_START) - FUNC(hilse_inc_ddi, 0, HILSEN_NEXT, HILSEN_START, 0) - FUNC(hilse_take_idd, 0, HILSEN_MATCH, HILSEN_IFCACF, HILSEN_FOLLOW) - OUT_LAST(HIL_PKT_CMD | HIL_CMD_RSC) - EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RSC | HIL_ERR_INT, - 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR) - FUNC(hilse_take_rsc, 0, HILSEN_MATCH, 0, HILSEN_FOLLOW) - OUT_LAST(HIL_PKT_CMD | HIL_CMD_EXD) - EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_EXD | HIL_ERR_INT, - 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR) - FUNC(hilse_take_exd, 0, HILSEN_MATCH, 0, HILSEN_FOLLOW) - OUT_LAST(HIL_PKT_CMD | HIL_CMD_RNM) - EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RNM | HIL_ERR_INT, - 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR) - FUNC(hilse_take_rnm, 0, HILSEN_MATCH, 0, 0) - - /* 40 HILSEN_MATCH */ - FUNC(hilse_match, 0, HILSEN_NEXT, HILSEN_NEXT, /* TODO */ 0) - - /* 41 HILSEN_OPERATE */ - OUT(HIL_PKT_CMD | HIL_CMD_POL) - EXPECT(HIL_PKT_CMD | HIL_CMD_POL | HIL_ERR_INT, - 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT) - FUNC(hilse_operate, 0, HILSEN_OPERATE, HILSEN_IFC, HILSEN_NEXT) - - /* 44 HILSEN_PROBE */ - OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT) - IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) - OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB) - IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) - OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1) - IN(10000, HILSEN_DISC0, HILSEN_DSR, HILSEN_NEXT) - OUT_LAST(HIL_PKT_CMD | HIL_CMD_ELB) - IN(10000, HILSEN_OPERATE, HILSEN_DSR, HILSEN_DSR) - - /* 52 HILSEN_DSR */ - FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0) - OUT(HIL_PKT_CMD | HIL_CMD_DSR) - IN(20000, HILSEN_DHR, HILSEN_DHR, HILSEN_IFC) - - /* 55 HILSEN_REPOLL */ - OUT(HIL_PKT_CMD | HIL_CMD_RPL) - EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT, - 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT) - FUNC(hilse_operate, 1, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE) - - /* 58 HILSEN_IFCACF */ - OUT(HIL_PKT_CMD | HIL_CMD_IFC) - EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT, - 20000, HILSEN_ACF2, HILSEN_DHR2, HILSEN_HEAL) - - /* 60 HILSEN_END */ -}; - -static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) { - - switch (node->act) { - case HILSE_EXPECT_DISC: - mlc->imatch = node->object.packet; - mlc->imatch |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT); - break; - case HILSE_EXPECT_LAST: - mlc->imatch = node->object.packet; - mlc->imatch |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT); - break; - case HILSE_EXPECT: - mlc->imatch = node->object.packet; - break; - case HILSE_IN: - mlc->imatch = 0; - break; - default: - BUG(); - } - mlc->istarted = 1; - mlc->intimeout = node->arg; - do_gettimeofday(&(mlc->instart)); - mlc->icount = 15; - memset(mlc->ipacket, 0, 16 * sizeof(hil_packet)); - if (down_trylock(&(mlc->isem))) BUG(); - - return; -} - -#ifdef HIL_MLC_DEBUG -static int doze = 0; -static int seidx; /* For debug */ -static int kick = 1; -#endif - -static int hilse_donode (hil_mlc *mlc) { - struct hilse_node *node; - int nextidx = 0; - int sched_long = 0; - unsigned long flags; - -#ifdef HIL_MLC_DEBUG - if (mlc->seidx && (mlc->seidx != seidx) && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) { - printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx); - doze = 0; - } - kick = 0; - - seidx = mlc->seidx; -#endif - node = hil_mlc_se + mlc->seidx; - - switch (node->act) { - int rc; - hil_packet pack; - - case HILSE_FUNC: - if (node->object.func == NULL) break; - rc = node->object.func(mlc, node->arg); - nextidx = (rc > 0) ? node->ugly : - ((rc < 0) ? node->bad : node->good); - if (nextidx == HILSEN_FOLLOW) nextidx = rc; - break; - case HILSE_EXPECT_LAST: - case HILSE_EXPECT_DISC: - case HILSE_EXPECT: - case HILSE_IN: - /* Already set up from previous HILSE_OUT_* */ - write_lock_irqsave(&(mlc->lock), flags); - rc = mlc->in(mlc, node->arg); - if (rc == 2) { - nextidx = HILSEN_DOZE; - sched_long = 1; - write_unlock_irqrestore(&(mlc->lock), flags); - break; - } - if (rc == 1) nextidx = node->ugly; - else if (rc == 0) nextidx = node->good; - else nextidx = node->bad; - mlc->istarted = 0; - write_unlock_irqrestore(&(mlc->lock), flags); - break; - case HILSE_OUT_LAST: - write_lock_irqsave(&(mlc->lock), flags); - pack = node->object.packet; - pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT); - goto out; - case HILSE_OUT_DISC: - write_lock_irqsave(&(mlc->lock), flags); - pack = node->object.packet; - pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT); - goto out; - case HILSE_OUT: - write_lock_irqsave(&(mlc->lock), flags); - pack = node->object.packet; - out: - if (mlc->istarted) goto out2; - /* Prepare to receive input */ - if ((node + 1)->act & HILSE_IN) - hilse_setup_input(mlc, node + 1); - - out2: - write_unlock_irqrestore(&(mlc->lock), flags); - - if (down_trylock(&mlc->osem)) { - nextidx = HILSEN_DOZE; - break; - } - up(&mlc->osem); - - write_lock_irqsave(&(mlc->lock), flags); - if (!(mlc->ostarted)) { - mlc->ostarted = 1; - mlc->opacket = pack; - mlc->out(mlc); - nextidx = HILSEN_DOZE; - write_unlock_irqrestore(&(mlc->lock), flags); - break; - } - mlc->ostarted = 0; - do_gettimeofday(&(mlc->instart)); - write_unlock_irqrestore(&(mlc->lock), flags); - nextidx = HILSEN_NEXT; - break; - case HILSE_CTS: - nextidx = mlc->cts(mlc) ? node->bad : node->good; - break; - default: - BUG(); - nextidx = 0; - break; - } - -#ifdef HIL_MLC_DEBUG - if (nextidx == HILSEN_DOZE) doze++; -#endif - - while (nextidx & HILSEN_SCHED) { - struct timeval tv; - - if (!sched_long) goto sched; - - do_gettimeofday(&tv); - tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec); - tv.tv_usec -= mlc->instart.tv_usec; - if (tv.tv_usec >= mlc->intimeout) goto sched; - tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000; - if (!tv.tv_usec) goto sched; - mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec); - break; - sched: - tasklet_schedule(&hil_mlcs_tasklet); - break; - } - if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK; - else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK; - else mlc->seidx = nextidx & HILSEN_MASK; - - if (nextidx & HILSEN_BREAK) return 1; - return 0; -} - -/******************** tasklet context functions **************************/ -static void hil_mlcs_process(unsigned long unused) { - struct list_head *tmp; - - read_lock(&hil_mlcs_lock); - list_for_each(tmp, &hil_mlcs) { - struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list); - while (hilse_donode(mlc) == 0) { -#ifdef HIL_MLC_DEBUG - if (mlc->seidx != 41 && - mlc->seidx != 42 && - mlc->seidx != 43) - printk(KERN_DEBUG PREFIX " + "); -#endif - }; - } - read_unlock(&hil_mlcs_lock); -} - -/************************* Keepalive timer task *********************/ - -void hil_mlcs_timer (unsigned long data) { - hil_mlcs_probe = 1; - tasklet_schedule(&hil_mlcs_tasklet); - /* Re-insert the periodic task. */ - if (!timer_pending(&hil_mlcs_kicker)) - mod_timer(&hil_mlcs_kicker, jiffies + HZ); -} - -/******************** user/kernel context functions **********************/ - -static int hil_mlc_serio_write(struct serio *serio, unsigned char c) { - struct hil_mlc_serio_map *map; - struct hil_mlc *mlc; - struct serio_driver *drv; - uint8_t *idx, *last; - - map = serio->port_data; - if (map == NULL) { - BUG(); - return -EIO; - } - mlc = map->mlc; - if (mlc == NULL) { - BUG(); - return -EIO; - } - mlc->serio_opacket[map->didx] |= - ((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx])); - - if (mlc->serio_oidx[map->didx] >= 3) { - /* for now only commands */ - if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) - return -EIO; - switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) { - case HIL_CMD_IDD: - idx = mlc->di[map->didx].idd; - goto emu; - case HIL_CMD_RSC: - idx = mlc->di[map->didx].rsc; - goto emu; - case HIL_CMD_EXD: - idx = mlc->di[map->didx].exd; - goto emu; - case HIL_CMD_RNM: - idx = mlc->di[map->didx].rnm; - goto emu; - default: - break; - } - mlc->serio_oidx[map->didx] = 0; - mlc->serio_opacket[map->didx] = 0; - } - - mlc->serio_oidx[map->didx]++; - return -EIO; - emu: - drv = serio->drv; - if (drv == NULL) { - BUG(); - return -EIO; - } - last = idx + 15; - while ((last != idx) && (*last == 0)) last--; - - while (idx != last) { - drv->interrupt(serio, 0, 0, NULL); - drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL); - drv->interrupt(serio, 0, 0, NULL); - drv->interrupt(serio, *idx, 0, NULL); - idx++; - } - drv->interrupt(serio, 0, 0, NULL); - drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL); - drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL); - drv->interrupt(serio, *idx, 0, NULL); - - mlc->serio_oidx[map->didx] = 0; - mlc->serio_opacket[map->didx] = 0; - - return 0; -} - -static int hil_mlc_serio_open(struct serio *serio) { - struct hil_mlc_serio_map *map; - struct hil_mlc *mlc; - - if (serio->private != NULL) return -EBUSY; - - map = serio->port_data; - if (map == NULL) { - BUG(); - return -ENODEV; - } - mlc = map->mlc; - if (mlc == NULL) { - BUG(); - return -ENODEV; - } - - return 0; -} - -static void hil_mlc_serio_close(struct serio *serio) { - struct hil_mlc_serio_map *map; - struct hil_mlc *mlc; - - map = serio->port_data; - if (map == NULL) { - BUG(); - return; - } - mlc = map->mlc; - if (mlc == NULL) { - BUG(); - return; - } - - serio->private = NULL; - serio->drv = NULL; - /* TODO wake up interruptable */ -} - -int hil_mlc_register(hil_mlc *mlc) { - int i; - unsigned long flags; - - if (mlc == NULL) { - return -EINVAL; - } - - mlc->istarted = 0; - mlc->ostarted = 0; - - mlc->lock = RW_LOCK_UNLOCKED; - init_MUTEX(&(mlc->osem)); - - init_MUTEX(&(mlc->isem)); - mlc->icount = -1; - mlc->imatch = 0; - - mlc->opercnt = 0; - - init_MUTEX_LOCKED(&(mlc->csem)); - - hil_mlc_clear_di_scratch(mlc); - hil_mlc_clear_di_map(mlc, 0); - for (i = 0; i < HIL_MLC_DEVMEM; i++) { - struct serio *mlc_serio; - hil_mlc_copy_di_scratch(mlc, i); - mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL); - mlc->serio[i] = mlc_serio; - memset(mlc_serio, 0, sizeof(*mlc_serio)); - mlc_serio->type = SERIO_HIL | SERIO_HIL_MLC; - mlc_serio->write = hil_mlc_serio_write; - mlc_serio->open = hil_mlc_serio_open; - mlc_serio->close = hil_mlc_serio_close; - mlc_serio->port_data = &(mlc->serio_map[i]); - mlc->serio_map[i].mlc = mlc; - mlc->serio_map[i].didx = i; - mlc->serio_map[i].di_revmap = -1; - mlc->serio_opacket[i] = 0; - mlc->serio_oidx[i] = 0; - serio_register_port(mlc_serio); - } - - mlc->tasklet = &hil_mlcs_tasklet; - - write_lock_irqsave(&hil_mlcs_lock, flags); - list_add_tail(&mlc->list, &hil_mlcs); - mlc->seidx = HILSEN_START; - write_unlock_irqrestore(&hil_mlcs_lock, flags); - - tasklet_schedule(&hil_mlcs_tasklet); - return 0; -} - -int hil_mlc_unregister(hil_mlc *mlc) { - struct list_head *tmp; - unsigned long flags; - int i; - - if (mlc == NULL) - return -EINVAL; - - write_lock_irqsave(&hil_mlcs_lock, flags); - list_for_each(tmp, &hil_mlcs) { - if (list_entry(tmp, hil_mlc, list) == mlc) - goto found; - } - - /* not found in list */ - write_unlock_irqrestore(&hil_mlcs_lock, flags); - tasklet_schedule(&hil_mlcs_tasklet); - return -ENODEV; - - found: - list_del(tmp); - write_unlock_irqrestore(&hil_mlcs_lock, flags); - - for (i = 0; i < HIL_MLC_DEVMEM; i++) { - serio_unregister_port(mlc->serio[i]); - mlc->serio[i] = NULL; - } - - tasklet_schedule(&hil_mlcs_tasklet); - return 0; -} - -/**************************** Module interface *************************/ - -static int __init hil_mlc_init(void) -{ - init_timer(&hil_mlcs_kicker); - hil_mlcs_kicker.expires = jiffies + HZ; - hil_mlcs_kicker.function = &hil_mlcs_timer; - add_timer(&hil_mlcs_kicker); - - tasklet_enable(&hil_mlcs_tasklet); - - return 0; -} - -static void __exit hil_mlc_exit(void) -{ - del_timer(&hil_mlcs_kicker); - - tasklet_disable(&hil_mlcs_tasklet); - tasklet_kill(&hil_mlcs_tasklet); -} - -module_init(hil_mlc_init); -module_exit(hil_mlc_exit); reverted: --- b/drivers/input/serio/hp_sdc.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,1055 +0,0 @@ -/* - * HP i8042-based System Device Controller driver. - * - * Copyright (c) 2001 Brian S. Julin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * - * References: - * System Device Controller Microprocessor Firmware Theory of Operation - * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 - * Helge Deller's original hilkbd.c port for PA-RISC. - * - * - * Driver theory of operation: - * - * hp_sdc_put does all writing to the SDC. ISR can run on a different - * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time - * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly. - * - * All data coming back from the SDC is sent via interrupt and can be read - * fully in the ISR, so there are no latency/throughput problems there. - * The problem is with output, due to the slow clock speed of the SDC - * compared to the CPU. This should not be too horrible most of the time, - * but if used with HIL devices that support the multibyte transfer command, - * keeping outbound throughput flowing at the 6500KBps that the HIL is - * capable of is more than can be done at HZ=100. - * - * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf - * is set to 0 when the IBF flag in the status register has cleared. ISR - * may do this, and may also access the parts of queued transactions related - * to reading data back from the SDC, but otherwise will not touch the - * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1. - * - * The i8042 write index and the values in the 4-byte input buffer - * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively, - * to minimize the amount of IO needed to the SDC. However these values - * do not need to be locked since they are only ever accessed by hp_sdc_put. - * - * A timer task schedules the tasklet once per second just to make - * sure it doesn't freeze up and to allow for bad reads to time out. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Machine-specific abstraction */ - -#if defined(__hppa__) -# include -# define sdc_readb(p) gsc_readb(p) -# define sdc_writeb(v,p) gsc_writeb((v),(p)) -#elif defined(__mc68000__) -# include -# define sdc_readb(p) in_8(p) -# define sdc_writeb(v,p) out_8((p),(v)) -#else -# error "HIL is not supported on this platform" -#endif - -#define PREFIX "HP SDC: " - -MODULE_AUTHOR("Brian S. Julin "); -MODULE_DESCRIPTION("HP i8042-based SDC Driver"); -MODULE_LICENSE("Dual BSD/GPL"); - -EXPORT_SYMBOL(hp_sdc_request_timer_irq); -EXPORT_SYMBOL(hp_sdc_request_hil_irq); -EXPORT_SYMBOL(hp_sdc_request_cooked_irq); - -EXPORT_SYMBOL(hp_sdc_release_timer_irq); -EXPORT_SYMBOL(hp_sdc_release_hil_irq); -EXPORT_SYMBOL(hp_sdc_release_cooked_irq); - -EXPORT_SYMBOL(hp_sdc_enqueue_transaction); -EXPORT_SYMBOL(hp_sdc_dequeue_transaction); - -static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */ - -/*************** primitives for use in any context *********************/ -static inline uint8_t hp_sdc_status_in8 (void) { - uint8_t status; - unsigned long flags; - - write_lock_irqsave(&hp_sdc.ibf_lock, flags); - status = sdc_readb(hp_sdc.status_io); - if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0; - write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); - - return status; -} - -static inline uint8_t hp_sdc_data_in8 (void) { - return sdc_readb(hp_sdc.data_io); -} - -static inline void hp_sdc_status_out8 (uint8_t val) { - unsigned long flags; - - write_lock_irqsave(&hp_sdc.ibf_lock, flags); - hp_sdc.ibf = 1; - if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff; - sdc_writeb(val, hp_sdc.status_io); - write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); -} - -static inline void hp_sdc_data_out8 (uint8_t val) { - unsigned long flags; - - write_lock_irqsave(&hp_sdc.ibf_lock, flags); - hp_sdc.ibf = 1; - sdc_writeb(val, hp_sdc.data_io); - write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); -} - -/* Care must be taken to only invoke hp_sdc_spin_ibf when - * absolutely needed, or in rarely invoked subroutines. - * Not only does it waste CPU cycles, it also wastes bus cycles. - */ -static inline void hp_sdc_spin_ibf(void) { - unsigned long flags; - rwlock_t *lock; - - lock = &hp_sdc.ibf_lock; - - read_lock_irqsave(lock, flags); - if (!hp_sdc.ibf) { - read_unlock_irqrestore(lock, flags); - return; - } - read_unlock(lock); - write_lock(lock); - while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {}; - hp_sdc.ibf = 0; - write_unlock_irqrestore(lock, flags); -} - - -/************************ Interrupt context functions ************************/ -static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) { - hp_sdc_transaction *curr; - - read_lock(&hp_sdc.rtq_lock); - if (hp_sdc.rcurr < 0) { - read_unlock(&hp_sdc.rtq_lock); - return; - } - curr = hp_sdc.tq[hp_sdc.rcurr]; - read_unlock(&hp_sdc.rtq_lock); - - curr->seq[curr->idx++] = status; - curr->seq[curr->idx++] = data; - hp_sdc.rqty -= 2; - do_gettimeofday(&hp_sdc.rtv); - - if (hp_sdc.rqty <= 0) { - /* All data has been gathered. */ - if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) { - if (curr->act.semaphore) up(curr->act.semaphore); - } - if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) { - if (curr->act.irqhook) - curr->act.irqhook(irq, dev_id, status, data); - } - curr->actidx = curr->idx; - curr->idx++; - /* Return control of this transaction */ - write_lock(&hp_sdc.rtq_lock); - hp_sdc.rcurr = -1; - hp_sdc.rqty = 0; - write_unlock(&hp_sdc.rtq_lock); - tasklet_schedule(&hp_sdc.task); - } -} - -static irqreturn_t hp_sdc_isr(int irq, void *dev_id, struct pt_regs * regs) { - uint8_t status, data; - - status = hp_sdc_status_in8(); - /* Read data unconditionally to advance i8042. */ - data = hp_sdc_data_in8(); - - /* For now we are ignoring these until we get the SDC to behave. */ - if (((status & 0xf1) == 0x51) && data == 0x82) { - return IRQ_HANDLED; - } - - switch(status & HP_SDC_STATUS_IRQMASK) { - case 0: /* This case is not documented. */ - break; - case HP_SDC_STATUS_USERTIMER: - case HP_SDC_STATUS_PERIODIC: - case HP_SDC_STATUS_TIMER: - read_lock(&hp_sdc.hook_lock); - if (hp_sdc.timer != NULL) - hp_sdc.timer(irq, dev_id, status, data); - read_unlock(&hp_sdc.hook_lock); - break; - case HP_SDC_STATUS_REG: - hp_sdc_take(irq, dev_id, status, data); - break; - case HP_SDC_STATUS_HILCMD: - case HP_SDC_STATUS_HILDATA: - read_lock(&hp_sdc.hook_lock); - if (hp_sdc.hil != NULL) - hp_sdc.hil(irq, dev_id, status, data); - read_unlock(&hp_sdc.hook_lock); - break; - case HP_SDC_STATUS_PUP: - read_lock(&hp_sdc.hook_lock); - if (hp_sdc.pup != NULL) - hp_sdc.pup(irq, dev_id, status, data); - else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n"); - read_unlock(&hp_sdc.hook_lock); - break; - default: - read_lock(&hp_sdc.hook_lock); - if (hp_sdc.cooked != NULL) - hp_sdc.cooked(irq, dev_id, status, data); - read_unlock(&hp_sdc.hook_lock); - break; - } - return IRQ_HANDLED; -} - - -static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id, struct pt_regs * regs) { - int status; - - status = hp_sdc_status_in8(); - printk(KERN_WARNING PREFIX "NMI !\n"); - -#if 0 - if (status & HP_SDC_NMISTATUS_FHS) { - read_lock(&hp_sdc.hook_lock); - if (hp_sdc.timer != NULL) - hp_sdc.timer(irq, dev_id, status, 0); - read_unlock(&hp_sdc.hook_lock); - } - else { - /* TODO: pass this on to the HIL handler, or do SAK here? */ - printk(KERN_WARNING PREFIX "HIL NMI\n"); - } -#endif - return IRQ_HANDLED; -} - - -/***************** Kernel (tasklet) context functions ****************/ - -unsigned long hp_sdc_put(void); - -static void hp_sdc_tasklet(unsigned long foo) { - - write_lock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.rcurr >= 0) { - struct timeval tv; - do_gettimeofday(&tv); - if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000; - if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) { - hp_sdc_transaction *curr; - uint8_t tmp; - - curr = hp_sdc.tq[hp_sdc.rcurr]; - /* If this turns out to be a normal failure mode - * we'll need to figure out a way to communicate - * it back to the application. and be less verbose. - */ - printk(KERN_WARNING PREFIX "read timeout (%ius)!\n", - tv.tv_usec - hp_sdc.rtv.tv_usec); - curr->idx += hp_sdc.rqty; - hp_sdc.rqty = 0; - tmp = curr->seq[curr->actidx]; - curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD; - if(tmp & HP_SDC_ACT_SEMAPHORE) { - if (curr->act.semaphore) - up(curr->act.semaphore); - } - if(tmp & HP_SDC_ACT_CALLBACK) { - /* Note this means that irqhooks may be called - * in tasklet/bh context. - */ - if (curr->act.irqhook) - curr->act.irqhook(0, 0, 0, 0); - } - curr->actidx = curr->idx; - curr->idx++; - hp_sdc.rcurr = -1; - } - } - write_unlock_irq(&hp_sdc.rtq_lock); - hp_sdc_put(); -} - -unsigned long hp_sdc_put(void) { - hp_sdc_transaction *curr; - uint8_t act; - int idx, curridx; - - int limit = 0; - - write_lock(&hp_sdc.lock); - - /* If i8042 buffers are full, we cannot do anything that - requires output, so we skip to the administrativa. */ - if (hp_sdc.ibf) { - hp_sdc_status_in8(); - if (hp_sdc.ibf) goto finish; - } - - anew: - /* See if we are in the middle of a sequence. */ - if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0; - read_lock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++; - read_unlock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; - curridx = hp_sdc.wcurr; - - if (hp_sdc.tq[curridx] != NULL) goto start; - - while (++curridx != hp_sdc.wcurr) { - if (curridx >= HP_SDC_QUEUE_LEN) { - curridx = -1; /* Wrap to top */ - continue; - } - read_lock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.rcurr == curridx) { - read_unlock_irq(&hp_sdc.rtq_lock); - continue; - } - read_unlock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */ - } - if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */ - curridx = -1; - } - hp_sdc.wcurr = curridx; - - start: - - /* Check to see if the interrupt mask needs to be set. */ - if (hp_sdc.set_im) { - hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM); - hp_sdc.set_im = 0; - goto finish; - } - - if (hp_sdc.wcurr == -1) goto done; - - curr = hp_sdc.tq[curridx]; - idx = curr->actidx; - - if (curr->actidx >= curr->endidx) { - hp_sdc.tq[curridx] = NULL; - /* Interleave outbound data between the transactions. */ - hp_sdc.wcurr++; - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; - goto finish; - } - - act = curr->seq[idx]; - idx++; - - if (curr->idx >= curr->endidx) { - if (act & HP_SDC_ACT_DEALLOC) kfree(curr); - hp_sdc.tq[curridx] = NULL; - /* Interleave outbound data between the transactions. */ - hp_sdc.wcurr++; - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; - goto finish; - } - - while (act & HP_SDC_ACT_PRECMD) { - if (curr->idx != idx) { - idx++; - act &= ~HP_SDC_ACT_PRECMD; - break; - } - hp_sdc_status_out8(curr->seq[idx]); - curr->idx++; - /* act finished? */ - if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD) - goto actdone; - /* skip quantity field if data-out sequence follows. */ - if (act & HP_SDC_ACT_DATAOUT) curr->idx++; - goto finish; - } - if (act & HP_SDC_ACT_DATAOUT) { - int qty; - - qty = curr->seq[idx]; - idx++; - if (curr->idx - idx < qty) { - hp_sdc_data_out8(curr->seq[curr->idx]); - curr->idx++; - /* act finished? */ - if ((curr->idx - idx >= qty) && - ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)) - goto actdone; - goto finish; - } - idx += qty; - act &= ~HP_SDC_ACT_DATAOUT; - } - else while (act & HP_SDC_ACT_DATAREG) { - int mask; - uint8_t w7[4]; - - mask = curr->seq[idx]; - if (idx != curr->idx) { - idx++; - idx += !!(mask & 1); - idx += !!(mask & 2); - idx += !!(mask & 4); - idx += !!(mask & 8); - act &= ~HP_SDC_ACT_DATAREG; - break; - } - - w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0]; - w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1]; - w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2]; - w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3]; - - if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 || - w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) { - int i = 0; - - /* Need to point the write index register */ - while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; - if (i < 4) { - hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i); - hp_sdc.wi = 0x70 + i; - goto finish; - } - idx++; - if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG) - goto actdone; - curr->idx = idx; - act &= ~HP_SDC_ACT_DATAREG; - break; - } - - hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]); - hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70]; - hp_sdc.wi++; /* write index register autoincrements */ - { - int i = 0; - - while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; - if (i >= 4) { - curr->idx = idx + 1; - if ((act & HP_SDC_ACT_DURING) == - HP_SDC_ACT_DATAREG) - goto actdone; - } - } - goto finish; - } - /* We don't go any further in the command if there is a pending read, - because we don't want interleaved results. */ - read_lock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.rcurr >= 0) { - read_unlock_irq(&hp_sdc.rtq_lock); - goto finish; - } - read_unlock_irq(&hp_sdc.rtq_lock); - - - if (act & HP_SDC_ACT_POSTCMD) { - uint8_t postcmd; - - /* curr->idx should == idx at this point. */ - postcmd = curr->seq[idx]; - curr->idx++; - if (act & HP_SDC_ACT_DATAIN) { - - /* Start a new read */ - hp_sdc.rqty = curr->seq[curr->idx]; - do_gettimeofday(&hp_sdc.rtv); - curr->idx++; - /* Still need to lock here in case of spurious irq. */ - write_lock_irq(&hp_sdc.rtq_lock); - hp_sdc.rcurr = curridx; - write_unlock_irq(&hp_sdc.rtq_lock); - hp_sdc_status_out8(postcmd); - goto finish; - } - hp_sdc_status_out8(postcmd); - goto actdone; - } - -actdone: - if (act & HP_SDC_ACT_SEMAPHORE) { - up(curr->act.semaphore); - } - else if (act & HP_SDC_ACT_CALLBACK) { - curr->act.irqhook(0,0,0,0); - } - if (curr->idx >= curr->endidx) { /* This transaction is over. */ - if (act & HP_SDC_ACT_DEALLOC) kfree(curr); - hp_sdc.tq[curridx] = NULL; - } - else { - curr->actidx = idx + 1; - curr->idx = idx + 2; - } - /* Interleave outbound data between the transactions. */ - hp_sdc.wcurr++; - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; - - finish: - /* If by some quirk IBF has cleared and our ISR has run to - see that that has happened, do it all again. */ - if (!hp_sdc.ibf && limit++ < 20) goto anew; - - done: - if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task); - write_unlock(&hp_sdc.lock); - return 0; -} - -/******* Functions called in either user or kernel context ****/ -int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) { - unsigned long flags; - int i; - - if (this == NULL) { - tasklet_schedule(&hp_sdc.task); - return -EINVAL; - }; - - write_lock_irqsave(&hp_sdc.lock, flags); - - /* Can't have same transaction on queue twice */ - for (i=0; i < HP_SDC_QUEUE_LEN; i++) - if (hp_sdc.tq[i] == this) goto fail; - - this->actidx = 0; - this->idx = 1; - - /* Search for empty slot */ - for (i=0; i < HP_SDC_QUEUE_LEN; i++) { - if (hp_sdc.tq[i] == NULL) { - hp_sdc.tq[i] = this; - write_unlock_irqrestore(&hp_sdc.lock, flags); - tasklet_schedule(&hp_sdc.task); - return 0; - } - } - write_unlock_irqrestore(&hp_sdc.lock, flags); - printk(KERN_WARNING PREFIX "No free slot to add transaction.\n"); - return -EBUSY; - - fail: - write_unlock_irqrestore(&hp_sdc.lock,flags); - printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n"); - return -EINVAL; -} - -int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) { - unsigned long flags; - int i; - - write_lock_irqsave(&hp_sdc.lock, flags); - - /* TODO: don't remove it if it's not done. */ - - for (i=0; i < HP_SDC_QUEUE_LEN; i++) - if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL; - - write_unlock_irqrestore(&hp_sdc.lock, flags); - return 0; -} - - - -/********************** User context functions **************************/ -int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) { - - if (callback == NULL || hp_sdc.dev == NULL) { - return -EINVAL; - } - write_lock_irq(&hp_sdc.hook_lock); - if (hp_sdc.timer != NULL) { - write_unlock_irq(&hp_sdc.hook_lock); - return -EBUSY; - } - - hp_sdc.timer = callback; - /* Enable interrupts from the timers */ - hp_sdc.im &= ~HP_SDC_IM_FH; - hp_sdc.im &= ~HP_SDC_IM_PT; - hp_sdc.im &= ~HP_SDC_IM_TIMERS; - hp_sdc.set_im = 1; - write_unlock_irq(&hp_sdc.hook_lock); - - tasklet_schedule(&hp_sdc.task); - - return 0; -} - -int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) { - - if (callback == NULL || hp_sdc.dev == NULL) { - return -EINVAL; - } - write_lock_irq(&hp_sdc.hook_lock); - if (hp_sdc.hil != NULL) { - write_unlock_irq(&hp_sdc.hook_lock); - return -EBUSY; - } - - hp_sdc.hil = callback; - hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET); - hp_sdc.set_im = 1; - write_unlock_irq(&hp_sdc.hook_lock); - - tasklet_schedule(&hp_sdc.task); - - return 0; -} - -int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) { - - if (callback == NULL || hp_sdc.dev == NULL) { - return -EINVAL; - } - write_lock_irq(&hp_sdc.hook_lock); - if (hp_sdc.cooked != NULL) { - write_unlock_irq(&hp_sdc.hook_lock); - return -EBUSY; - } - - /* Enable interrupts from the HIL MLC */ - hp_sdc.cooked = callback; - hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET); - hp_sdc.set_im = 1; - write_unlock_irq(&hp_sdc.hook_lock); - - tasklet_schedule(&hp_sdc.task); - - return 0; -} - -int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) { - - - write_lock_irq(&hp_sdc.hook_lock); - if ((callback != hp_sdc.timer) || - (hp_sdc.timer == NULL)) { - write_unlock_irq(&hp_sdc.hook_lock); - return -EINVAL; - } - - /* Disable interrupts from the timers */ - hp_sdc.timer = NULL; - hp_sdc.im |= HP_SDC_IM_TIMERS; - hp_sdc.im |= HP_SDC_IM_FH; - hp_sdc.im |= HP_SDC_IM_PT; - hp_sdc.set_im = 1; - write_unlock_irq(&hp_sdc.hook_lock); - tasklet_schedule(&hp_sdc.task); - - return 0; -} - -int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) { - - write_lock_irq(&hp_sdc.hook_lock); - if ((callback != hp_sdc.hil) || - (hp_sdc.hil == NULL)) { - write_unlock_irq(&hp_sdc.hook_lock); - return -EINVAL; - } - - hp_sdc.hil = NULL; - /* Disable interrupts from HIL only if there is no cooked driver. */ - if(hp_sdc.cooked == NULL) { - hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET); - hp_sdc.set_im = 1; - } - write_unlock_irq(&hp_sdc.hook_lock); - tasklet_schedule(&hp_sdc.task); - - return 0; -} - -int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) { - - write_lock_irq(&hp_sdc.hook_lock); - if ((callback != hp_sdc.cooked) || - (hp_sdc.cooked == NULL)) { - write_unlock_irq(&hp_sdc.hook_lock); - return -EINVAL; - } - - hp_sdc.cooked = NULL; - /* Disable interrupts from HIL only if there is no raw HIL driver. */ - if(hp_sdc.hil == NULL) { - hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET); - hp_sdc.set_im = 1; - } - write_unlock_irq(&hp_sdc.hook_lock); - tasklet_schedule(&hp_sdc.task); - - return 0; -} - -/************************* Keepalive timer task *********************/ - -void hp_sdc_kicker (unsigned long data) { - tasklet_schedule(&hp_sdc.task); - /* Re-insert the periodic task. */ - mod_timer(&hp_sdc.kicker, jiffies + HZ); -} - -/************************** Module Initialization ***************************/ - -#if defined(__hppa__) - -static struct parisc_device_id hp_sdc_tbl[] = { - { - .hw_type = HPHW_FIO, - .hversion_rev = HVERSION_REV_ANY_ID, - .hversion = HVERSION_ANY_ID, - .sversion = 0x73, - }, - { 0, } -}; - -MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); - -static int __init hp_sdc_init_hppa(struct parisc_device *d); - -static struct parisc_driver hp_sdc_driver = { - .name = "HP SDC", - .id_table = hp_sdc_tbl, - .probe = hp_sdc_init_hppa, -}; - -#endif /* __hppa__ */ - -static int __init hp_sdc_init(void) -{ - int i; - char *errstr; - hp_sdc_transaction t_sync; - uint8_t ts_sync[6]; - struct semaphore s_sync; - - hp_sdc.lock = RW_LOCK_UNLOCKED; - hp_sdc.ibf_lock = RW_LOCK_UNLOCKED; - hp_sdc.rtq_lock = RW_LOCK_UNLOCKED; - hp_sdc.hook_lock = RW_LOCK_UNLOCKED; - - hp_sdc.timer = NULL; - hp_sdc.hil = NULL; - hp_sdc.pup = NULL; - hp_sdc.cooked = NULL; - hp_sdc.im = HP_SDC_IM_MASK; /* Mask maskable irqs */ - hp_sdc.set_im = 1; - hp_sdc.wi = 0xff; - hp_sdc.r7[0] = 0xff; - hp_sdc.r7[1] = 0xff; - hp_sdc.r7[2] = 0xff; - hp_sdc.r7[3] = 0xff; - hp_sdc.ibf = 1; - - for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL; - hp_sdc.wcurr = -1; - hp_sdc.rcurr = -1; - hp_sdc.rqty = 0; - - hp_sdc.dev_err = -ENODEV; - - errstr = "IO not found for"; - if (!hp_sdc.base_io) goto err0; - - errstr = "IRQ not found for"; - if (!hp_sdc.irq) goto err0; - - hp_sdc.dev_err = -EBUSY; - -#if defined(__hppa__) - errstr = "IO not available for"; - if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0; -#endif - - errstr = "IRQ not available for"; - if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC", - (void *) hp_sdc.base_io)) goto err1; - - errstr = "NMI not available for"; - if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", - (void *) hp_sdc.base_io)) goto err2; - - printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", - (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); - - hp_sdc_status_in8(); - hp_sdc_data_in8(); - - tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0); - - /* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */ - t_sync.actidx = 0; - t_sync.idx = 1; - t_sync.endidx = 6; - t_sync.seq = ts_sync; - ts_sync[0] = HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE; - ts_sync[1] = 0x0f; - ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0; - t_sync.act.semaphore = &s_sync; - init_MUTEX_LOCKED(&s_sync); - hp_sdc_enqueue_transaction(&t_sync); - down(&s_sync); /* Wait for t_sync to complete */ - - /* Create the keepalive task */ - init_timer(&hp_sdc.kicker); - hp_sdc.kicker.expires = jiffies + HZ; - hp_sdc.kicker.function = &hp_sdc_kicker; - add_timer(&hp_sdc.kicker); - - hp_sdc.dev_err = 0; - return 0; - err2: - free_irq(hp_sdc.irq, NULL); - err1: - release_region(hp_sdc.data_io, 2); - err0: - printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", - errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); - hp_sdc.dev = NULL; - return hp_sdc.dev_err; -} - -#if defined(__hppa__) - -static int __init hp_sdc_init_hppa(struct parisc_device *d) -{ - if (!d) return 1; - if (hp_sdc.dev != NULL) return 1; /* We only expect one SDC */ - - hp_sdc.dev = d; - hp_sdc.irq = d->irq; - /* TODO: Is NMI == IRQ - 1 all cases, or is there a way to query? */ - hp_sdc.nmi = d->irq - 1; - hp_sdc.base_io = (unsigned long) d->hpa; - hp_sdc.data_io = (unsigned long) d->hpa + 0x800; - hp_sdc.status_io = (unsigned long) d->hpa + 0x801; - - return hp_sdc_init(); -} - -#endif /* __hppa__ */ - -#if !defined(__mc68000__) /* Link error on m68k! */ -static void __exit hp_sdc_exit(void) -#else -static void hp_sdc_exit(void) -#endif -{ - write_lock_irq(&hp_sdc.lock); - - /* Turn off all maskable "sub-function" irq's. */ - hp_sdc_spin_ibf(); - sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io); - - /* Wait until we know this has been processed by the i8042 */ - hp_sdc_spin_ibf(); - - free_irq(hp_sdc.nmi, NULL); - free_irq(hp_sdc.irq, NULL); - write_unlock_irq(&hp_sdc.lock); - - del_timer(&hp_sdc.kicker); - - tasklet_kill(&hp_sdc.task); - -/* release_region(hp_sdc.data_io, 2); */ - -#if defined(__hppa__) - if (unregister_parisc_driver(&hp_sdc_driver)) - printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); -#endif -} - -static int __init hp_sdc_register(void) -{ - hp_sdc_transaction tq_init; - uint8_t tq_init_seq[5]; - struct semaphore tq_init_sem; -#if defined(__mc68000__) - mm_segment_t fs; - unsigned char i; -#endif - - hp_sdc.dev = NULL; - hp_sdc.dev_err = 0; -#if defined(__hppa__) - if (register_parisc_driver(&hp_sdc_driver)) { - printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n"); - return -ENODEV; - } -#elif defined(__mc68000__) - if (!MACH_IS_HP300) - return -ENODEV; - - hp_sdc.irq = 1; - hp_sdc.nmi = 7; - hp_sdc.base_io = (unsigned long) 0xf0428000; - hp_sdc.data_io = (unsigned long) hp_sdc.base_io + 1; - hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3; - fs = get_fs(); - set_fs(KERNEL_DS); - if (!get_user(i, (unsigned char *)hp_sdc.data_io)) - hp_sdc.dev = (void *)1; - set_fs(fs); - hp_sdc.dev_err = hp_sdc_init(); -#endif - if (hp_sdc.dev == NULL) { - printk(KERN_WARNING PREFIX "No SDC found.\n"); - return hp_sdc.dev_err; - } - - init_MUTEX_LOCKED(&tq_init_sem); - - tq_init.actidx = 0; - tq_init.idx = 1; - tq_init.endidx = 5; - tq_init.seq = tq_init_seq; - tq_init.act.semaphore = &tq_init_sem; - - tq_init_seq[0] = - HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; - tq_init_seq[1] = HP_SDC_CMD_READ_KCC; - tq_init_seq[2] = 1; - tq_init_seq[3] = 0; - tq_init_seq[4] = 0; - - hp_sdc_enqueue_transaction(&tq_init); - - down(&tq_init_sem); - up(&tq_init_sem); - - if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { - printk(KERN_WARNING PREFIX "Error reading config byte.\n"); - hp_sdc_exit(); - return -ENODEV; - } - hp_sdc.r11 = tq_init_seq[4]; - if (hp_sdc.r11 & HP_SDC_CFG_NEW) { - char *str; - printk(KERN_INFO PREFIX "New style SDC\n"); - tq_init_seq[1] = HP_SDC_CMD_READ_XTD; - tq_init.actidx = 0; - tq_init.idx = 1; - down(&tq_init_sem); - hp_sdc_enqueue_transaction(&tq_init); - down(&tq_init_sem); - up(&tq_init_sem); - if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { - printk(KERN_WARNING PREFIX "Error reading extended config byte.\n"); - return -ENODEV; - } - hp_sdc.r7e = tq_init_seq[4]; - HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str) - printk(KERN_INFO PREFIX "Revision: %s\n", str); - if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) { - printk(KERN_INFO PREFIX "TI SN76494 beeper present\n"); - } - if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) { - printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n"); - } - printk(KERN_INFO PREFIX "Spunking the self test register to force PUP " - "on next firmware reset.\n"); - tq_init_seq[0] = HP_SDC_ACT_PRECMD | - HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; - tq_init_seq[1] = HP_SDC_CMD_SET_STR; - tq_init_seq[2] = 1; - tq_init_seq[3] = 0; - tq_init.actidx = 0; - tq_init.idx = 1; - tq_init.endidx = 4; - down(&tq_init_sem); - hp_sdc_enqueue_transaction(&tq_init); - down(&tq_init_sem); - up(&tq_init_sem); - } - else { - printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", - (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087"); - } - - return 0; -} - -module_init(hp_sdc_register); -module_exit(hp_sdc_exit); - -/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64) - * cycles cycles-adj time - * between two consecutive mfctl(16)'s: 4 n/a 63ns - * hp_sdc_spin_ibf when idle: 119 115 1.7us - * gsc_writeb status register: 83 79 1.2us - * IBF to clear after sending SET_IM: 6204 6006 93us - * IBF to clear after sending LOAD_RT: 4467 4352 68us - * IBF to clear after sending two LOAD_RTs: 18974 18859 295us - * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us - * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms - * between IRQ received and ~IBF for above: 2578877 n/a 40ms - * - * Performance stats after a run of this module configuring HIL and - * receiving a few mouse events: - * - * status in8 282508 cycles 7128 calls - * status out8 8404 cycles 341 calls - * data out8 1734 cycles 78 calls - * isr 174324 cycles 617 calls (includes take) - * take 1241 cycles 2 calls - * put 1411504 cycles 6937 calls - * task 1655209 cycles 6937 calls (includes put) - * - */ reverted: --- b/drivers/input/serio/hp_sdc_mlc.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,358 +0,0 @@ -/* - * Access to HP-HIL MLC through HP System Device Controller. - * - * Copyright (c) 2001 Brian S. Julin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * - * References: - * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A - * System Device Controller Microprocessor Firmware Theory of Operation - * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#define PREFIX "HP SDC MLC: " - -static hil_mlc hp_sdc_mlc; - -MODULE_AUTHOR("Brian S. Julin "); -MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines"); -MODULE_LICENSE("Dual BSD/GPL"); - -struct hp_sdc_mlc_priv_s { - int emtestmode; - hp_sdc_transaction trans; - u8 tseq[16]; - int got5x; -} hp_sdc_mlc_priv; - -/************************* Interrupt context ******************************/ -static void hp_sdc_mlc_isr (int irq, void *dev_id, - uint8_t status, uint8_t data) { - int idx; - hil_mlc *mlc = &hp_sdc_mlc; - - write_lock(&(mlc->lock)); - if (mlc->icount < 0) { - printk(KERN_WARNING PREFIX "HIL Overflow!\n"); - up(&mlc->isem); - goto out; - } - idx = 15 - mlc->icount; - if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) { - mlc->ipacket[idx] |= data | HIL_ERR_INT; - mlc->icount--; - if (hp_sdc_mlc_priv.got5x) goto check; - if (!idx) goto check; - if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) != - (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) { - mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK; - mlc->ipacket[idx] |= (mlc->ipacket[idx-1] - & HIL_PKT_ADDR_MASK); - } - goto check; - } - /* We know status is 5X */ - if (data & HP_SDC_HIL_ISERR) goto err; - mlc->ipacket[idx] = - (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT; - hp_sdc_mlc_priv.got5x = 1; - goto out; - - check: - hp_sdc_mlc_priv.got5x = 0; - if (mlc->imatch == 0) goto done; - if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) - && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done; - if (mlc->ipacket[idx] == mlc->imatch) goto done; - goto out; - - err: - printk(KERN_DEBUG PREFIX "err code %x\n", data); - switch (data) { - case HP_SDC_HIL_RC_DONE: - printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n"); - break; - case HP_SDC_HIL_ERR: - mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | - HIL_ERR_FERR | HIL_ERR_FOF; - break; - case HP_SDC_HIL_TO: - mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR; - break; - case HP_SDC_HIL_RC: - printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n"); - break; - default: - printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data); - break; - } - /* No more data will be coming due to an error. */ - done: - tasklet_schedule(mlc->tasklet); - up(&(mlc->isem)); - out: - write_unlock(&(mlc->lock)); -} - - -/******************** Tasklet or userspace context functions ****************/ - -static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) { - unsigned long flags; - struct hp_sdc_mlc_priv_s *priv; - int rc = 2; - - priv = mlc->priv; - - write_lock_irqsave(&(mlc->lock), flags); - - /* Try to down the semaphore */ - if (down_trylock(&(mlc->isem))) { - struct timeval tv; - if (priv->emtestmode) { - mlc->ipacket[0] = - HIL_ERR_INT | (mlc->opacket & - (HIL_PKT_CMD | - HIL_PKT_ADDR_MASK | - HIL_PKT_DATA_MASK)); - mlc->icount = 14; - /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */ - goto wasup; - } - do_gettimeofday(&tv); - tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec); - if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) { - /* printk("!%i %i", - tv.tv_usec - mlc->instart.tv_usec, - mlc->intimeout); - */ - rc = 1; - up(&(mlc->isem)); - } - goto done; - } - wasup: - up(&(mlc->isem)); - rc = 0; - goto done; - done: - write_unlock_irqrestore(&(mlc->lock), flags); - return rc; -} - -static int hp_sdc_mlc_cts (hil_mlc *mlc) { - struct hp_sdc_mlc_priv_s *priv; - unsigned long flags; - - priv = mlc->priv; - - write_lock_irqsave(&(mlc->lock), flags); - - /* Try to down the semaphores -- they should be up. */ - if (down_trylock(&(mlc->isem))) { - BUG(); - goto busy; - } - if (down_trylock(&(mlc->osem))) { - BUG(); - up(&(mlc->isem)); - goto busy; - } - up(&(mlc->isem)); - up(&(mlc->osem)); - - if (down_trylock(&(mlc->csem))) { - if (priv->trans.act.semaphore != &(mlc->csem)) goto poll; - goto busy; - } - if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done; - - poll: - priv->trans.act.semaphore = &(mlc->csem); - priv->trans.actidx = 0; - priv->trans.idx = 1; - priv->trans.endidx = 5; - priv->tseq[0] = - HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; - priv->tseq[1] = HP_SDC_CMD_READ_USE; - priv->tseq[2] = 1; - priv->tseq[3] = 0; - priv->tseq[4] = 0; - hp_sdc_enqueue_transaction(&(priv->trans)); - busy: - write_unlock_irqrestore(&(mlc->lock), flags); - return 1; - done: - priv->trans.act.semaphore = &(mlc->osem); - up(&(mlc->csem)); - write_unlock_irqrestore(&(mlc->lock), flags); - return 0; -} - -static void hp_sdc_mlc_out (hil_mlc *mlc) { - struct hp_sdc_mlc_priv_s *priv; - unsigned long flags; - - priv = mlc->priv; - - write_lock_irqsave(&(mlc->lock), flags); - - /* Try to down the semaphore -- it should be up. */ - if (down_trylock(&(mlc->osem))) { - BUG(); - goto done; - } - - if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control; - - do_data: - if (priv->emtestmode) { - up(&(mlc->osem)); - goto done; - } - /* Shouldn't be sending commands when loop may be busy */ - if (down_trylock(&(mlc->csem))) { - BUG(); - goto done; - } - up(&(mlc->csem)); - - priv->trans.actidx = 0; - priv->trans.idx = 1; - priv->trans.act.semaphore = &(mlc->osem); - priv->trans.endidx = 6; - priv->tseq[0] = - HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE; - priv->tseq[1] = 0x7; - priv->tseq[2] = - (mlc->opacket & - (HIL_PKT_ADDR_MASK | HIL_PKT_CMD)) - >> HIL_PKT_ADDR_SHIFT; - priv->tseq[3] = - (mlc->opacket & HIL_PKT_DATA_MASK) - >> HIL_PKT_DATA_SHIFT; - priv->tseq[4] = 0; /* No timeout */ - if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1; - priv->tseq[5] = HP_SDC_CMD_DO_HIL; - goto enqueue; - - do_control: - priv->emtestmode = mlc->opacket & HIL_CTRL_TEST; - if ((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE) { - BUG(); /* we cannot emulate this, it should not be used. */ - } - if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only; - if (mlc->opacket & HIL_CTRL_APE) { - BUG(); /* Should not send command/data after engaging APE */ - goto done; - } - /* Disengaging APE this way would not be valid either since - * the loop must be allowed to idle. - * - * So, it works out that we really never actually send control - * and data when using SDC, we just send the data. - */ - goto do_data; - - control_only: - priv->trans.actidx = 0; - priv->trans.idx = 1; - priv->trans.act.semaphore = &(mlc->osem); - priv->trans.endidx = 4; - priv->tseq[0] = - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; - priv->tseq[1] = HP_SDC_CMD_SET_LPC; - priv->tseq[2] = 1; - // priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; - priv->tseq[3] = 0; - if (mlc->opacket & HIL_CTRL_APE) { - priv->tseq[3] |= HP_SDC_LPC_APE_IPF; - down_trylock(&(mlc->csem)); - } - enqueue: - hp_sdc_enqueue_transaction(&(priv->trans)); - done: - write_unlock_irqrestore(&(mlc->lock), flags); -} - -static int __init hp_sdc_mlc_init(void) -{ - hil_mlc *mlc = &hp_sdc_mlc; - - printk(KERN_INFO PREFIX "Registering the System Domain Controller's HIL MLC.\n"); - - hp_sdc_mlc_priv.emtestmode = 0; - hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq; - hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem); - hp_sdc_mlc_priv.got5x = 0; - - mlc->cts = &hp_sdc_mlc_cts; - mlc->in = &hp_sdc_mlc_in; - mlc->out = &hp_sdc_mlc_out; - - if (hil_mlc_register(mlc)) { - printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); - goto err0; - } - mlc->priv = &hp_sdc_mlc_priv; - - if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { - printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); - goto err1; - } - return 0; - err1: - if (hil_mlc_unregister(mlc)) { - printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" - "This is bad. Could cause an oops.\n"); - } - err0: - return -EBUSY; -} - -static void __exit hp_sdc_mlc_exit(void) -{ - hil_mlc *mlc = &hp_sdc_mlc; - if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) { - printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n" - "This is bad. Could cause an oops.\n"); - } - if (hil_mlc_unregister(mlc)) { - printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" - "This is bad. Could cause an oops.\n"); - } -} - -module_init(hp_sdc_mlc_init); -module_exit(hp_sdc_mlc_exit); reverted: --- b/drivers/input/serio/i8042-x86ia64io.h 2005-02-09 19:00:45 -08:00 +++ a/drivers/input/serio/i8042-x86ia64io.h 2005-02-09 19:00:45 -08:00 @@ -88,113 +88,183 @@ }; #endif +#ifdef CONFIG_ACPI +#include +#include + +struct i8042_acpi_resources { + unsigned int port1; + unsigned int port2; + unsigned int irq; +}; -#ifdef CONFIG_PNP -#include +static int i8042_acpi_kbd_registered; +static int i8042_acpi_aux_registered; -static int i8042_pnp_kbd_registered; -static int i8042_pnp_aux_registered; +static acpi_status i8042_acpi_parse_resource(struct acpi_resource *res, void *data) +{ + struct i8042_acpi_resources *i8042_res = data; + struct acpi_resource_io *io; + struct acpi_resource_fixed_io *fixed_io; + struct acpi_resource_irq *irq; + struct acpi_resource_ext_irq *ext_irq; + + switch (res->id) { + case ACPI_RSTYPE_IO: + io = &res->data.io; + if (io->range_length) { + if (!i8042_res->port1) + i8042_res->port1 = io->min_base_address; + else + i8042_res->port2 = io->min_base_address; + } + break; + + case ACPI_RSTYPE_FIXED_IO: + fixed_io = &res->data.fixed_io; + if (fixed_io->range_length) { + if (!i8042_res->port1) + i8042_res->port1 = fixed_io->base_address; + else + i8042_res->port2 = fixed_io->base_address; + } + break; + + case ACPI_RSTYPE_IRQ: + irq = &res->data.irq; + if (irq->number_of_interrupts > 0) + i8042_res->irq = + acpi_register_gsi(irq->interrupts[0], + irq->edge_level, + irq->active_high_low); + break; + + case ACPI_RSTYPE_EXT_IRQ: + ext_irq = &res->data.extended_irq; + if (ext_irq->number_of_interrupts > 0) + i8042_res->irq = + acpi_register_gsi(ext_irq->interrupts[0], + ext_irq->edge_level, + ext_irq->active_high_low); + break; + } + return AE_OK; +} +static int i8042_acpi_kbd_add(struct acpi_device *device) -static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did) { + struct i8042_acpi_resources kbd_res; + acpi_status status; + + memset(&kbd_res, 0, sizeof(kbd_res)); + status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + i8042_acpi_parse_resource, &kbd_res); + if (ACPI_FAILURE(status)) + return -ENODEV; + + if (kbd_res.port1) + i8042_data_reg = kbd_res.port1; - if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1) - i8042_data_reg = pnp_port_start(dev,0); else + printk(KERN_WARNING "ACPI: [%s] has no data port; default is 0x%x\n", + acpi_device_bid(device), i8042_data_reg); - printk(KERN_WARNING "PNP: [%s] has no data port; default is 0x%x\n", - pnp_dev_name(dev), i8042_data_reg); + if (kbd_res.port2) + i8042_command_reg = kbd_res.port2; - if (pnp_port_valid(dev, 1) && pnp_port_len(dev, 1) == 1) - i8042_command_reg = pnp_port_start(dev,1); else + printk(KERN_WARNING "ACPI: [%s] has no command port; default is 0x%x\n", + acpi_device_bid(device), i8042_command_reg); - printk(KERN_WARNING "PNP: [%s] has no command port; default is 0x%x\n", - pnp_dev_name(dev), i8042_command_reg); + if (kbd_res.irq) + i8042_kbd_irq = kbd_res.irq; - if (pnp_irq_valid(dev,0)) - i8042_kbd_irq = pnp_irq(dev,0); else + printk(KERN_WARNING "ACPI: [%s] has no IRQ; default is %d\n", + acpi_device_bid(device), i8042_kbd_irq); - printk(KERN_WARNING "PNP: [%s] has no IRQ; default is %d\n", - pnp_dev_name(dev), i8042_kbd_irq); + strncpy(acpi_device_name(device), "PS/2 Keyboard Controller", + sizeof(acpi_device_name(device))); + printk("ACPI: %s [%s] at I/O 0x%x, 0x%x, irq %d\n", + acpi_device_name(device), acpi_device_bid(device), - printk(KERN_INFO "PNP: %s [%s,%s] at 0x%x,0x%x irq %d\n", - "PS/2 Keyboard Controller", did->id, pnp_dev_name(dev), i8042_data_reg, i8042_command_reg, i8042_kbd_irq); return 0; } +static int i8042_acpi_aux_add(struct acpi_device *device) -static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *did) { + struct i8042_acpi_resources aux_res; + acpi_status status; + + memset(&aux_res, 0, sizeof(aux_res)); + status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + i8042_acpi_parse_resource, &aux_res); + if (ACPI_FAILURE(status)) + return -ENODEV; + + if (aux_res.irq) + i8042_aux_irq = aux_res.irq; - if (pnp_irq_valid(dev,0)) - i8042_aux_irq = pnp_irq(dev,0); else + printk(KERN_WARNING "ACPI: [%s] has no IRQ; default is %d\n", + acpi_device_bid(device), i8042_aux_irq); - printk(KERN_WARNING "PNP: [%s] has no IRQ; default is %d\n", - pnp_dev_name(dev), i8042_aux_irq); + strncpy(acpi_device_name(device), "PS/2 Mouse Controller", + sizeof(acpi_device_name(device))); + printk("ACPI: %s [%s] at irq %d\n", + acpi_device_name(device), acpi_device_bid(device), i8042_aux_irq); - printk(KERN_INFO "PNP: %s [%s,%s] irq %d\n", - "PS/2 Mouse Controller", did->id, pnp_dev_name(dev), i8042_aux_irq); return 0; } +static struct acpi_driver i8042_acpi_kbd_driver = { + .name = "i8042", + .ids = "PNP0303,PNP030B", + .ops = { + .add = i8042_acpi_kbd_add, + }, -static struct pnp_device_id pnp_kbd_devids[] = { - { .id = "PNP0303", .driver_data = 0 }, - { .id = "PNP030b", .driver_data = 0 }, - { .id = "", }, -}; - -static struct pnp_driver i8042_pnp_kbd_driver = { - .name = "i8042 kbd", - .id_table = pnp_kbd_devids, - .probe = i8042_pnp_kbd_probe, -}; - -static struct pnp_device_id pnp_aux_devids[] = { - { .id = "PNP0f13", .driver_data = 0 }, - { .id = "SYN0801", .driver_data = 0 }, - { .id = "", }, }; +static struct acpi_driver i8042_acpi_aux_driver = { + .name = "i8042", + .ids = "PNP0F13,SYN0801", + .ops = { + .add = i8042_acpi_aux_add, + }, -static struct pnp_driver i8042_pnp_aux_driver = { - .name = "i8042 aux", - .id_table = pnp_aux_devids, - .probe = i8042_pnp_aux_probe, }; +static int i8042_acpi_init(void) -static int i8042_pnp_init(void) { int result; + if (acpi_disabled || i8042_noacpi) { + printk("i8042: ACPI detection disabled\n"); - if (i8042_nopnp) { - printk("i8042: PNP detection disabled\n"); return 0; } + result = acpi_bus_register_driver(&i8042_acpi_kbd_driver); - result = pnp_register_driver(&i8042_pnp_kbd_driver); if (result < 0) return result; if (result == 0) { + acpi_bus_unregister_driver(&i8042_acpi_kbd_driver); - pnp_unregister_driver(&i8042_pnp_kbd_driver); return -ENODEV; } + i8042_acpi_kbd_registered = 1; - i8042_pnp_kbd_registered = 1; + result = acpi_bus_register_driver(&i8042_acpi_aux_driver); - result = pnp_register_driver(&i8042_pnp_aux_driver); if (result >= 0) + i8042_acpi_aux_registered = 1; - i8042_pnp_aux_registered = 1; if (result == 0) i8042_noaux = 1; return 0; } +static void i8042_acpi_exit(void) -static void i8042_pnp_exit(void) { + if (i8042_acpi_kbd_registered) + acpi_bus_unregister_driver(&i8042_acpi_kbd_driver); - if (i8042_pnp_kbd_registered) - pnp_unregister_driver(&i8042_pnp_kbd_driver); + if (i8042_acpi_aux_registered) + acpi_bus_unregister_driver(&i8042_acpi_aux_driver); - if (i8042_pnp_aux_registered) - pnp_unregister_driver(&i8042_pnp_aux_driver); } #endif @@ -211,8 +281,8 @@ i8042_kbd_irq = I8042_MAP_IRQ(1); i8042_aux_irq = I8042_MAP_IRQ(12); +#ifdef CONFIG_ACPI + if (i8042_acpi_init()) -#ifdef CONFIG_PNP - if (i8042_pnp_init()) return -1; #endif @@ -230,8 +300,8 @@ static inline void i8042_platform_exit(void) { +#ifdef CONFIG_ACPI + i8042_acpi_exit(); -#ifdef CONFIG_PNP - i8042_pnp_exit(); #endif } diff -u b/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c --- b/drivers/input/serio/i8042.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/serio/i8042.c 2005-02-09 18:51:40 -08:00 @@ -59,10 +59,10 @@ module_param_named(panicblink, i8042_blink_frequency, uint, 0600); MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); -#ifdef CONFIG_PNP -static int i8042_nopnp; -module_param_named(nopnp, i8042_nopnp, bool, 0); -MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); +#ifdef CONFIG_ACPI +static int i8042_noacpi; +module_param_named(noacpi, i8042_noacpi, bool, 0); +MODULE_PARM_DESC(noacpi, "Do not use ACPI to detect controller settings"); #endif #define DEBUG @@ -900,7 +900,7 @@ * Here we try to restore the original BIOS settings */ -static int i8042_suspend(struct device *dev, pm_message_t state, u32 level) +static int i8042_suspend(struct device *dev, u32 state, u32 level) { if (level == SUSPEND_DISABLE) { del_timer_sync(&i8042_timer); @@ -932,12 +932,12 @@ printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't work.\n"); /* - * Activate all ports. + * Reconnect anything that was connected to the ports. */ for (i = 0; i < I8042_NUM_PORTS; i++) - i8042_activate_port(&i8042_ports[i]); - + if (i8042_activate_port(&i8042_ports[i]) == 0) + serio_reconnect(i8042_ports[i].serio); /* * Restart timer (for polling "stuck" data) */ diff -u b/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c --- b/drivers/input/serio/parkbd.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/serio/parkbd.c 2005-02-09 18:51:40 -08:00 @@ -1,47 +1,31 @@ /* - * Parallel port to Keyboard port adapter driver for Linux + * $Id: parkbd.c,v 1.10 2002/03/13 10:09:20 vojtech Exp $ * - * Copyright (c) 1999-2004 Vojtech Pavlik + * Copyright (c) 1999-2001 Vojtech Pavlik */ /* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. + * Parallel port to Keyboard port adapter driver for Linux */ /* - * To connect an AT or XT keyboard to the parallel port, a fairly simple adapter - * can be made: - * - * Parallel port Keyboard port + * 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 of the License, or + * (at your option) any later version. * - * +5V --------------------- +5V - * - * ______ - * +5V -------|______|--. - * | - * ACK -----------------| - * |--- KBD CLOCK - * STROBE -------|<|----' - * - * ______ - * +5V -------|______|--. - * | - * BUSY ----------------| - * |--- KBD DATA - * AUTOFD -------|<|----' + * 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. * - * GND --------------------- GND - * - * The diodes can be fairly any type, and the resistors should be somewhere - * around 5 kOhm, but the adapter will likely work without the resistors, - * too. + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * The +5V source can be taken either from USB, from mouse or keyboard ports, - * or from a joystick port. Unfortunately, the parallel port of a PC doesn't - * have a +5V pin, and feeding the keyboard from signal pins is out of question - * with 300 mA power reqirement of a typical AT keyboard. + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include diff -u b/drivers/input/serio/serio.c b/drivers/input/serio/serio.c --- b/drivers/input/serio/serio.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/serio/serio.c 2005-02-09 18:51:40 -08:00 @@ -475,7 +475,7 @@ init_MUTEX(&serio->drv_sem); device_initialize(&serio->dev); snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), - "serio%ld", (long)atomic_inc_return(&serio_no) - 1); + "serio%d", atomic_inc_return(&serio_no) - 1); serio->dev.bus = &serio_bus; serio->dev.release = serio_release_port; if (serio->parent) @@ -774,22 +774,6 @@ #endif /* CONFIG_HOTPLUG */ -static int serio_resume(struct device *dev) -{ - struct serio *serio = to_serio_port(dev); - - if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { - serio_disconnect_port(serio); - /* - * Driver re-probing can take a while, so better let kseriod - * deal with it. - */ - serio_rescan(serio); - } - - return 0; -} - /* called from serio_driver->connect/disconnect methods under serio_sem */ int serio_open(struct serio *serio, struct serio_driver *drv) { @@ -842,7 +826,6 @@ serio_bus.drv_attrs = serio_driver_attrs; serio_bus.match = serio_bus_match; serio_bus.hotplug = serio_hotplug; - serio_bus.resume = serio_resume; bus_register(&serio_bus); return 0; diff -u b/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig --- b/drivers/input/touchscreen/Kconfig 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/touchscreen/Kconfig 2005-02-09 18:51:40 -08:00 @@ -12,7 +12,7 @@ if INPUT_TOUCHSCREEN config TOUCHSCREEN_BITSY - tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" + tristate "Compaq iPAQ H3600 (Bitsy) touchscreen input driver" depends on SA1100_BITSY select SERIO help @@ -23,19 +23,6 @@ To compile this driver as a module, choose M here: the module will be called h3600_ts_input. -config TOUCHSCREEN_CORGI - tristate "Corgi touchscreen (for Sharp SL-C7xx)" - depends on PXA_SHARPSL - default y - help - Say Y here to enable the driver for the touchscreen on the - Sharp SL-C7xx series of PDAs. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called ads7846_ts. - config TOUCHSCREEN_GUNZE tristate "Gunze AHL-51S touchscreen" select SERIO @@ -50,26 +37,2 @@ -config TOUCHSCREEN_ELO - tristate "Elo serial touchscreens" - select SERIO - help - Say Y here if you have an Elo serial touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called gunze. - - -config TOUCHSCREEN_MK712 - tristate "ICS MicroClock MK712 touchscreen" - help - Say Y here if you have the ICS MicroClock MK712 touchscreen - controller chip in your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mk712. - endif reverted: --- b/drivers/input/touchscreen/Makefile 2005-02-09 19:00:45 -08:00 +++ a/drivers/input/touchscreen/Makefile 2005-02-09 19:00:45 -08:00 @@ -5,7 +5,4 @@ # Each configuration option enables a list of files. obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o -obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o -obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o -obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o reverted: --- b/drivers/input/touchscreen/corgi_ts.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,380 +0,0 @@ -/* - * Touchscreen driver for Sharp Corgi models (SL-C7xx) - * - * Copyright (c) 2004-2005 Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#define PWR_MODE_ACTIVE 0 -#define PWR_MODE_SUSPEND 1 - -#define X_AXIS_MAX 3830 -#define X_AXIS_MIN 150 -#define Y_AXIS_MAX 3830 -#define Y_AXIS_MIN 190 -#define PRESSURE_MIN 0 -#define PRESSURE_MAX 15000 - -struct ts_event { - short pressure; - short x; - short y; -}; - -struct corgi_ts { - char phys[32]; - struct input_dev input; - struct timer_list timer; - struct ts_event tc; - int pendown; - int power_mode; -}; - -#define STATUS_HSYNC (GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC)) - -#define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0); -#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) -#define CCNT_ON() {int pmnc = 1; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));} -#define CCNT_OFF() {int pmnc = 0; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));} - -#define WAIT_HS_400_VGA 7013U // 17.615us -#define WAIT_HS_400_QVGA 16622U // 41.750us - - -/* ADS7846 Touch Screen Controller bit definitions */ -#define ADSCTRL_PD0 (1u << 0) /* PD0 */ -#define ADSCTRL_PD1 (1u << 1) /* PD1 */ -#define ADSCTRL_DFR (1u << 2) /* SER/DFR */ -#define ADSCTRL_MOD (1u << 3) /* Mode */ -#define ADSCTRL_ADR_SH 4 /* Address setting */ -#define ADSCTRL_STS (1u << 7) /* Start Bit */ - -/* External Functions */ -extern int w100fb_get_xres(void); -extern int w100fb_get_blanking(void); -extern int w100fb_get_fastsysclk(void); -extern unsigned int get_clk_frequency_khz(int info); - -static unsigned long calc_waittime(void) -{ - int w100fb_xres = w100fb_get_xres(); - unsigned int waittime=0; - - if (w100fb_xres == 480 || w100fb_xres == 640) { - waittime = WAIT_HS_400_VGA*get_clk_frequency_khz(0)/398131U; - - if (w100fb_get_fastsysclk() == 100) - waittime=waittime*75/100; - - if (w100fb_xres == 640) - waittime=waittime*3; - - return waittime; - } - - return WAIT_HS_400_QVGA*get_clk_frequency_khz(0)/398131U; -} - -static int sync_receive_data_send_cmd(int doRecive,int doSend,unsigned int address, unsigned long wait_time) -{ - int pos = 0; - unsigned long timer1=0,timer2; - int dosleep; - - dosleep = !w100fb_get_blanking(); - - if (dosleep && doSend) { - CCNT_ON(); - /* polling HSync */ - SyncHS(); - /* get CCNT */ - CCNT(timer1); - } - - if (doRecive) - pos = corgi_ssp_ads7846_get(); - - if(doSend) { - int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS; - /* dummy command */ - corgi_ssp_ads7846_put(cmd); - corgi_ssp_ads7846_get(); - - if (dosleep) { - /* Wait after HSync */ - CCNT(timer2); - if ((timer2-timer1) > wait_time) { - /* timeout */ - SyncHS(); - /* get OSCR */ - CCNT(timer1); - /* Wait after HSync */ - CCNT(timer2); - } - while((timer2-timer1) < wait_time) - CCNT(timer2); - } - corgi_ssp_ads7846_put(cmd); - if (dosleep) - CCNT_OFF(); - } - return pos; -} - -static int read_xydata(struct corgi_ts *corgi_ts) -{ - unsigned int x,y,z1,z2; - unsigned long flags, wait_time; - - /* critical section */ - local_irq_save(flags); - corgi_ssp_ads7846_lock(); - wait_time=calc_waittime(); - - /* Y-axis */ - sync_receive_data_send_cmd(0, 1, 1u, wait_time); - - /* Y-axis */ - sync_receive_data_send_cmd(1, 1, 1u, wait_time); - - /* X-axis */ - y = sync_receive_data_send_cmd(1, 1, 5u, wait_time); - - /* Z1 */ - x = sync_receive_data_send_cmd(1, 1, 3u, wait_time); - - /* Z2 */ - z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time); - z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time); - - /* Power-Down Enable */ - corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - corgi_ssp_ads7846_get(); - - corgi_ssp_ads7846_unlock(); - local_irq_restore(flags); - - if ((x==0) || (y==0) || (z1 == 0) || ((x * (z2 -z1) / z1) >= 15000)) { - corgi_ts->tc.pressure = 0; - return 0; - } - - corgi_ts->tc.x = x; - corgi_ts->tc.y = y; - corgi_ts->tc.pressure = (x * (z2 - z1)) / z1; - return 1; -} - -static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs) -{ - if (corgi_ts->power_mode != PWR_MODE_ACTIVE) - return; - - if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) - return; - - if (regs) - input_regs(&corgi_ts->input, regs); - - input_report_abs(&corgi_ts->input, ABS_X, corgi_ts->tc.x); - input_report_abs(&corgi_ts->input, ABS_Y, corgi_ts->tc.y); - input_report_abs(&corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure); - input_report_key(&corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0)); - input_sync(&corgi_ts->input); -} - -static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs) -{ - if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) { - /* Disable Interrupt */ - set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE); - if (read_xydata(corgi_ts)) { - corgi_ts->pendown = 1; - new_data(corgi_ts,regs); - } - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - } else { - if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) { - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - corgi_ts->pendown ++; - return; - } - - if (corgi_ts->pendown) { - corgi_ts->tc.pressure = 0; - new_data(corgi_ts,regs); - } - - /* Enable Falling Edge */ - set_irq_type(CORGI_IRQ_GPIO_TP_INT,IRQT_FALLING); - corgi_ts->pendown = 0; - } -} - -static void corgi_ts_timer(unsigned long data) -{ - struct corgi_ts *corgits_data = (struct corgi_ts *) data; - ts_interrupt_main(corgits_data, 1, NULL); -} - -static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct corgi_ts *corgits_data = dev_id; - ts_interrupt_main(corgits_data, 0, regs); - return IRQ_HANDLED; -} - -#ifdef CONFIG_PM -static int corgits_suspend(struct device *dev, uint32_t state, uint32_t level) -{ - if (level == SUSPEND_POWER_DOWN) { - struct corgi_ts *corgi_ts = dev_get_drvdata(dev); - - if (corgi_ts->pendown) { - del_timer(&corgi_ts->timer); - corgi_ts->tc.pressure = 0; - new_data(corgi_ts,NULL); - corgi_ts->pendown = 0; - } - corgi_ts->power_mode = PWR_MODE_SUSPEND; - - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - } - return 0; -} - -static int corgits_resume(struct device *dev, uint32_t level) -{ - if (level == RESUME_POWER_ON) - { - struct corgi_ts *corgi_ts = dev_get_drvdata(dev); - - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - /* Enable Falling Edge */ - set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING); - corgi_ts->power_mode = PWR_MODE_ACTIVE; - } - return 0; -} -#else -#define corgits_suspend NULL -#define corgits_resume NULL -#endif - -static int __init corgits_probe(struct device *dev) -{ - struct corgi_ts *corgi_ts; - - if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL))) - return -ENOMEM; - - dev_set_drvdata(dev,corgi_ts); - - memset(corgi_ts, 0, sizeof(struct corgi_ts)); - - init_input_dev(&corgi_ts->input); - corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - input_set_abs_params(&corgi_ts->input, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0); - input_set_abs_params(&corgi_ts->input, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0); - input_set_abs_params(&corgi_ts->input, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0); - - strcpy(corgi_ts->phys, "corgits/input0"); - - corgi_ts->input.private = corgi_ts; - corgi_ts->input.name = "Corgi Touchscreen"; - corgi_ts->input.dev = dev; - corgi_ts->input.phys = corgi_ts->phys; - corgi_ts->input.id.bustype = BUS_HOST; - corgi_ts->input.id.vendor = 0x0001; - corgi_ts->input.id.product = 0x0002; - corgi_ts->input.id.version = 0x0100; - - pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN); - pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN); - - /* Initiaize ADS7846 Difference Reference mode */ - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - - init_timer(&corgi_ts->timer); - corgi_ts->timer.data = (unsigned long) corgi_ts; - corgi_ts->timer.function = corgi_ts_timer; - - input_register_device(&corgi_ts->input); - corgi_ts->power_mode = PWR_MODE_ACTIVE; - - if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) { - input_unregister_device(&corgi_ts->input); - kfree(corgi_ts); - return -EBUSY; - } - - /* Enable Falling Edge */ - set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING); - - printk(KERN_INFO "input: Corgi Touchscreen Registered\n"); - - return 0; -} - -static int corgits_remove(struct device *dev) -{ - struct corgi_ts *corgi_ts = dev_get_drvdata(dev); - - free_irq(CORGI_IRQ_GPIO_TP_INT, NULL); - input_unregister_device(&corgi_ts->input); - kfree(corgi_ts); - return 0; -} - -static struct device_driver corgits_driver = { - .name = "corgi-ts", - .bus = &platform_bus_type, - .probe = corgits_probe, - .remove = corgits_remove, - .suspend = corgits_suspend, - .resume = corgits_resume, -}; - -static int __devinit corgits_init(void) -{ - return driver_register(&corgits_driver); -} - -static void __exit corgits_exit(void) -{ - driver_unregister(&corgits_driver); -} - -module_init(corgits_init); -module_exit(corgits_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Corgi TouchScreen Driver"); -MODULE_LICENSE("GPL"); reverted: --- b/drivers/input/touchscreen/elo.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,315 +0,0 @@ -/* - * Elo serial touchscreen driver - * - * Copyright (c) 2004 Vojtech Pavlik - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -/* - * This driver can handle serial Elo touchscreens using either the Elo standard - * 'E271-2210' 10-byte protocol, Elo legacy 'E281A-4002' 6-byte protocol, Elo - * legacy 'E271-140' 4-byte protocol and Elo legacy 'E261-280' 3-byte protocol. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_DESC "Elo serial touchscreen driver" - -MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -/* - * Definitions & global arrays. - */ - -#define ELO_MAX_LENGTH 10 - -static char *elo_name = "Elo Serial TouchScreen"; - -/* - * Per-touchscreen data. - */ - -struct elo { - struct input_dev dev; - struct serio *serio; - int id; - int idx; - unsigned char csum; - unsigned char data[ELO_MAX_LENGTH]; - char phys[32]; -}; - -static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs) -{ - struct input_dev *dev = &elo->dev; - - elo->csum += elo->data[elo->idx] = data; - - switch (elo->idx++) { - - case 0: - if (data != 'U') { - elo->idx = 0; - elo->csum = 0; - } - break; - - case 1: - if (data != 'T') { - elo->idx = 0; - elo->csum = 0; - } - break; - - case 9: - if (elo->csum) { - input_regs(dev, regs); - input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); - input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); - input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]); - input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]); - input_sync(dev); - } - elo->idx = 0; - elo->csum = 0; - break; - } -} - -static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs) -{ - struct input_dev *dev = &elo->dev; - - elo->data[elo->idx] = data; - - switch (elo->idx++) { - - case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break; - case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break; - case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break; - - case 3: - if (data & 0xc0) { - elo->idx = 0; - break; - } - - input_regs(dev, regs); - input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f)); - input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f)); - - if (elo->id == 2) { - input_report_key(dev, BTN_TOUCH, 1); - input_sync(dev); - elo->idx = 0; - } - - break; - - case 4: - if (data) { - input_sync(dev); - elo->idx = 0; - } - break; - - case 5: - if ((data & 0xf0) == 0) { - input_report_abs(dev, ABS_PRESSURE, elo->data[5]); - input_report_key(dev, BTN_TOUCH, !!elo->data[5]); - } - input_sync(dev); - elo->idx = 0; - break; - } -} - -static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs) -{ - struct input_dev *dev = &elo->dev; - - elo->data[elo->idx] = data; - - switch (elo->idx++) { - - case 0: - if ((data & 0x7f) != 0x01) - elo->idx = 0; - break; - case 2: - input_regs(dev, regs); - input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80)); - input_report_abs(dev, ABS_X, elo->data[1]); - input_report_abs(dev, ABS_Y, elo->data[2]); - input_sync(dev); - elo->idx = 0; - break; - } -} - -static irqreturn_t elo_interrupt(struct serio *serio, - unsigned char data, unsigned int flags, struct pt_regs *regs) -{ - struct elo* elo = serio_get_drvdata(serio); - - switch(elo->id) { - case 0: - elo_process_data_10(elo, data, regs); - break; - - case 1: - case 2: - elo_process_data_6(elo, data, regs); - break; - - case 3: - elo_process_data_3(elo, data, regs); - break; - } - - return IRQ_HANDLED; -} - -/* - * elo_disconnect() is the opposite of elo_connect() - */ - -static void elo_disconnect(struct serio *serio) -{ - struct elo* elo = serio_get_drvdata(serio); - - input_unregister_device(&elo->dev); - serio_close(serio); - serio_set_drvdata(serio, NULL); - kfree(elo); -} - -/* - * elo_connect() is the routine that is called when someone adds a - * new serio device that supports Gunze protocol and registers it as - * an input device. - */ - -static int elo_connect(struct serio *serio, struct serio_driver *drv) -{ - struct elo *elo; - int err; - - if (!(elo = kmalloc(sizeof(struct elo), GFP_KERNEL))) - return -ENOMEM; - - memset(elo, 0, sizeof(struct elo)); - - init_input_dev(&elo->dev); - elo->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - elo->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - - elo->id = serio->id.id; - - switch (elo->id) { - - case 0: /* 10-byte protocol */ - input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0); - input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); - input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0); - break; - - case 1: /* 6-byte protocol */ - input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0); - - case 2: /* 4-byte protocol */ - input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0); - input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); - break; - - case 3: /* 3-byte protocol */ - input_set_abs_params(&elo->dev, ABS_X, 0, 255, 0, 0); - input_set_abs_params(&elo->dev, ABS_Y, 0, 255, 0, 0); - break; - } - - elo->serio = serio; - - sprintf(elo->phys, "%s/input0", serio->phys); - - elo->dev.private = elo; - elo->dev.name = elo_name; - elo->dev.phys = elo->phys; - elo->dev.id.bustype = BUS_RS232; - elo->dev.id.vendor = SERIO_ELO; - elo->dev.id.product = elo->id; - elo->dev.id.version = 0x0100; - - serio_set_drvdata(serio, elo); - - err = serio_open(serio, drv); - if (err) { - serio_set_drvdata(serio, NULL); - kfree(elo); - return err; - } - - input_register_device(&elo->dev); - - printk(KERN_INFO "input: %s on %s\n", elo_name, serio->phys); - - return 0; -} - -/* - * The serio driver structure. - */ - -static struct serio_device_id elo_serio_ids[] = { - { - .type = SERIO_RS232, - .proto = SERIO_ELO, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { 0 } -}; - -MODULE_DEVICE_TABLE(serio, elo_serio_ids); - -static struct serio_driver elo_drv = { - .driver = { - .name = "elo", - }, - .description = DRIVER_DESC, - .id_table = elo_serio_ids, - .interrupt = elo_interrupt, - .connect = elo_connect, - .disconnect = elo_disconnect, -}; - -/* - * The functions for inserting/removing us as a module. - */ - -static int __init elo_init(void) -{ - serio_register_driver(&elo_drv); - return 0; -} - -static void __exit elo_exit(void) -{ - serio_unregister_driver(&elo_drv); -} - -module_init(elo_init); -module_exit(elo_exit); diff -u b/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c --- b/drivers/input/touchscreen/gunze.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/touchscreen/gunze.c 2005-02-09 18:51:40 -08:00 @@ -74,8 +74,8 @@ } input_regs(dev, regs); - input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10)); - input_report_abs(dev, ABS_Y, 1024 - simple_strtoul(gunze->data + 6, NULL, 10)); + input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10) * 4); + input_report_abs(dev, ABS_Y, 3072 - simple_strtoul(gunze->data + 6, NULL, 10) * 3); input_report_key(dev, BTN_TOUCH, gunze->data[0] == 'T'); input_sync(dev); } @@ -128,8 +128,8 @@ init_input_dev(&gunze->dev); gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - input_set_abs_params(&gunze->dev, ABS_X, 24, 1000, 0, 0); - input_set_abs_params(&gunze->dev, ABS_Y, 24, 1000, 0, 0); + input_set_abs_params(&gunze->dev, ABS_X, 96, 4000, 0, 0); + input_set_abs_params(&gunze->dev, ABS_Y, 72, 3000, 0, 0); gunze->serio = serio; reverted: --- b/drivers/input/touchscreen/mk712.c 2005-02-09 19:00:45 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,222 +0,0 @@ -/* - * ICS MK712 touchscreen controller driver - * - * Copyright (c) 1999-2002 Transmeta Corporation - * Copyright (c) 2005 Rick Koch - * Copyright (c) 2005 Vojtech Pavlik - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -/* - * This driver supports the ICS MicroClock MK712 TouchScreen controller, - * found in Gateway AOL Connected Touchpad computers. - * - * Documentation for ICS MK712 can be found at: - * http://www.icst.com/pdf/mk712.pdf - */ - -/* - * 1999-12-18: original version, Daniel Quinlan - * 1999-12-19: added anti-jitter code, report pen-up events, fixed mk712_poll - * to use queue_empty, Nathan Laredo - * 1999-12-20: improved random point rejection, Nathan Laredo - * 2000-01-05: checked in new anti-jitter code, changed mouse protocol, fixed - * queue code, added module options, other fixes, Daniel Quinlan - * 2002-03-15: Clean up for kernel merge - * Fixed multi open race, fixed memory checks, fixed resource - * allocation, fixed close/powerdown bug, switched to new init - * 2005-01-18: Ported to 2.6 from 2.4.28, Rick Koch - * 2005-02-05: Rewritten for the input layer, Vojtech Pavlik - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Daniel Quinlan , Vojtech Pavlik "); -MODULE_DESCRIPTION("ICS MicroClock MK712 TouchScreen driver"); -MODULE_LICENSE("GPL"); - -static unsigned int mk712_io = 0x260; /* Also 0x200, 0x208, 0x300 */ -module_param_named(io, mk712_io, uint, 0); -MODULE_PARM_DESC(io, "I/O base address of MK712 touchscreen controller"); - -static unsigned int mk712_irq = 10; /* Also 12, 14, 15 */ -module_param_named(irq, mk712_irq, uint, 0); -MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller"); - -/* eight 8-bit registers */ -#define MK712_STATUS 0 -#define MK712_X 2 -#define MK712_Y 4 -#define MK712_CONTROL 6 -#define MK712_RATE 7 - -/* status */ -#define MK712_STATUS_TOUCH 0x10 -#define MK712_CONVERSION_COMPLETE 0x80 - -/* control */ -#define MK712_ENABLE_INT 0x01 -#define MK712_INT_ON_CONVERSION_COMPLETE 0x02 -#define MK712_INT_ON_CHANGE_IN_TOUCH_STATUS 0x04 -#define MK712_ENABLE_PERIODIC_CONVERSIONS 0x10 -#define MK712_READ_ONE_POINT 0x20 -#define MK712_POWERUP 0x40 - -static int mk712_used = 0; -static struct input_dev mk712_dev; -static DEFINE_SPINLOCK(mk712_lock); - -static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned char status; - static int debounce = 1; - static unsigned short last_x; - static unsigned short last_y; - - spin_lock(&mk712_lock); - input_regs(&mk712_dev, regs); - - status = inb(mk712_io + MK712_STATUS); - - if (~status & MK712_CONVERSION_COMPLETE) { - debounce = 1; - goto end; - } - - if (~status & MK712_STATUS_TOUCH) - { - debounce = 1; - input_report_key(&mk712_dev, BTN_TOUCH, 0); - goto end; - } - - if (debounce) - { - debounce = 0; - goto end; - } - - input_report_key(&mk712_dev, BTN_TOUCH, 1); - input_report_abs(&mk712_dev, ABS_X, last_x); - input_report_abs(&mk712_dev, ABS_Y, last_y); - -end: - - last_x = inw(mk712_io + MK712_X) & 0x0fff; - last_y = inw(mk712_io + MK712_Y) & 0x0fff; - input_sync(&mk712_dev); - spin_unlock(&mk712_lock); - return IRQ_HANDLED; -} - -static int mk712_open(struct input_dev *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&mk712_lock, flags); - - if (!mk712_used++) { - - outb(0, mk712_io + MK712_CONTROL); /* Reset */ - - outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | - MK712_INT_ON_CHANGE_IN_TOUCH_STATUS | - MK712_ENABLE_PERIODIC_CONVERSIONS | - MK712_POWERUP, mk712_io + MK712_CONTROL); - - outb(10, mk712_io + MK712_RATE); /* 187 points per second */ - } - - spin_unlock_irqrestore(&mk712_lock, flags); - - return 0; -} - -static void mk712_close(struct input_dev *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&mk712_lock, flags); - - if (!--mk712_used) - outb(0, mk712_io + MK712_CONTROL); - - spin_unlock_irqrestore(&mk712_lock, flags); -} - -static struct input_dev mk712_dev = { - .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, - .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_TOUCH) }, - .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, - .open = mk712_open, - .close = mk712_close, - .name = "ICS MicroClock MK712 TouchScreen", - .phys = "isa0260/input0", - .absmin = { [ABS_X] = 0, [ABS_Y] = 0 }, - .absmax = { [ABS_X] = 0xfff, [ABS_Y] = 0xfff }, - .absfuzz = { [ABS_X] = 88, [ABS_Y] = 88 }, - .id = { - .bustype = BUS_ISA, - .vendor = 0x0005, - .product = 0x0001, - .version = 0x0100, - }, -}; - -int __init mk712_init(void) -{ - - if(!request_region(mk712_io, 8, "mk712")) - { - printk(KERN_WARNING "mk712: unable to get IO region\n"); - return -ENODEV; - } - - outb(0, mk712_io + MK712_CONTROL); - - if ((inw(mk712_io + MK712_X) & 0xf000) || /* Sanity check */ - (inw(mk712_io + MK712_Y) & 0xf000) || - (inw(mk712_io + MK712_STATUS) & 0xf333)) { - printk(KERN_WARNING "mk712: device not present\n"); - release_region(mk712_io, 8); - return -ENODEV; - } - - if(request_irq(mk712_irq, mk712_interrupt, 0, "mk712", &mk712_dev)) - { - printk(KERN_WARNING "mk712: unable to get IRQ\n"); - release_region(mk712_io, 8); - return -EBUSY; - } - - input_register_device(&mk712_dev); - - printk(KERN_INFO "input: ICS MicroClock MK712 TouchScreen at %#x irq %d\n", mk712_io, mk712_irq); - - return 0; -} - -static void __exit mk712_exit(void) -{ - input_unregister_device(&mk712_dev); - free_irq(mk712_irq, &mk712_dev); - release_region(mk712_io, 8); -} - -module_init(mk712_init); -module_exit(mk712_exit); diff -u b/drivers/input/tsdev.c b/drivers/input/tsdev.c --- b/drivers/input/tsdev.c 2005-02-09 19:00:45 -08:00 +++ b/drivers/input/tsdev.c 2005-02-09 18:51:40 -08:00 @@ -232,9 +232,11 @@ static unsigned int tsdev_poll(struct file *file, poll_table * wait) { struct tsdev_list *list = file->private_data; + poll_wait(file, &list->tsdev->wait, wait); - return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | - (list->tsdev->exist ? 0 : (POLLHUP | POLLERR)); + if (list->head != list->tail) + return POLLIN | POLLRDNORM; + return 0; } static int tsdev_ioctl(struct inode *inode, struct file *file, @@ -424,7 +426,6 @@ static void tsdev_disconnect(struct input_handle *handle) { struct tsdev *tsdev = handle->private; - struct tsdev_list *list; class_simple_device_remove(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor)); devfs_remove("input/ts%d", tsdev->minor); @@ -434,8 +435,6 @@ if (tsdev->open) { input_close_device(handle); wake_up_interruptible(&tsdev->wait); - list_for_each_entry(list, &tsdev->list, node) - kill_fasync(&list->fasync, SIGIO, POLL_HUP); } else tsdev_free(tsdev); } reverted: --- b/drivers/usb/input/hid-core.c 2005-02-09 19:00:45 -08:00 +++ a/drivers/usb/input/hid-core.c 2005-02-09 19:00:45 -08:00 @@ -37,20 +37,13 @@ * Version Information */ +#define DRIVER_VERSION "v2.0" -#define DRIVER_VERSION "v2.01" #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" #define DRIVER_DESC "USB HID core driver" #define DRIVER_LICENSE "GPL" static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"}; -/* - * Module parameters. - */ - -static unsigned int hid_mousepoll_interval; -module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); -MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); /* * Register a new report for a device. @@ -128,17 +121,18 @@ if (parser->device->maxcollection == parser->device->collection_size) { collection = kmalloc(sizeof(struct hid_collection) * + parser->device->collection_size * 2, + GFP_KERNEL); - parser->device->collection_size * 2, GFP_KERNEL); if (collection == NULL) { dbg("failed to reallocate collection array"); return -1; } memcpy(collection, parser->device->collection, + sizeof(struct hid_collection) * + parser->device->collection_size); - sizeof(struct hid_collection) * - parser->device->collection_size); memset(collection + parser->device->collection_size, 0, + sizeof(struct hid_collection) * + parser->device->collection_size); - sizeof(struct hid_collection) * - parser->device->collection_size); kfree(parser->device->collection); parser->device->collection = collection; parser->device->collection_size *= 2; @@ -147,12 +141,12 @@ parser->collection_stack[parser->collection_stack_ptr++] = parser->device->maxcollection; + collection = parser->device->collection + - collection = parser->device->collection + parser->device->maxcollection++; collection->type = type; collection->usage = usage; collection->level = parser->collection_stack_ptr - 1; + - if (type == HID_COLLECTION_APPLICATION) parser->device->maxapplication++; @@ -199,7 +193,7 @@ } parser->local.usage[parser->local.usage_index] = usage; parser->local.collection_index[parser->local.usage_index] = + parser->collection_stack_ptr ? - parser->collection_stack_ptr ? parser->collection_stack[parser->collection_stack_ptr - 1] : 0; parser->local.usage_index++; return 0; @@ -226,7 +220,7 @@ dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); return -1; } + - if (!(usages = max_t(int, parser->local.usage_index, parser->global.report_count))) return 0; /* Ignore padding fields */ @@ -587,13 +581,13 @@ item->size = *start++; item->tag = *start++; + if ((end - start) < item->size) - if ((end - start) < item->size) return NULL; item->data.longdata = start; start += item->size; return start; + } - } item->format = HID_ITEM_FORMAT_SHORT; item->size = b & 3; @@ -610,7 +604,7 @@ return start; case 2: + if ((end - start) < 2) - if ((end - start) < 2) return NULL; item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start)); start = (__u8 *)((__le16 *)start + 1); @@ -652,13 +646,13 @@ return NULL; memset(device, 0, sizeof(struct hid_device)); + if (!(device->collection =kmalloc(sizeof(struct hid_collection) * - if (!(device->collection = kmalloc(sizeof(struct hid_collection) * HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) { kfree(device); return NULL; } memset(device->collection, 0, sizeof(struct hid_collection) * + HID_DEFAULT_NUM_COLLECTIONS); - HID_DEFAULT_NUM_COLLECTIONS); device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; for (i = 0; i < HID_REPORT_TYPES; i++) @@ -837,7 +831,7 @@ } else { if (value[n] == field->value[n]) continue; + } - } hid_process_event(hid, field, &field->usage[n], value[n], regs); continue; } @@ -899,8 +893,10 @@ size = ((report->size - 1) >> 3) + 1; + if (len < size) { - if (len < size) dbg("report %d is too short, (%d < %d)", report->id, len, size); + return -1; + } if (hid->claimed & HID_CLAIMED_HIDDEV) hiddev_report_event(hid, report); @@ -938,7 +934,7 @@ default: /* error */ warn("input irq status %d received", urb->status); } + - status = usb_submit_urb(urb, SLAB_ATOMIC); if (status) err("can't resubmit intr, %s-%s/input%d, status %d", @@ -960,7 +956,7 @@ for (n = 0; n < count; n++) { if (field->logical_minimum < 0) /* signed values */ implement(data, offset + n * size, size, s32ton(field->value[n], size)); + else /* unsigned values */ - else /* unsigned values */ implement(data, offset + n * size, size, field->value[n]); } } @@ -1122,8 +1118,8 @@ hid->cr->wLength = cpu_to_le16(len); dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u", + hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", + hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength); - hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", - hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength); if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) { err("usb_submit_urb(ctrl) failed"); @@ -1190,7 +1186,7 @@ switch (urb->status) { case 0: /* success */ + if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) - if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs); case -ESHUTDOWN: /* unplug */ case -EILSEQ: /* unplug timectrl on uhci */ @@ -1409,11 +1405,11 @@ #define USB_DEVICE_ID_WACOM_INTUOS 0x0020 #define USB_DEVICE_ID_WACOM_PL 0x0030 #define USB_DEVICE_ID_WACOM_INTUOS2 0x0040 +#define USB_DEVICE_ID_WACOM_VOLITO 0x0060 +#define USB_DEVICE_ID_WACOM_PTU 0x0003 -#define USB_DEVICE_ID_WACOM_VOLITO 0x0060 -#define USB_DEVICE_ID_WACOM_PTU 0x0003 +#define USB_VENDOR_ID_KBGEAR 0x084e +#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 -#define USB_VENDOR_ID_KBGEAR 0x084e -#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 #define USB_VENDOR_ID_AIPTEK 0x08ca #define USB_DEVICE_ID_AIPTEK_01 0x0001 @@ -1428,35 +1424,35 @@ #define USB_DEVICE_ID_POWERMATE 0x0410 #define USB_DEVICE_ID_SOUNDKNOB 0x04AA +#define USB_VENDOR_ID_ATEN 0x0557 +#define USB_DEVICE_ID_ATEN_UC100KM 0x2004 +#define USB_DEVICE_ID_ATEN_CS124U 0x2202 +#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204 +#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 +#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 + +#define USB_VENDOR_ID_TOPMAX 0x0663 +#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 + +#define USB_VENDOR_ID_HAPP 0x078b +#define USB_DEVICE_ID_UGCI_DRIVING 0x0010 +#define USB_DEVICE_ID_UGCI_FLYING 0x0020 +#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 + +#define USB_VENDOR_ID_MGE 0x0463 +#define USB_DEVICE_ID_MGE_UPS 0xffff +#define USB_DEVICE_ID_MGE_UPS1 0x0001 -#define USB_VENDOR_ID_ATEN 0x0557 -#define USB_DEVICE_ID_ATEN_UC100KM 0x2004 -#define USB_DEVICE_ID_ATEN_CS124U 0x2202 -#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204 -#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 -#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 - -#define USB_VENDOR_ID_TOPMAX 0x0663 -#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 - -#define USB_VENDOR_ID_HAPP 0x078b -#define USB_DEVICE_ID_UGCI_DRIVING 0x0010 -#define USB_DEVICE_ID_UGCI_FLYING 0x0020 -#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 - -#define USB_VENDOR_ID_MGE 0x0463 -#define USB_DEVICE_ID_MGE_UPS 0xffff -#define USB_DEVICE_ID_MGE_UPS1 0x0001 #define USB_VENDOR_ID_ONTRAK 0x0a07 #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 +#define USB_VENDOR_ID_TANGTOP 0x0d3d +#define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001 -#define USB_VENDOR_ID_TANGTOP 0x0d3d -#define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001 #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f +#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 -#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 +#define USB_VENDOR_ID_A4TECH 0x09DA -#define USB_VENDOR_ID_A4TECH 0x09da #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 #define USB_VENDOR_ID_CYPRESS 0x04b4 @@ -1498,18 +1494,6 @@ #define USB_VENDOR_ID_DELORME 0x1163 #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 -#define USB_VENDOR_ID_MCC 0x09db -#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 -#define USB_DEVICE_ID_MCC_PMD1208LS 0x007a - -#define USB_VENDOR_ID_CHICONY 0x04f2 -#define USB_DEVICE_ID_CHICONY_USBHUB_KB 0x0100 - - -/* - * Alphabetically sorted blacklist by quirk type. - */ - static struct hid_blacklist { __u16 idVendor; __u16 idProduct; @@ -1528,9 +1512,9 @@ { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE }, + - { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, 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_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, @@ -1538,9 +1522,6 @@ { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, 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_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, 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 }, @@ -1576,17 +1557,18 @@ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, 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_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET}, { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, + { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, @@ -1597,6 +1579,13 @@ { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE }, + + { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE }, + { 0, 0 } }; @@ -1706,10 +1695,6 @@ if (dev->speed == USB_SPEED_HIGH) interval = 1 << (interval - 1); - /* Change the polling interval of mice. */ - if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) - interval = hid_mousepoll_interval; - if (endpoint->bEndpointAddress & USB_DIR_IN) { if (hid->urbin) continue; @@ -1739,7 +1724,7 @@ } init_waitqueue_head(&hid->wait); + - spin_lock_init(&hid->outlock); spin_lock_init(&hid->ctrllock); @@ -1761,9 +1746,9 @@ } else if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0) { snprintf(hid->name, 128, "%s", buf); } else + snprintf(hid->name, 128, "%04x:%04x", + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); - snprintf(hid->name, 128, "%04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); usb_make_path(dev, buf, 64); snprintf(hid->phys, 64, "%s/input%d", buf, @@ -1907,7 +1892,7 @@ static struct usb_device_id hid_usb_ids [] = { { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, + .bInterfaceClass = USB_INTERFACE_CLASS_HID }, - .bInterfaceClass = USB_INTERFACE_CLASS_HID }, { } /* Terminating entry */ }; reverted: --- b/drivers/usb/input/hid-ff.c 2005-02-09 19:00:45 -08:00 +++ a/drivers/usb/input/hid-ff.c 2005-02-09 19:00:45 -08:00 @@ -55,7 +55,6 @@ {0x46d, 0xc211, hid_lgff_init}, // Logitech Cordless rumble pad {0x46d, 0xc283, hid_lgff_init}, // Logitech Wingman Force 3d {0x46d, 0xc295, hid_lgff_init}, // Logitech MOMO force wheel - {0x46d, 0xc219, hid_lgff_init}, // Logitech Cordless rumble pad 2 #endif #ifdef CONFIG_HID_PID {0x45e, 0x001b, hid_pid_init}, reverted: --- b/drivers/usb/input/hid-lgff.c 2005-02-09 19:00:45 -08:00 +++ a/drivers/usb/input/hid-lgff.c 2005-02-09 19:00:45 -08:00 @@ -126,7 +126,6 @@ static struct device_type devices[] = { {0x046d, 0xc211, ff_rumble}, - {0x046d, 0xc219, ff_rumble}, {0x046d, 0xc283, ff_joystick}, {0x0000, 0x0000, ff_joystick} }; reverted: --- b/drivers/usb/input/hiddev.c 2005-02-09 19:00:45 -08:00 +++ a/drivers/usb/input/hiddev.c 2005-02-09 19:00:45 -08:00 @@ -634,8 +634,9 @@ goto inval; else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && + (uref_multi->num_values >= HID_MAX_MULTI_USAGES || + uref->usage_index + uref_multi->num_values >= field->report_count || + uref->usage_index + uref_multi->num_values < uref->usage_index)) - (uref_multi->num_values > HID_MAX_MULTI_USAGES || - uref->usage_index + uref_multi->num_values >= field->report_count)) goto inval; } reverted: --- b/drivers/usb/input/powermate.c 2005-02-09 19:00:45 -08:00 +++ a/drivers/usb/input/powermate.c 2005-02-09 19:00:45 -08:00 @@ -395,7 +395,6 @@ pm->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); pm->input.event = powermate_input_event; pm->input.dev = &intf->dev; - pm->input.phys = pm->phys; input_register_device(&pm->input); reverted: --- b/drivers/usb/input/wacom.c 2005-02-09 19:00:45 -08:00 +++ a/drivers/usb/input/wacom.c 2005-02-09 19:00:45 -08:00 @@ -72,7 +72,7 @@ /* * Version Information */ +#define DRIVER_VERSION "v1.30" -#define DRIVER_VERSION "v1.40" #define DRIVER_AUTHOR "Vojtech Pavlik " #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_LICENSE "GPL" @@ -141,10 +141,8 @@ goto exit; } + if (data[0] != 2) - if (data[0] != 2) { dbg("wacom_pl_irq: received unknown report #%d", data[0]); - goto exit; - } prox = data[1] & 0x40; @@ -235,7 +233,6 @@ if (data[0] != 2) { printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); - goto exit; } input_regs(dev, regs); @@ -249,9 +246,9 @@ input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); input_report_key(dev, BTN_TOUCH, data[1] & 0x01); } + input_report_abs(dev, ABS_X, data[3] << 8 | data[2]); + input_report_abs(dev, ABS_Y, data[5] << 8 | data[4]); + input_report_abs(dev, ABS_PRESSURE, (data[6]|data[7] << 8)); - input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2])); - input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4])); - input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); input_report_key(dev, BTN_STYLUS, data[1] & 0x02); input_report_key(dev, BTN_STYLUS2, data[1] & 0x10); @@ -286,15 +283,10 @@ goto exit; } - if (data[0] != 2) { - printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); - goto exit; - } - input_regs(dev, regs); input_report_key(dev, BTN_TOOL_PEN, 1); + input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((__le16 *) &data[1]))); + input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((__le16 *) &data[3]))); - input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1])); - input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3])); input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127); input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); @@ -330,10 +322,12 @@ goto exit; } + /* check if we can handle the data */ + if (data[0] == 99) + goto exit; + + if (data[0] != 2) - if (data[0] != 2) { dbg("wacom_graphire_irq: received unknown report #%d", data[0]); - goto exit; - } x = le16_to_cpu(*(__le16 *) &data[2]); y = le16_to_cpu(*(__le16 *) &data[4]); @@ -387,171 +381,107 @@ __FUNCTION__, retval); } +static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) -static int wacom_intuos_inout(struct urb *urb) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; struct input_dev *dev = &wacom->dev; + unsigned int t; int idx; + int retval; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + goto exit; + } + + if (data[0] != 2) + dbg("wacom_intuos_irq: received unknown report #%d", data[0]); + + input_regs(dev, regs); /* tool number */ idx = data[1] & 0x01; + if ((data[1] & 0xfc) == 0xc0) { /* Enter report */ + + wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) + /* serial number of the tool */ - /* Enter report */ - if ((data[1] & 0xfc) == 0xc0) - { - /* serial number of the tool */ - wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) + ((__u32)data[4] << 20) + ((__u32)data[5] << 12) + ((__u32)data[6] << 4) + (data[7] >> 4); switch (((__u32)data[2] << 4) | (data[3] >> 4)) { + case 0x812: + case 0x012: wacom->tool[idx] = BTN_TOOL_PENCIL; break; /* Inking pen */ + case 0x822: - case 0x812: /* Inking pen */ - case 0x801: /* Intuos3 Inking pen */ - case 0x012: - wacom->tool[idx] = BTN_TOOL_PENCIL; - break; - case 0x822: /* Pen */ case 0x842: case 0x852: + case 0x022: wacom->tool[idx] = BTN_TOOL_PEN; break; /* Pen */ + case 0x832: + case 0x032: wacom->tool[idx] = BTN_TOOL_BRUSH; break; /* Stroke pen */ + case 0x007: - case 0x823: /* Intuos3 Grip Pen */ - case 0x813: /* Intuos3 Classic Pen */ - case 0x885: /* Intuos3 Marker Pen */ - case 0x022: - wacom->tool[idx] = BTN_TOOL_PEN; - break; - case 0x832: /* Stroke pen */ - case 0x032: - wacom->tool[idx] = BTN_TOOL_BRUSH; - break; - case 0x007: /* Mouse 4D and 2D */ case 0x09c: + case 0x094: wacom->tool[idx] = BTN_TOOL_MOUSE; break; /* Mouse 4D and 2D */ + case 0x096: wacom->tool[idx] = BTN_TOOL_LENS; break; /* Lens cursor */ + case 0x82a: - case 0x094: - case 0x017: /* Intuos3 2D Mouse */ - wacom->tool[idx] = BTN_TOOL_MOUSE; - break; - case 0x096: /* Lens cursor */ - case 0x097: /* Intuos3 Lens cursor */ - wacom->tool[idx] = BTN_TOOL_LENS; - break; - case 0x82a: /* Eraser */ case 0x85a: case 0x91a: case 0xd1a: + case 0x0fa: wacom->tool[idx] = BTN_TOOL_RUBBER; break; /* Eraser */ - case 0x0fa: - case 0x82b: /* Intuos3 Grip Pen Eraser */ - case 0x81b: /* Intuos3 Classic Pen Eraser */ - case 0x91b: /* Intuos3 Airbrush Eraser */ - wacom->tool[idx] = BTN_TOOL_RUBBER; - break; case 0xd12: case 0x912: + case 0x112: wacom->tool[idx] = BTN_TOOL_AIRBRUSH; break; /* Airbrush */ + default: wacom->tool[idx] = BTN_TOOL_PEN; break; /* Unknown tool */ - case 0x112: - case 0x913: /* Intuos3 Airbrush */ - wacom->tool[idx] = BTN_TOOL_AIRBRUSH; - break; /* Airbrush */ - default: /* Unknown tool */ - wacom->tool[idx] = BTN_TOOL_PEN; } + input_report_key(dev, wacom->tool[idx], 1); input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); input_sync(dev); + goto exit; - return 1; } + if ((data[1] & 0xfe) == 0x80) { /* Exit report */ - /* Exit report */ - if ((data[1] & 0xfe) == 0x80) { input_report_key(dev, wacom->tool[idx], 0); input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); input_sync(dev); + goto exit; - return 1; } + input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); + input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); + input_report_abs(dev, ABS_DISTANCE, data[9]); - return 0; -} + if ((data[1] & 0xb8) == 0xa0) { /* general pen packet */ + input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); + input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); -static void wacom_intuos_general(struct urb *urb) -{ - struct wacom *wacom = urb->context; - unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; - unsigned int t; - - /* general pen packet */ - if ((data[1] & 0xb8) == 0xa0) - { - t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); - input_report_abs(dev, ABS_PRESSURE, t); - input_report_abs(dev, ABS_TILT_X, - ((data[7] << 1) & 0x7e) | (data[8] >> 7)); input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); input_report_key(dev, BTN_STYLUS, data[1] & 2); input_report_key(dev, BTN_STYLUS2, data[1] & 4); input_report_key(dev, BTN_TOUCH, t > 10); } + if ((data[1] & 0xbc) == 0xb4) { /* airbrush second packet */ + input_report_abs(dev, ABS_WHEEL, ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); + input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - /* airbrush second packet */ - if ((data[1] & 0xbc) == 0xb4) - { - input_report_abs(dev, ABS_WHEEL, - ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); - input_report_abs(dev, ABS_TILT_X, - ((data[7] << 1) & 0x7e) | (data[8] >> 7)); input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); } - return; -} - -static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) -{ - struct wacom *wacom = urb->context; - unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; - unsigned int t; - int idx; - int retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); - goto exit; - } - - if (data[0] != 2 && data[0] != 5 && data[0] != 6) { - dbg("wacom_intuos_irq: received unknown report #%d", data[0]); - goto exit; - } - - input_regs(dev, regs); - - /* tool number */ - idx = data[1] & 0x01; - - /* process in/out prox events */ - if (wacom_intuos_inout(urb)) goto exit; - - input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); - input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); - input_report_abs(dev, ABS_DISTANCE, data[9]); - - /* process general packets */ - wacom_intuos_general(urb); if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */ if (data[1] & 0x02) { /* Rotation packet */ + input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? + ((__u32)data[6] << 3) | ((data[7] >> 5) & 7): + (-(((__u32)data[6] << 3) | ((data[7] >> 5) & 7))) - 1); - t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); - input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2); } else { @@ -563,8 +493,9 @@ input_report_key(dev, BTN_SIDE, data[8] & 0x20); input_report_key(dev, BTN_EXTRA, data[8] & 0x10); + input_report_abs(dev, ABS_THROTTLE, -((data[8] & 0x08) ? + ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) : + -((__u32)data[6] << 2) | ((data[7] >> 6) & 3))); - t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); - input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); } else { if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */ @@ -596,111 +527,6 @@ __FUNCTION__, retval); } -static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs) -{ - struct wacom *wacom = urb->context; - unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; - unsigned int t; - int idx, retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); - goto exit; - } - - /* check for valid report */ - if (data[0] != 2 && data[0] != 5 && data[0] != 12) - { - printk(KERN_INFO "wacom_intuos3_irq: received unknown report #%d\n", data[0]); - goto exit; - } - - input_regs(dev, regs); - - /* tool index is always 0 here since there is no dual input tool */ - idx = data[1] & 0x01; - - /* pad packets. Works as a second tool and is always in prox */ - if (data[0] == 12) - { - /* initiate the pad as a device */ - if (wacom->tool[1] != BTN_TOOL_FINGER) - { - wacom->tool[1] = BTN_TOOL_FINGER; - input_report_key(dev, wacom->tool[1], 1); - } - input_report_key(dev, BTN_0, (data[5] & 0x01)); - input_report_key(dev, BTN_1, (data[5] & 0x02)); - input_report_key(dev, BTN_2, (data[5] & 0x04)); - input_report_key(dev, BTN_3, (data[5] & 0x08)); - input_report_key(dev, BTN_4, (data[6] & 0x01)); - input_report_key(dev, BTN_5, (data[6] & 0x02)); - input_report_key(dev, BTN_6, (data[6] & 0x04)); - input_report_key(dev, BTN_7, (data[6] & 0x08)); - input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); - input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); - input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff); - input_sync(dev); - goto exit; - } - - /* process in/out prox events */ - if (wacom_intuos_inout(urb)) goto exit; - - input_report_abs(dev, ABS_X, ((__u32)data[2] << 9) | ((__u32)data[3] << 1) | ((data[9] >> 1) & 1)); - input_report_abs(dev, ABS_Y, ((__u32)data[4] << 9) | ((__u32)data[5] << 1) | (data[9] & 1)); - input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); - - /* process general packets */ - wacom_intuos_general(urb); - - if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) - { - /* Marker pen rotation packet. Reported as wheel due to valuator limitation */ - if (data[1] & 0x02) - { - t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); - t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : - ((t-1) / 2 + 450)) : (450 - t / 2) ; - input_report_abs(dev, ABS_WHEEL, t); - } - - /* 2D mouse packets */ - if (wacom->tool[idx] == BTN_TOOL_MOUSE) - { - input_report_key(dev, BTN_LEFT, data[8] & 0x04); - input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); - input_report_key(dev, BTN_RIGHT, data[8] & 0x10); - input_report_key(dev, BTN_SIDE, data[8] & 0x40); - input_report_key(dev, BTN_EXTRA, data[8] & 0x20); - /* mouse wheel is positive when rolled backwards */ - input_report_rel(dev, REL_WHEEL, ((__u32)((data[8] & 0x02) >> 1) - - (__u32)(data[8] & 0x01))); - } - } - - input_report_key(dev, wacom->tool[idx], 1); - input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); - input_sync(dev); - -exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); - if (retval) - err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); -} - static struct wacom_features wacom_features[] = { { "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq }, { "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, @@ -726,9 +552,6 @@ { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, { "Wacom Volito", 8, 5104, 3712, 511, 32, 1, wacom_graphire_irq }, { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, 3, wacom_ptu_irq }, - { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, 4, wacom_intuos3_irq }, - { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq }, - { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq }, { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, { } }; @@ -758,9 +581,6 @@ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, { } }; @@ -831,12 +651,6 @@ wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); break; - case 4: /* new functions for Intuos3 */ - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); - wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); - wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY); - /* fall through */ - case 2: wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); @@ -848,7 +662,7 @@ break; case 3: + wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2); - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); break; } @@ -860,8 +674,6 @@ wacom->dev.absmax[ABS_TILT_Y] = 127; wacom->dev.absmax[ABS_WHEEL] = 1023; - wacom->dev.absmax[ABS_RX] = 4097; - wacom->dev.absmax[ABS_RY] = 4097; wacom->dev.absmin[ABS_RZ] = -900; wacom->dev.absmax[ABS_RZ] = 899; wacom->dev.absmin[ABS_THROTTLE] = -1023; @@ -900,10 +712,9 @@ input_register_device(&wacom->dev); - /* ask the tablet to report tablet data */ - usb_set_report(intf, 3, 2, rep_data, 2); - /* repeat once (not sure why the first call often fails) */ usb_set_report(intf, 3, 2, rep_data, 2); + usb_set_report(intf, 3, 5, rep_data, 0); + usb_set_report(intf, 3, 6, rep_data, 0); printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path); diff -u b/include/linux/serio.h b/include/linux/serio.h --- b/include/linux/serio.h 2005-02-09 19:00:45 -08:00 +++ b/include/linux/serio.h 2005-02-09 18:51:40 -08:00 @@ -10,12 +10,12 @@ */ #include +#include #define SPIOCSTYPE _IOW('q', 0x01, unsigned long) #ifdef __KERNEL__ -#include #include #include #include @@ -217,5 +217,4 @@ #define SERIO_SEMTECH 0x27 #define SERIO_LKKBD 0x28 -#define SERIO_ELO 0x29 #endif