Commit 7d9f7f7e authored by Vojtech Pavlik's avatar Vojtech Pavlik Committed by Linus Torvalds

input: Change AT keyboard to use hardware autorepeat and move

       untranslating to the AT keyboard driver as well. Lower
       PS/2 mouse default report rate. Fix repeat rate adjustment
       ioctls accordingly, and update other files to reflect the
       changes. This should fix most known keyboard problems in 2.6.
parent d4032a97
...@@ -264,12 +264,6 @@ void kd_mksound(unsigned int hz, unsigned int ticks) ...@@ -264,12 +264,6 @@ void kd_mksound(unsigned int hz, unsigned int ticks)
/* /*
* Setting the keyboard rate. * Setting the keyboard rate.
*/ */
static inline unsigned int ms_to_jiffies(unsigned int ms) {
unsigned int j;
j = (ms * HZ + 500) / 1000;
return (j > 0) ? j : 1;
}
int kbd_rate(struct kbd_repeat *rep) int kbd_rate(struct kbd_repeat *rep)
{ {
...@@ -283,11 +277,11 @@ int kbd_rate(struct kbd_repeat *rep) ...@@ -283,11 +277,11 @@ int kbd_rate(struct kbd_repeat *rep)
if (test_bit(EV_REP, dev->evbit)) { if (test_bit(EV_REP, dev->evbit)) {
if (rep->delay > 0) if (rep->delay > 0)
dev->rep[REP_DELAY] = ms_to_jiffies(rep->delay); input_event(dev, EV_REP, REP_DELAY, rep->delay);
if (rep->period > 0) if (rep->period > 0)
dev->rep[REP_PERIOD] = ms_to_jiffies(rep->period); input_event(dev, EV_REP, REP_PERIOD, rep->period);
d = dev->rep[REP_DELAY] * 1000 / HZ; d = dev->rep[REP_DELAY];
p = dev->rep[REP_PERIOD] * 1000 / HZ; p = dev->rep[REP_PERIOD];
} }
} }
rep->delay = d; rep->delay = d;
......
...@@ -220,16 +220,6 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -220,16 +220,6 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case EVIOCGID: case EVIOCGID:
return copy_to_user((void *) arg, &dev->id, sizeof(struct input_id)) ? -EFAULT : 0; return copy_to_user((void *) arg, &dev->id, sizeof(struct input_id)) ? -EFAULT : 0;
case EVIOCGREP:
if (put_user(dev->rep[0], ((int *) arg) + 0)) return -EFAULT;
if (put_user(dev->rep[1], ((int *) arg) + 1)) return -EFAULT;
return 0;
case EVIOCSREP:
if (get_user(dev->rep[0], ((int *) arg) + 0)) return -EFAULT;
if (get_user(dev->rep[1], ((int *) arg) + 1)) return -EFAULT;
return 0;
case EVIOCGKEYCODE: case EVIOCGKEYCODE:
if (get_user(t, ((int *) arg) + 0)) return -EFAULT; if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL; if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
......
...@@ -55,6 +55,13 @@ DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait); ...@@ -55,6 +55,13 @@ DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
static int input_devices_state; static int input_devices_state;
#endif #endif
static inline unsigned int ms_to_jiffies(unsigned int ms)
{
unsigned int j;
j = (ms * HZ + 500) / 1000;
return (j > 0) ? j : 1;
}
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{ {
...@@ -93,9 +100,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in ...@@ -93,9 +100,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
change_bit(code, dev->key); change_bit(code, dev->key);
if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && value) { if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->timer.data && value) {
dev->repeat_key = code; dev->repeat_key = code;
mod_timer(&dev->timer, jiffies + dev->rep[REP_DELAY]); mod_timer(&dev->timer, jiffies + ms_to_jiffies(dev->rep[REP_DELAY]));
} }
break; break;
...@@ -162,7 +169,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in ...@@ -162,7 +169,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
case EV_REP: case EV_REP:
if (code > REP_MAX || dev->rep[code] == value) return; if (code > REP_MAX || value < 0 || dev->rep[code] == value) return;
dev->rep[code] = value; dev->rep[code] = value;
if (dev->event) dev->event(dev, type, code, value); if (dev->event) dev->event(dev, type, code, value);
...@@ -195,7 +202,7 @@ static void input_repeat_key(unsigned long data) ...@@ -195,7 +202,7 @@ static void input_repeat_key(unsigned long data)
input_event(dev, EV_KEY, dev->repeat_key, 2); input_event(dev, EV_KEY, dev->repeat_key, 2);
input_sync(dev); input_sync(dev);
mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]); mod_timer(&dev->timer, jiffies + ms_to_jiffies(dev->rep[REP_PERIOD]));
} }
int input_accept_process(struct input_handle *handle, struct file *file) int input_accept_process(struct input_handle *handle, struct file *file)
...@@ -423,13 +430,18 @@ void input_register_device(struct input_dev *dev) ...@@ -423,13 +430,18 @@ void input_register_device(struct input_dev *dev)
set_bit(EV_SYN, dev->evbit); set_bit(EV_SYN, dev->evbit);
/*
* If delay and period are pre-set by the driver, then autorepeating
* is handled by the driver itself and we don't do it in input.c.
*/
init_timer(&dev->timer); init_timer(&dev->timer);
dev->timer.data = (long) dev; if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
dev->timer.function = input_repeat_key; dev->timer.data = (long) dev;
if (!dev->rep[REP_DELAY]) dev->timer.function = input_repeat_key;
dev->rep[REP_DELAY] = HZ/4; dev->rep[REP_DELAY] = 250;
if (!dev->rep[REP_PERIOD]) dev->rep[REP_PERIOD] = 33;
dev->rep[REP_PERIOD] = HZ/33; }
INIT_LIST_HEAD(&dev->h_list); INIT_LIST_HEAD(&dev->h_list);
list_add_tail(&dev->node, &input_dev_list); list_add_tail(&dev->node, &input_dev_list);
......
...@@ -10,6 +10,13 @@ ...@@ -10,6 +10,13 @@
* the Free Software Foundation. * the Free Software Foundation.
*/ */
/*
* This driver can handle standard AT keyboards and PS/2 keyboards in
* Translated and Raw Set 2 and Set 3, as well as AT keyboards on dumb
* input-only controllers and AT keyboards connected over a one way RS232
* converter.
*/
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -24,6 +31,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); ...@@ -24,6 +31,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("AT and PS/2 keyboard driver"); MODULE_DESCRIPTION("AT and PS/2 keyboard driver");
MODULE_PARM(atkbd_set, "1i"); MODULE_PARM(atkbd_set, "1i");
MODULE_PARM(atkbd_reset, "1i"); MODULE_PARM(atkbd_reset, "1i");
MODULE_PARM(atkbd_softrepeat, "1i");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int atkbd_set = 2; static int atkbd_set = 2;
...@@ -32,6 +40,7 @@ static int atkbd_reset; ...@@ -32,6 +40,7 @@ static int atkbd_reset;
#else #else
static int atkbd_reset = 1; static int atkbd_reset = 1;
#endif #endif
static int atkbd_softrepeat;
/* /*
* Scancode to keycode tables. These are just the default setting, and * Scancode to keycode tables. These are just the default setting, and
...@@ -47,19 +56,19 @@ static unsigned char atkbd_set2_keycode[512] = { ...@@ -47,19 +56,19 @@ static unsigned char atkbd_set2_keycode[512] = {
122, 89, 40,120, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 0, 122, 89, 40,120, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 0,
85, 86, 90, 91, 92, 93, 14, 94, 95, 79,183, 75, 71,121, 0,123, 85, 86, 90, 91, 92, 93, 14, 94, 95, 79,183, 75, 71,121, 0,123,
82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99, 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
252, 0, 0, 65, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,251, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
252,253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,
0, 0, 92, 90, 85, 0,137, 0, 0, 0, 0, 91, 89,144,115, 0, 0, 0, 92, 90, 85, 0,137, 0, 0, 0, 0, 91, 89,144,115, 0,
217,100,255, 0, 97,165,164, 0,156, 0, 0,140,115, 0, 0,125, 217,100,255, 0, 97,165,164, 0,156, 0, 0,140,115, 0, 0,125,
173,114, 0,113,152,163,151,126,128,166, 0,140, 0,147, 0,127, 173,114, 0,113,152,163,151,126,128,166, 0,140, 0,147, 0,127,
159,167,115,160,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142, 159,167,115,160,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
157, 0,114,166,168, 0, 0, 0,155, 0, 98,113, 0,163, 0,138, 157, 0,114,166,168, 0, 0,213,155, 0, 98,113, 0,163, 0,138,
226, 0, 0, 0, 0, 0,153,140, 0,255, 96, 0, 0, 0,143, 0, 226, 0, 0, 0, 0, 0,153,140, 0,255, 96, 0, 0, 0,143, 0,
133, 0,116, 0,143, 0,174,133, 0,107, 0,105,102, 0, 0,112, 133, 0,116, 0,143, 0,174,133, 0,107, 0,105,102, 0, 0,112,
110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119
...@@ -76,12 +85,23 @@ static unsigned char atkbd_set3_keycode[512] = { ...@@ -76,12 +85,23 @@ static unsigned char atkbd_set3_keycode[512] = {
82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55, 85, 82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55, 85,
89, 90, 91, 92, 74,185,184,182, 0, 0, 0,125,126,127,112, 0, 89, 90, 91, 92, 74,185,184,182, 0, 0, 0,125,126,127,112, 0,
0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168, 0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
148,149,147,140, 0, 0, 0, 0, 0, 0,251, 0, 0, 0, 0, 0, 148,149,147,140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
252,253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255
254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255 };
static unsigned char atkbd_unxlate_table[128] = {
0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
}; };
#define ATKBD_CMD_SETLEDS 0x10ed #define ATKBD_CMD_SETLEDS 0x10ed
...@@ -99,12 +119,13 @@ static unsigned char atkbd_set3_keycode[512] = { ...@@ -99,12 +119,13 @@ static unsigned char atkbd_set3_keycode[512] = {
#define ATKBD_RET_ACK 0xfa #define ATKBD_RET_ACK 0xfa
#define ATKBD_RET_NAK 0xfe #define ATKBD_RET_NAK 0xfe
#define ATKBD_RET_BAT 0xaa
#define ATKBD_RET_EMUL0 0xe0
#define ATKBD_RET_EMULX 0x80
#define ATKBD_RET_EMUL1 0xe1
#define ATKBD_RET_RELEASE 0xf0
#define ATKBD_KEY_UNKNOWN 0 #define ATKBD_KEY_UNKNOWN 0
#define ATKBD_KEY_BAT 251
#define ATKBD_KEY_EMUL0 252
#define ATKBD_KEY_EMUL1 253
#define ATKBD_KEY_RELEASE 254
#define ATKBD_KEY_NULL 255 #define ATKBD_KEY_NULL 255
/* /*
...@@ -127,7 +148,11 @@ struct atkbd { ...@@ -127,7 +148,11 @@ struct atkbd {
unsigned char emul; unsigned char emul;
unsigned short id; unsigned short id;
unsigned char write; unsigned char write;
unsigned char translated;
unsigned char resend; unsigned char resend;
unsigned char bat_xl;
unsigned int last;
unsigned long time;
}; };
/* /*
...@@ -139,7 +164,8 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -139,7 +164,8 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
unsigned int flags, struct pt_regs *regs) unsigned int flags, struct pt_regs *regs)
{ {
struct atkbd *atkbd = serio->private; struct atkbd *atkbd = serio->private;
int code = data; unsigned int code = data;
int value;
#ifdef ATKBD_DEBUG #ifdef ATKBD_DEBUG
printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags); printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
...@@ -153,10 +179,38 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -153,10 +179,38 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
goto out; goto out;
} }
if (!flags) if (!flags && data == ATKBD_RET_ACK)
atkbd->resend = 0; atkbd->resend = 0;
#endif #endif
if (atkbd->translated) do {
if (atkbd->emul != 1) {
if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
code == ATKBD_RET_ACK || code == ATKBD_RET_NAK)
break;
if (code == ATKBD_RET_BAT) {
if (!atkbd->bat_xl)
break;
atkbd->bat_xl = 0;
}
if (code == (ATKBD_RET_BAT & 0x7f))
atkbd->bat_xl = 1;
}
if (code < 0x80) {
code = atkbd_unxlate_table[code];
break;
}
if (atkbd->cmdcnt)
break;
code = atkbd_unxlate_table[code & 0x7f];
atkbd->release = 1;
} while (0);
switch (code) { switch (code) {
case ATKBD_RET_ACK: case ATKBD_RET_ACK:
atkbd->ack = 1; atkbd->ack = 1;
...@@ -171,17 +225,17 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -171,17 +225,17 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
goto out; goto out;
} }
switch (atkbd->keycode[code]) { switch (code) {
case ATKBD_KEY_BAT: case ATKBD_RET_BAT:
serio_rescan(atkbd->serio); serio_rescan(atkbd->serio);
goto out; goto out;
case ATKBD_KEY_EMUL0: case ATKBD_RET_EMUL0:
atkbd->emul = 1; atkbd->emul = 1;
goto out; goto out;
case ATKBD_KEY_EMUL1: case ATKBD_RET_EMUL1:
atkbd->emul = 2; atkbd->emul = 2;
goto out; goto out;
case ATKBD_KEY_RELEASE: case ATKBD_RET_RELEASE:
atkbd->release = 1; atkbd->release = 1;
goto out; goto out;
} }
...@@ -196,21 +250,31 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -196,21 +250,31 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
case ATKBD_KEY_NULL: case ATKBD_KEY_NULL:
break; break;
case ATKBD_KEY_UNKNOWN: case ATKBD_KEY_UNKNOWN:
printk(KERN_WARNING "atkbd.c: Unknown key (set %d, scancode %#x, on %s) %s.\n", printk(KERN_WARNING "atkbd.c: Unknown key %s (%s set %d, code %#x, data %#x, on %s).\n",
atkbd->set, code, serio->phys, atkbd->release ? "released" : "pressed"); atkbd->release ? "released" : "pressed",
atkbd->translated ? "translated" : "raw",
atkbd->set, code, data, serio->phys);
break; break;
default: default:
#if 0 value = atkbd->release ? 0 :
if (!atkbd->release) { (1 + (!atkbd_softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
mod_timer(&atkbd->timer,
jiffies + (test_bit(atkbd->keycode[code], switch (value) { /* Workaround Toshiba laptop multiple keypress */
atkbd->dev.key) ? HZ/33 : HZ/4) + HZ/100); case 0:
atkbd->lastkey = atkbd->keycode[code]; atkbd->last = 0;
break;
case 1:
atkbd->last = code;
atkbd->time = jiffies + (atkbd->dev.rep[REP_DELAY] * HZ + 500) / 1000 / 2;
break;
case 2:
if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
value = 1;
break;
} }
#endif
input_regs(&atkbd->dev, regs); input_regs(&atkbd->dev, regs);
input_report_key(&atkbd->dev, atkbd->keycode[code], !atkbd->release); input_event(&atkbd->dev, EV_KEY, atkbd->keycode[code], value);
input_sync(&atkbd->dev); input_sync(&atkbd->dev);
} }
...@@ -219,13 +283,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -219,13 +283,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void atkbd_force_key_up(unsigned long data)
{
struct atkbd *atkbd = (void *) data;
input_report_key(&atkbd->dev, atkbd->lastkey, 0);
input_sync(&atkbd->dev);
}
/* /*
* atkbd_sendbyte() sends a byte to the keyboard, and waits for * atkbd_sendbyte() sends a byte to the keyboard, and waits for
* acknowledge. It doesn't handle resends according to the keyboard * acknowledge. It doesn't handle resends according to the keyboard
...@@ -312,7 +369,12 @@ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command) ...@@ -312,7 +369,12 @@ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command)
static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{ {
struct atkbd *atkbd = dev->private; struct atkbd *atkbd = dev->private;
struct { int p; u8 v; } period[] =
{ {30, 0x00}, {25, 0x02}, {20, 0x04}, {15, 0x08}, {10, 0x0c}, {7, 0x10}, {5, 0x14}, {0, 0x14} };
struct { int d; u8 v; } delay[] =
{ {1000, 0x60}, {750, 0x40}, {500, 0x20}, {250, 0x00}, {0, 0x00} };
char param[2]; char param[2];
int i, j;
if (!atkbd->write) if (!atkbd->write)
return -1; return -1;
...@@ -337,6 +399,21 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co ...@@ -337,6 +399,21 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
} }
return 0; return 0;
case EV_REP:
if (atkbd_softrepeat) return 0;
i = j = 0;
while (period[i].p > dev->rep[REP_PERIOD]) i++;
while (delay[j].d > dev->rep[REP_DELAY]) j++;
dev->rep[REP_PERIOD] = period[i].p;
dev->rep[REP_DELAY] = delay[j].d;
param[0] = period[i].v | delay[j].v;
atkbd_command(atkbd, param, ATKBD_CMD_SETREP);
return 0;
} }
return -1; return -1;
...@@ -405,6 +482,9 @@ static int atkbd_set_3(struct atkbd *atkbd) ...@@ -405,6 +482,9 @@ static int atkbd_set_3(struct atkbd *atkbd)
* IBM RapidAccess / IBM EzButton / Chicony KBP-8993 keyboards. * IBM RapidAccess / IBM EzButton / Chicony KBP-8993 keyboards.
*/ */
if (atkbd->translated)
return 2;
if (atkbd->id == 0xaca1) { if (atkbd->id == 0xaca1) {
param[0] = 3; param[0] = 3;
atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET); atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET);
...@@ -434,8 +514,11 @@ static int atkbd_set_3(struct atkbd *atkbd) ...@@ -434,8 +514,11 @@ static int atkbd_set_3(struct atkbd *atkbd)
if (atkbd_command(atkbd, param, ATKBD_CMD_GSCANSET)) if (atkbd_command(atkbd, param, ATKBD_CMD_GSCANSET))
return 2; return 2;
if (param[0] != 3) if (param[0] != 3) {
param[0] = 2;
if (atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET))
return 2; return 2;
}
return 3; return 3;
} }
...@@ -508,25 +591,35 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -508,25 +591,35 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
struct atkbd *atkbd; struct atkbd *atkbd;
int i; int i;
if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
(((serio->type & SERIO_TYPE) != SERIO_RS232) || (serio->type & SERIO_PROTO) != SERIO_PS2SER))
return;
if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL))) if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
return; return;
memset(atkbd, 0, sizeof(struct atkbd)); memset(atkbd, 0, sizeof(struct atkbd));
if ((serio->type & SERIO_TYPE) == SERIO_8042 && serio->write) switch (serio->type & SERIO_TYPE) {
atkbd->write = 1;
case SERIO_8042_XL:
atkbd->translated = 1;
case SERIO_8042:
if (serio->write)
atkbd->write = 1;
break;
case SERIO_RS232:
if ((serio->type & SERIO_PROTO) == SERIO_PS2SER)
break;
default:
kfree(atkbd);
return;
}
if (atkbd->write) { if (atkbd->write) {
atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
} else atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); } else atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
atkbd->dev.rep[REP_DELAY] = HZ/4 + HZ/50; if (!atkbd_softrepeat) {
atkbd->dev.rep[REP_PERIOD] = HZ/33; atkbd->dev.rep[REP_DELAY] = 250;
atkbd->dev.rep[REP_PERIOD] = 33;
}
atkbd->serio = serio; atkbd->serio = serio;
...@@ -540,10 +633,6 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -540,10 +633,6 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
serio->private = atkbd; serio->private = atkbd;
init_timer(&atkbd->timer);
atkbd->timer.data = (long) atkbd;
atkbd->timer.function = atkbd_force_key_up;
if (serio_open(serio, dev)) { if (serio_open(serio, dev)) {
kfree(atkbd); kfree(atkbd);
return; return;
...@@ -569,7 +658,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -569,7 +658,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC); atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
sprintf(atkbd->name, "AT Set 2 Extended keyboard"); sprintf(atkbd->name, "AT Set 2 Extended keyboard");
} else } else
sprintf(atkbd->name, "AT Set %d keyboard", atkbd->set); sprintf(atkbd->name, "AT %s Set %d keyboard",
atkbd->translated ? "Translated" : "Raw", atkbd->set);
sprintf(atkbd->phys, "%s/input0", serio->phys); sprintf(atkbd->phys, "%s/input0", serio->phys);
...@@ -586,7 +676,7 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -586,7 +676,7 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd->dev.id.version = atkbd->id; atkbd->dev.id.version = atkbd->id;
for (i = 0; i < 512; i++) for (i = 0; i < 512; i++)
if (atkbd->keycode[i] && atkbd->keycode[i] <= 250) if (atkbd->keycode[i] && atkbd->keycode[i] < 255)
set_bit(atkbd->keycode[i], atkbd->dev.keybit); set_bit(atkbd->keycode[i], atkbd->dev.keybit);
input_register_device(&atkbd->dev); input_register_device(&atkbd->dev);
......
...@@ -28,6 +28,8 @@ MODULE_PARM(psmouse_noext, "1i"); ...@@ -28,6 +28,8 @@ MODULE_PARM(psmouse_noext, "1i");
MODULE_PARM_DESC(psmouse_noext, "Disable any protocol extensions. Useful for KVM switches."); MODULE_PARM_DESC(psmouse_noext, "Disable any protocol extensions. Useful for KVM switches.");
MODULE_PARM(psmouse_resolution, "i"); MODULE_PARM(psmouse_resolution, "i");
MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi."); MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi.");
MODULE_PARM(psmouse_rate, "i");
MODULE_PARM_DESC(psmouse_rate, "Report rate, in reports per second.");
MODULE_PARM(psmouse_smartscroll, "i"); MODULE_PARM(psmouse_smartscroll, "i");
MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
MODULE_PARM(psmouse_resetafter, "i"); MODULE_PARM(psmouse_resetafter, "i");
...@@ -38,6 +40,7 @@ MODULE_LICENSE("GPL"); ...@@ -38,6 +40,7 @@ MODULE_LICENSE("GPL");
static int psmouse_noext; static int psmouse_noext;
int psmouse_resolution; int psmouse_resolution;
unsigned int psmouse_rate = 60;
int psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL; int psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL;
unsigned int psmouse_resetafter; unsigned int psmouse_resetafter;
...@@ -442,6 +445,19 @@ static void psmouse_set_resolution(struct psmouse *psmouse) ...@@ -442,6 +445,19 @@ static void psmouse_set_resolution(struct psmouse *psmouse)
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
} }
/*
* Here we set the mouse report rate.
*/
static void psmouse_set_rate(struct psmouse *psmouse)
{
unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 };
int i = 0;
while (rates[i] > psmouse_rate) i++;
psmouse_command(psmouse, rates + i, PSMOUSE_CMD_SETRATE);
}
/* /*
* psmouse_initialize() initializes the mouse to a sane state. * psmouse_initialize() initializes the mouse to a sane state.
*/ */
...@@ -449,16 +465,13 @@ static void psmouse_set_resolution(struct psmouse *psmouse) ...@@ -449,16 +465,13 @@ static void psmouse_set_resolution(struct psmouse *psmouse)
static void psmouse_initialize(struct psmouse *psmouse) static void psmouse_initialize(struct psmouse *psmouse)
{ {
unsigned char param[2]; unsigned char param[2];
/* /*
* We set the mouse report rate to a highest possible value. * We set the mouse report rate.
* We try 100 first in case mouse fails to set 200.
*/ */
param[0] = 100;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
param[0] = 200; psmouse_set_rate(psmouse);
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
/* /*
* We also set the resolution and scaling. * We also set the resolution and scaling.
......
...@@ -58,8 +58,6 @@ static struct serio i8042_kbd_port; ...@@ -58,8 +58,6 @@ static struct serio i8042_kbd_port;
static struct serio i8042_aux_port; static struct serio i8042_aux_port;
static unsigned char i8042_initial_ctr; static unsigned char i8042_initial_ctr;
static unsigned char i8042_ctr; static unsigned char i8042_ctr;
static unsigned char i8042_last_e0;
static unsigned char i8042_last_release;
static unsigned char i8042_mux_open; static unsigned char i8042_mux_open;
struct timer_list i8042_timer; struct timer_list i8042_timer;
...@@ -69,18 +67,6 @@ struct timer_list i8042_timer; ...@@ -69,18 +67,6 @@ struct timer_list i8042_timer;
*/ */
#define i8042_request_irq_cookie (&i8042_timer) #define i8042_request_irq_cookie (&i8042_timer)
static unsigned long i8042_unxlate_seen[256 / BITS_PER_LONG];
static unsigned char i8042_unxlate_table[128] = {
0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
};
static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/* /*
...@@ -301,7 +287,7 @@ static struct i8042_values i8042_kbd_values = { ...@@ -301,7 +287,7 @@ static struct i8042_values i8042_kbd_values = {
static struct serio i8042_kbd_port = static struct serio i8042_kbd_port =
{ {
.type = SERIO_8042, .type = SERIO_8042_XL,
.write = i8042_kbd_write, .write = i8042_kbd_write,
.open = i8042_open, .open = i8042_open,
.close = i8042_close, .close = i8042_close,
...@@ -400,39 +386,10 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -400,39 +386,10 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!i8042_kbd_values.exists) if (!i8042_kbd_values.exists)
continue; continue;
if (i8042_direct) {
serio_interrupt(&i8042_kbd_port, data, dfl, regs);
continue;
}
if (data > 0x7f) {
unsigned char index = (data & 0x7f) | (i8042_last_e0 << 7);
/* work around hardware that doubles key releases */
if (index == i8042_last_release) {
dbg("i8042 skipped double release (%d)\n", index);
i8042_last_e0 = 0;
continue;
}
if (index == 0xaa || index == 0xb6)
set_bit(index, i8042_unxlate_seen);
if (test_and_clear_bit(index, i8042_unxlate_seen)) {
serio_interrupt(&i8042_kbd_port, 0xf0, dfl, regs);
data = i8042_unxlate_table[data & 0x7f];
i8042_last_release = index;
}
} else {
set_bit(data | (i8042_last_e0 << 7), i8042_unxlate_seen);
data = i8042_unxlate_table[data];
i8042_last_release = 0;
}
i8042_last_e0 = (data == 0xe0);
serio_interrupt(&i8042_kbd_port, data, dfl, regs); serio_interrupt(&i8042_kbd_port, data, dfl, regs);
} }
/* FIXME - was it really ours? */ return IRQ_RETVAL(j);
return IRQ_HANDLED;
} }
/* /*
...@@ -511,8 +468,10 @@ static int __init i8042_controller_init(void) ...@@ -511,8 +468,10 @@ static int __init i8042_controller_init(void)
* BIOSes. * BIOSes.
*/ */
if (i8042_direct) if (i8042_direct) {
i8042_ctr &= ~I8042_CTR_XLATE; i8042_ctr &= ~I8042_CTR_XLATE;
i8042_kbd_port.type = SERIO_8042;
}
/* /*
* Write CTR back. * Write CTR back.
......
...@@ -56,8 +56,6 @@ struct input_absinfo { ...@@ -56,8 +56,6 @@ struct input_absinfo {
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ #define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ #define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
#define EVIOCGREP _IOR('E', 0x03, int[2]) /* get repeat settings */
#define EVIOCSREP _IOW('E', 0x03, int[2]) /* get repeat settings */
#define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */ #define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */
#define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */ #define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */
......
...@@ -107,6 +107,7 @@ static __inline__ void serio_cleanup(struct serio *serio) ...@@ -107,6 +107,7 @@ static __inline__ void serio_cleanup(struct serio *serio)
#define SERIO_HIL_MLC 0x03000000UL #define SERIO_HIL_MLC 0x03000000UL
#define SERIO_PC9800 0x04000000UL #define SERIO_PC9800 0x04000000UL
#define SERIO_PS_PSTHRU 0x05000000UL #define SERIO_PS_PSTHRU 0x05000000UL
#define SERIO_8042_XL 0x06000000UL
#define SERIO_PROTO 0xFFUL #define SERIO_PROTO 0xFFUL
#define SERIO_MSC 0x01 #define SERIO_MSC 0x01
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment