diff options
author | Jamie Lentin <jamie@lentin.co.uk> | 2009-10-20 17:36:49 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-10-22 02:48:39 -0400 |
commit | e57130698fe3dd2b7d617d90bbf86474473cb40c (patch) | |
tree | 3cee0a8bf630f7f117b06b872bfd5e4876eb6486 | |
parent | 3776989d2339c58ff8d8421e754603f186d7439b (diff) |
Input: atkbd - add a quirk for OQO 01+ multimedia keys
OQO 01+ multimedia keys produce 6x on press, e0 6x upon release.
As a result, Linux thinks that another key has been pressed (or is
repeating), when it is actually a release of the same key. Mangle the
release scancode when running on OQO so that driver recognizes it as
such.
Since the device does not have external PS/2 ports mangling is safe
since there is no chance that an external keyboard is connected.
Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 271c0b7045c3..e9acbe0c9e2a 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -233,6 +233,7 @@ struct atkbd { | |||
233 | */ | 233 | */ |
234 | static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); | 234 | static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); |
235 | static void *atkbd_platform_fixup_data; | 235 | static void *atkbd_platform_fixup_data; |
236 | static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int); | ||
236 | 237 | ||
237 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, | 238 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, |
238 | ssize_t (*handler)(struct atkbd *, char *)); | 239 | ssize_t (*handler)(struct atkbd *, char *)); |
@@ -393,6 +394,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
393 | 394 | ||
394 | input_event(dev, EV_MSC, MSC_RAW, code); | 395 | input_event(dev, EV_MSC, MSC_RAW, code); |
395 | 396 | ||
397 | if (atkbd_platform_scancode_fixup) | ||
398 | code = atkbd_platform_scancode_fixup(atkbd, code); | ||
399 | |||
396 | if (atkbd->translated) { | 400 | if (atkbd->translated) { |
397 | 401 | ||
398 | if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) { | 402 | if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) { |
@@ -923,6 +927,22 @@ static unsigned int atkbd_volume_forced_release_keys[] = { | |||
923 | }; | 927 | }; |
924 | 928 | ||
925 | /* | 929 | /* |
930 | * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas | ||
931 | * they should be generating e4-e6 (0x80 | code). | ||
932 | */ | ||
933 | static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd, | ||
934 | unsigned int code) | ||
935 | { | ||
936 | if (atkbd->translated && atkbd->emul == 1 && | ||
937 | (code == 0x64 || code == 0x65 || code == 0x66)) { | ||
938 | atkbd->emul = 0; | ||
939 | code |= 0x80; | ||
940 | } | ||
941 | |||
942 | return code; | ||
943 | } | ||
944 | |||
945 | /* | ||
926 | * atkbd_set_keycode_table() initializes keyboard's keycode table | 946 | * atkbd_set_keycode_table() initializes keyboard's keycode table |
927 | * according to the selected scancode set | 947 | * according to the selected scancode set |
928 | */ | 948 | */ |
@@ -1527,6 +1547,13 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id) | |||
1527 | return 0; | 1547 | return 0; |
1528 | } | 1548 | } |
1529 | 1549 | ||
1550 | static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id) | ||
1551 | { | ||
1552 | atkbd_platform_scancode_fixup = id->driver_data; | ||
1553 | |||
1554 | return 0; | ||
1555 | } | ||
1556 | |||
1530 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | 1557 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { |
1531 | { | 1558 | { |
1532 | .ident = "Dell Laptop", | 1559 | .ident = "Dell Laptop", |
@@ -1663,6 +1690,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1663 | .callback = atkbd_setup_forced_release, | 1690 | .callback = atkbd_setup_forced_release, |
1664 | .driver_data = atkdb_soltech_ta12_forced_release_keys, | 1691 | .driver_data = atkdb_soltech_ta12_forced_release_keys, |
1665 | }, | 1692 | }, |
1693 | { | ||
1694 | .ident = "OQO Model 01+", | ||
1695 | .matches = { | ||
1696 | DMI_MATCH(DMI_SYS_VENDOR, "OQO"), | ||
1697 | DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), | ||
1698 | }, | ||
1699 | .callback = atkbd_setup_scancode_fixup, | ||
1700 | .driver_data = atkbd_oqo_01plus_scancode_fixup, | ||
1701 | }, | ||
1666 | { } | 1702 | { } |
1667 | }; | 1703 | }; |
1668 | 1704 | ||