Re: Input issues - key down with no key up

From: Vojtech Pavlik
Date: Fri Aug 15 2003 - 08:00:28 EST


On Fri, Aug 15, 2003 at 10:46:07PM +1000, Neil Brown wrote:
> On Friday August 15, vojtech@xxxxxxx wrote:
> >
> > My proposed solution is to do an input_report_key(pressed) immediately
> > followed by input_report_key(released) for these keys straight in
> > atkbd.c. Possibly based on some flag in the scancode->keycode table for
> > that scancode.
>
> Something like this?
>
> I use bit 32 in the keycode setting to mean "don't expect an 'up'
> event".
> It seems to work (though some of the keys actually generate 'down'
> events for both the down and up transitions, so it seems that the key
> is pressed twice.

Now that is suspicious. This smells of some scancode mangling happening.
Can you try with i8042_direct=1? And with both i8042_direct=1 and atkbd_set=3?

> I'm happy that that is just a buggy keyboard and I
> can work around it).
>
> NeilBrown
>
>
> ----------- Diffstat output ------------
> ./drivers/input/evdev.c | 13 ++++++++++---
> ./drivers/input/keyboard/atkbd.c | 7 +++++++
> ./include/linux/input.h | 1 +
> 3 files changed, 18 insertions(+), 3 deletions(-)
>
> diff ./drivers/input/evdev.c~current~ ./drivers/input/evdev.c
> --- ./drivers/input/evdev.c~current~ 2003-08-15 21:31:47.000000000 +1000
> +++ ./drivers/input/evdev.c 2003-08-15 21:35:00.000000000 +1000
> @@ -233,15 +233,22 @@ static int evdev_ioctl(struct inode *ino
> case EVIOCGKEYCODE:
> if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
> if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
> - if (put_user(INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT;
> + u = (dev->keycode_noup && test_bit(t, dev->keycode_noup)) ? (1<<31) : 0;
> + if (put_user(u | INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT;
> return 0;
>
> case EVIOCSKEYCODE:
> if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
> if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
> u = INPUT_KEYCODE(dev, t);
> - if (get_user(INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT;
> -
> + if (get_user(i, ((int *) arg) + 1)) return -EFAULT;
> + INPUT_KEYCODE(dev, t) = i;
> + if (dev->keycode_noup) {
> + if (i & (1<<31))
> + set_bit(t, dev->keycode_noup);
> + else
> + clear_bit(t, dev->keycode_noup);
> + }
> for (i = 0; i < dev->keycodemax; i++)
> if(INPUT_KEYCODE(dev, t) == u) break;
> if (i == dev->keycodemax) clear_bit(u, dev->keybit);
>
> diff ./drivers/input/keyboard/atkbd.c~current~ ./drivers/input/keyboard/atkbd.c
> --- ./drivers/input/keyboard/atkbd.c~current~ 2003-08-15 21:35:00.000000000 +1000
> +++ ./drivers/input/keyboard/atkbd.c 2003-08-15 22:12:50.000000000 +1000
> @@ -112,6 +112,7 @@ static unsigned char atkbd_set3_keycode[
>
> struct atkbd {
> unsigned char keycode[512];
> + unsigned long keycode_noup[NBITS(512)];
> struct input_dev dev;
> struct serio *serio;
> char name[64];
> @@ -198,6 +199,10 @@ static irqreturn_t atkbd_interrupt(struc
> input_regs(&atkbd->dev, regs);
> input_report_key(&atkbd->dev, atkbd->keycode[code], !atkbd->release);
> input_sync(&atkbd->dev);
> + if (!atkbd->release && test_bit(code, atkbd->keycode_noup)) {
> + input_report_key(&atkbd->dev, atkbd->keycode[code], 0);
> + input_sync(&atkbd->dev);
> + }
> }
>
> atkbd->release = 0;
> @@ -512,6 +517,7 @@ static void atkbd_connect(struct serio *
> atkbd->dev.keycode = atkbd->keycode;
> atkbd->dev.keycodesize = sizeof(unsigned char);
> atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
> + atkbd->dev.keycode_noup = atkbd->keycode_noup;
> atkbd->dev.event = atkbd_event;
> atkbd->dev.private = atkbd;
>
> @@ -549,6 +555,7 @@ static void atkbd_connect(struct serio *
> memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
> else
> memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
> + memset(atkbd->keycode_noup, 0, sizeof(atkbd->keycode_noup));
>
> atkbd->dev.name = atkbd->name;
> atkbd->dev.phys = atkbd->phys;
>
> diff ./include/linux/input.h~current~ ./include/linux/input.h
> --- ./include/linux/input.h~current~ 2003-08-15 21:31:47.000000000 +1000
> +++ ./include/linux/input.h 2003-08-15 21:35:00.000000000 +1000
> @@ -778,6 +778,7 @@ struct input_dev {
> unsigned int keycodemax;
> unsigned int keycodesize;
> void *keycode;
> + unsigned long *keycode_noup;
>
> unsigned int repeat_key;
> struct timer_list timer;

--
Vojtech Pavlik
SuSE Labs, SuSE CR
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/