aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard/atkbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/keyboard/atkbd.c')
-rw-r--r--drivers/input/keyboard/atkbd.c91
1 files changed, 72 insertions, 19 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index b39c5b31e620..4a95adc4cc78 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -19,7 +19,6 @@
19 19
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <linux/slab.h> 22#include <linux/slab.h>
24#include <linux/interrupt.h> 23#include <linux/interrupt.h>
25#include <linux/init.h> 24#include <linux/init.h>
@@ -28,6 +27,7 @@
28#include <linux/workqueue.h> 27#include <linux/workqueue.h>
29#include <linux/libps2.h> 28#include <linux/libps2.h>
30#include <linux/mutex.h> 29#include <linux/mutex.h>
30#include <linux/dmi.h>
31 31
32#define DRIVER_DESC "AT and PS/2 keyboard driver" 32#define DRIVER_DESC "AT and PS/2 keyboard driver"
33 33
@@ -201,6 +201,7 @@ struct atkbd {
201 201
202 unsigned short id; 202 unsigned short id;
203 unsigned char keycode[512]; 203 unsigned char keycode[512];
204 DECLARE_BITMAP(force_release_mask, 512);
204 unsigned char set; 205 unsigned char set;
205 unsigned char translated; 206 unsigned char translated;
206 unsigned char extra; 207 unsigned char extra;
@@ -225,6 +226,11 @@ struct atkbd {
225 unsigned long event_mask; 226 unsigned long event_mask;
226}; 227};
227 228
229/*
230 * System-specific ketymap fixup routine
231 */
232static void (*atkbd_platform_fixup)(struct atkbd *);
233
228static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, 234static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
229 ssize_t (*handler)(struct atkbd *, char *)); 235 ssize_t (*handler)(struct atkbd *, char *));
230static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, 236static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
@@ -349,7 +355,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
349 struct atkbd *atkbd = serio_get_drvdata(serio); 355 struct atkbd *atkbd = serio_get_drvdata(serio);
350 struct input_dev *dev = atkbd->dev; 356 struct input_dev *dev = atkbd->dev;
351 unsigned int code = data; 357 unsigned int code = data;
352 int scroll = 0, hscroll = 0, click = -1, add_release_event = 0; 358 int scroll = 0, hscroll = 0, click = -1;
353 int value; 359 int value;
354 unsigned char keycode; 360 unsigned char keycode;
355 361
@@ -414,14 +420,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
414 "Some program might be trying access hardware directly.\n", 420 "Some program might be trying access hardware directly.\n",
415 data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); 421 data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
416 goto out; 422 goto out;
417 case ATKBD_RET_HANGEUL:
418 case ATKBD_RET_HANJA:
419 /*
420 * These keys do not report release and thus need to be
421 * flagged properly
422 */
423 add_release_event = 1;
424 break;
425 case ATKBD_RET_ERR: 423 case ATKBD_RET_ERR:
426 atkbd->err_count++; 424 atkbd->err_count++;
427#ifdef ATKBD_DEBUG 425#ifdef ATKBD_DEBUG
@@ -491,7 +489,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
491 input_event(dev, EV_KEY, keycode, value); 489 input_event(dev, EV_KEY, keycode, value);
492 input_sync(dev); 490 input_sync(dev);
493 491
494 if (value && add_release_event) { 492 if (value && test_bit(code, atkbd->force_release_mask)) {
495 input_report_key(dev, keycode, 0); 493 input_report_key(dev, keycode, 0);
496 input_sync(dev); 494 input_sync(dev);
497 } 495 }
@@ -824,7 +822,6 @@ static void atkbd_disconnect(struct serio *serio)
824 atkbd_disable(atkbd); 822 atkbd_disable(atkbd);
825 823
826 /* make sure we don't have a command in flight */ 824 /* make sure we don't have a command in flight */
827 synchronize_sched(); /* Allow atkbd_interrupt()s to complete. */
828 flush_scheduled_work(); 825 flush_scheduled_work();
829 826
830 sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); 827 sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
@@ -834,6 +831,22 @@ static void atkbd_disconnect(struct serio *serio)
834 kfree(atkbd); 831 kfree(atkbd);
835} 832}
836 833
834/*
835 * Most special keys (Fn+F?) on Dell Latitudes do not generate release
836 * events so we have to do it ourselves.
837 */
838static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd)
839{
840 const unsigned int forced_release_keys[] = {
841 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93,
842 };
843 int i;
844
845 if (atkbd->set == 2)
846 for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
847 __set_bit(forced_release_keys[i],
848 atkbd->force_release_mask);
849}
837 850
838/* 851/*
839 * atkbd_set_keycode_table() initializes keyboard's keycode table 852 * atkbd_set_keycode_table() initializes keyboard's keycode table
@@ -842,17 +855,20 @@ static void atkbd_disconnect(struct serio *serio)
842 855
843static void atkbd_set_keycode_table(struct atkbd *atkbd) 856static void atkbd_set_keycode_table(struct atkbd *atkbd)
844{ 857{
858 unsigned int scancode;
845 int i, j; 859 int i, j;
846 860
847 memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); 861 memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
862 bitmap_zero(atkbd->force_release_mask, 512);
848 863
849 if (atkbd->translated) { 864 if (atkbd->translated) {
850 for (i = 0; i < 128; i++) { 865 for (i = 0; i < 128; i++) {
851 atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; 866 scancode = atkbd_unxlate_table[i];
852 atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80]; 867 atkbd->keycode[i] = atkbd_set2_keycode[scancode];
868 atkbd->keycode[i | 0x80] = atkbd_set2_keycode[scancode | 0x80];
853 if (atkbd->scroll) 869 if (atkbd->scroll)
854 for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++) 870 for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++)
855 if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j].set2) 871 if ((scancode | 0x80) == atkbd_scroll_keys[j].set2)
856 atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode; 872 atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
857 } 873 }
858 } else if (atkbd->set == 3) { 874 } else if (atkbd->set == 3) {
@@ -861,12 +877,29 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd)
861 memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode)); 877 memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
862 878
863 if (atkbd->scroll) 879 if (atkbd->scroll)
864 for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++) 880 for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++) {
865 atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode; 881 scancode = atkbd_scroll_keys[i].set2;
882 atkbd->keycode[scancode] = atkbd_scroll_keys[i].keycode;
883 }
866 } 884 }
867 885
868 atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL)] = KEY_HANGUEL; 886/*
869 atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA)] = KEY_HANJA; 887 * HANGEUL and HANJA keys do not send release events so we need to
888 * generate such events ourselves
889 */
890 scancode = atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL);
891 atkbd->keycode[scancode] = KEY_HANGEUL;
892 __set_bit(scancode, atkbd->force_release_mask);
893
894 scancode = atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA);
895 atkbd->keycode[scancode] = KEY_HANJA;
896 __set_bit(scancode, atkbd->force_release_mask);
897
898/*
899 * Perform additional fixups
900 */
901 if (atkbd_platform_fixup)
902 atkbd_platform_fixup(atkbd);
870} 903}
871 904
872/* 905/*
@@ -1401,9 +1434,29 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf)
1401 return sprintf(buf, "%lu\n", atkbd->err_count); 1434 return sprintf(buf, "%lu\n", atkbd->err_count);
1402} 1435}
1403 1436
1437static int __init atkbd_setup_fixup(const struct dmi_system_id *id)
1438{
1439 atkbd_platform_fixup = id->driver_data;
1440 return 0;
1441}
1442
1443static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
1444 {
1445 .ident = "Dell Latitude series",
1446 .matches = {
1447 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
1448 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
1449 },
1450 .callback = atkbd_setup_fixup,
1451 .driver_data = atkbd_latitude_keymap_fixup,
1452 },
1453 { }
1454};
1404 1455
1405static int __init atkbd_init(void) 1456static int __init atkbd_init(void)
1406{ 1457{
1458 dmi_check_system(atkbd_dmi_quirk_table);
1459
1407 return serio_register_driver(&atkbd_drv); 1460 return serio_register_driver(&atkbd_drv);
1408} 1461}
1409 1462