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)
/*
* 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)
{
......@@ -283,11 +277,11 @@ int kbd_rate(struct kbd_repeat *rep)
if (test_bit(EV_REP, dev->evbit)) {
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)
dev->rep[REP_PERIOD] = ms_to_jiffies(rep->period);
d = dev->rep[REP_DELAY] * 1000 / HZ;
p = dev->rep[REP_PERIOD] * 1000 / HZ;
input_event(dev, EV_REP, REP_PERIOD, rep->period);
d = dev->rep[REP_DELAY];
p = dev->rep[REP_PERIOD];
}
}
rep->delay = d;
......
......@@ -220,16 +220,6 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case EVIOCGID:
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:
if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
......
......@@ -55,6 +55,13 @@ DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
static int input_devices_state;
#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)
{
......@@ -93,9 +100,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
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;
mod_timer(&dev->timer, jiffies + dev->rep[REP_DELAY]);
mod_timer(&dev->timer, jiffies + ms_to_jiffies(dev->rep[REP_DELAY]));
}
break;
......@@ -162,7 +169,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
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;
if (dev->event) dev->event(dev, type, code, value);
......@@ -195,7 +202,7 @@ static void input_repeat_key(unsigned long data)
input_event(dev, EV_KEY, dev->repeat_key, 2);
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)
......@@ -423,13 +430,18 @@ void input_register_device(struct input_dev *dev)
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);
if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
dev->timer.data = (long) dev;
dev->timer.function = input_repeat_key;
if (!dev->rep[REP_DELAY])
dev->rep[REP_DELAY] = HZ/4;
if (!dev->rep[REP_PERIOD])
dev->rep[REP_PERIOD] = HZ/33;
dev->rep[REP_DELAY] = 250;
dev->rep[REP_PERIOD] = 33;
}
INIT_LIST_HEAD(&dev->h_list);
list_add_tail(&dev->node, &input_dev_list);
......
This diff is collapsed.
......@@ -28,6 +28,8 @@ MODULE_PARM(psmouse_noext, "1i");
MODULE_PARM_DESC(psmouse_noext, "Disable any protocol extensions. Useful for KVM switches.");
MODULE_PARM(psmouse_resolution, "i");
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_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
MODULE_PARM(psmouse_resetafter, "i");
......@@ -38,6 +40,7 @@ MODULE_LICENSE("GPL");
static int psmouse_noext;
int psmouse_resolution;
unsigned int psmouse_rate = 60;
int psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL;
unsigned int psmouse_resetafter;
......@@ -442,6 +445,19 @@ static void psmouse_set_resolution(struct psmouse *psmouse)
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.
*/
......@@ -450,15 +466,12 @@ static void psmouse_initialize(struct psmouse *psmouse)
{
unsigned char param[2];
/*
* We set the mouse report rate to a highest possible value.
* We try 100 first in case mouse fails to set 200.
* We set the mouse report rate.
*/
param[0] = 100;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
param[0] = 200;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
psmouse_set_rate(psmouse);
/*
* We also set the resolution and scaling.
......
......@@ -58,8 +58,6 @@ static struct serio i8042_kbd_port;
static struct serio i8042_aux_port;
static unsigned char i8042_initial_ctr;
static unsigned char i8042_ctr;
static unsigned char i8042_last_e0;
static unsigned char i8042_last_release;
static unsigned char i8042_mux_open;
struct timer_list i8042_timer;
......@@ -69,18 +67,6 @@ struct timer_list 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);
/*
......@@ -301,7 +287,7 @@ static struct i8042_values i8042_kbd_values = {
static struct serio i8042_kbd_port =
{
.type = SERIO_8042,
.type = SERIO_8042_XL,
.write = i8042_kbd_write,
.open = i8042_open,
.close = i8042_close,
......@@ -400,39 +386,10 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!i8042_kbd_values.exists)
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);
}
/* FIXME - was it really ours? */
return IRQ_HANDLED;
return IRQ_RETVAL(j);
}
/*
......@@ -511,8 +468,10 @@ static int __init i8042_controller_init(void)
* BIOSes.
*/
if (i8042_direct)
if (i8042_direct) {
i8042_ctr &= ~I8042_CTR_XLATE;
i8042_kbd_port.type = SERIO_8042;
}
/*
* Write CTR back.
......
......@@ -56,8 +56,6 @@ struct input_absinfo {
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
#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 EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */
......
......@@ -107,6 +107,7 @@ static __inline__ void serio_cleanup(struct serio *serio)
#define SERIO_HIL_MLC 0x03000000UL
#define SERIO_PC9800 0x04000000UL
#define SERIO_PS_PSTHRU 0x05000000UL
#define SERIO_8042_XL 0x06000000UL
#define SERIO_PROTO 0xFFUL
#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