Re: Input issues - key down with no key up

From: Neil Brown
Date: Fri Aug 15 2003 - 07:52:13 EST


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. 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;
-
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/