]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Fixes for keyboard 2.4 compatibility
authorVojtech Pavlik <vojtech@suse.cz>
Thu, 18 Dec 2003 13:33:58 +0000 (05:33 -0800)
committerVojtech Pavlik <vojtech@suse.cz>
Thu, 18 Dec 2003 13:33:58 +0000 (05:33 -0800)
I have two patches I'd like to get tested by a wider audience before
sending them to Linus for the 2.6 tree.

The first one fixes an issue in current 2.6-test with AT keyboard repeat
rate setting, the second one makes setkeycodes/getkeycodes work the same
as 2.4, so that people can keep their setups. It also fixes japanese and
korean key handling.

drivers/char/keyboard.c
drivers/input/keyboard/atkbd.c
include/linux/keyboard.h

index 65594dad55fd7e07830e7a59ba231ec7486b50bb..b4c683f0e37c0d943326c4f391c0dc75f7f67cc9 100644 (file)
@@ -941,16 +941,16 @@ static unsigned short x86_keycodes[256] =
         32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
         48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
         64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-        80, 81, 82, 83, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90,
-       284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
-       367,288,302,304,350, 92,334,512,116,377,109,111,373,347,348,349,
-       360, 93, 94, 95, 98,376,100,101,321,316,354,286,289,102,351,355,
+        80, 81, 82, 83, 84, 93, 86, 87, 88, 94, 95, 85,259,375,260, 90,
+       284,285,309,311,312, 91,327,328,329,331,333,335,336,337,338,339,
+       367,288,302,304,350, 89,334,326,116,377,109,111,126,347,348,349,
+       360,261,262,263,298,376,100,101,321,316,373,286,289,102,351,355,
        103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
-       291,108,381,281,290,272,292,305,280, 99,112,257,258,359,270,114,
-       118,117,125,374,379,115,112,125,121,123,264,265,266,267,268,269,
-       271,273,276,277,278,282,283,295,296,297,299,300,301,293,303,307,
-       308,310,313,314,315,317,318,319,320,357,322,323,324,325,326,330,
-       332,340,365,342,343,344,345,346,356,113,341,368,369,370,371,372 };
+       291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
+       264,117,271,374,379,115,125,273,121,123, 92,265,266,267,268,269,
+       120,119,118,277,278,282,283,295,296,297,299,300,301,293,303,307,
+       308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
+       332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
 
 #ifdef CONFIG_MAC_EMUMOUSEBTN
 extern int mac_hid_mouse_emulate_buttons(int, int, int);
@@ -972,11 +972,18 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
        if (keycode > 255 || !x86_keycodes[keycode])
                return -1; 
 
-       if (keycode == KEY_PAUSE) {
-               put_queue(vc, 0xe1);
-               put_queue(vc, 0x1d | up_flag);
-               put_queue(vc, 0x45 | up_flag);
-               return 0;
+       switch (keycode) {
+               case KEY_PAUSE:
+                       put_queue(vc, 0xe1);
+                       put_queue(vc, 0x1d | up_flag);
+                       put_queue(vc, 0x45 | up_flag);
+                       return 0;
+               case KEY_LANG1:
+                       if (!up_flag) put_queue(vc, 0xf1);
+                       return 0;
+               case KEY_LANG2:
+                       if (!up_flag) put_queue(vc, 0xf2);
+                       return 0;
        } 
 
        if (keycode == KEY_SYSRQ && sysrq_alt) {
index 9c9dd3e3d2b94d9fffd0189978d9d5d2a4dd5b2e..25720d301bac6776a7612974675ff315cf2d0339 100644 (file)
@@ -48,33 +48,30 @@ static int atkbd_softrepeat;
  */
 
 static unsigned char atkbd_set2_keycode[512] = {
-         0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41, 85,
-         0, 56, 42,182, 29, 16,  2, 89,  0,  0, 44, 31, 30, 17,  3, 90,
-         0, 46, 45, 32, 18,  5,  4, 91, 90, 57, 47, 33, 20, 19,  6,  0,
-        91, 49, 48, 35, 34, 21,  7,  0,  0,  0, 50, 36, 22,  8,  9,  0,
+
+         0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
+         0, 56, 42,182, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
+         0, 46, 45, 32, 18,  5,  4,186,  0, 57, 47, 33, 20, 19,  6, 85,
+         0, 49, 48, 35, 34, 21,  7, 89,  0,  0, 50, 36, 22,  8,  9, 90,
          0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
-       122, 89, 40,120, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0,  0,
-        85, 86, 90, 91, 92, 93, 14, 94, 95, 79,183, 75, 71,121,  0,123,
+         0,181, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0,194,
+         0, 86,193,192,184,  0, 14,185,  0, 79,182, 75, 71,124,  0,  0,
         82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
-         0,  0,  0, 65, 99,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+
          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,255,
-         0,  0, 92, 90, 85,  0,137,  0,  0,  0,  0, 91, 89,144,115,  0,
-       217,100,255,  0, 97,165,164,  0,156,  0,  0,140,115,  0,  0,125,
-       173,114,  0,113,152,163,151,126,128,166,  0,140,  0,147,  0,127,
-       159,167,115,160,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
-       157,  0,114,166,168,  0,  0,213,155,  0, 98,113,  0,163,  0,138,
-       226,  0,  0,  0,  0,  0,153,140,  0,255, 96,  0,  0,  0,143,  0,
-       133,  0,116,  0,143,  0,174,133,  0,107,  0,105,102,  0,  0,112,
-       110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119
+       217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
+       173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
+       159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
+       157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
+       226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
+       110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
+
+         0,  0,  0, 65, 99,
 };
 
 static unsigned char atkbd_set3_keycode[512] = {
+
          0,  0,  0,  0,  0,  0,  0, 59,  1,138,128,129,130, 15, 41, 60,
        131, 29, 42, 86, 58, 16,  2, 61,133, 56, 44, 31, 30, 17,  3, 62,
        134, 46, 45, 32, 18,  5,  4, 63,135, 57, 47, 33, 20, 19,  6, 64,
@@ -83,25 +80,21 @@ static unsigned char atkbd_set3_keycode[512] = {
        113,114, 40, 84, 26, 13, 87, 99, 97, 54, 28, 27, 43, 84, 88, 70,
        108,105,119,103,111,107, 14,110,  0, 79,106, 75, 71,109,102,104,
         82, 83, 80, 76, 77, 72, 69, 98,  0, 96, 81,  0, 78, 73, 55, 85,
+
         89, 90, 91, 92, 74,185,184,182,  0,  0,  0,125,126,127,112,  0,
          0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
-       148,149,147,140,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,255
+       148,149,147,140
 };
 
 static unsigned char atkbd_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
+          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
 };
 
 #define ATKBD_CMD_SETLEDS      0x10ed
@@ -125,6 +118,9 @@ static unsigned char atkbd_unxlate_table[128] = {
 #define ATKBD_RET_EMULX                0x80
 #define ATKBD_RET_EMUL1                0xe1
 #define ATKBD_RET_RELEASE      0xf0
+#define ATKBD_RET_HANGUEL      0xf1
+#define ATKBD_RET_HANJA                0xf2
+#define ATKBD_RET_ERR          0xff
 
 #define ATKBD_KEY_UNKNOWN        0
 #define ATKBD_KEY_NULL         255
@@ -156,6 +152,17 @@ struct atkbd {
        unsigned long time;
 };
 
+static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value)
+{
+       input_regs(dev, regs);
+       if (value == 3) {
+               input_report_key(dev, code, 1);
+               input_report_key(dev, code, 0);
+       } else
+               input_event(dev, EV_KEY, code, value);
+       input_sync(dev);
+}
+
 /*
  * atkbd_interrupt(). Here takes place processing of data received from
  * the keyboard into events.
@@ -184,47 +191,37 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
                atkbd->resend = 0;
 #endif
 
-       switch (code) {
-               case ATKBD_RET_ACK:
-                       atkbd->ack = 1;
-                       goto out;
-               case ATKBD_RET_NAK:
-                       atkbd->ack = -1;
-                       goto out;
-       }
-
-       if (atkbd->translated) do {
-
-               if (atkbd->emul != 1) {
-                       if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1)
-                               break;
-                       if (code == ATKBD_RET_BAT) {
-                               if (!atkbd->bat_xl)
-                                       break;
-                               atkbd->bat_xl = 0;
-                       }
-                       if (code == (ATKBD_RET_BAT & 0x7f))
-                               atkbd->bat_xl = 1;
-               }
-
-               if (code < 0x80) {
-                       code = atkbd_unxlate_table[code];
-                       break;
+       if (!atkbd->ack)
+               switch (code) {
+                       case ATKBD_RET_ACK:
+                               atkbd->ack = 1;
+                               goto out;
+                       case ATKBD_RET_NAK:
+                               atkbd->ack = -1;
+                               goto out;
                }
 
-               if (atkbd->cmdcnt)
-                       break;
-
-               code = atkbd_unxlate_table[code & 0x7f];
-               atkbd->release = 1;
-
-       } while (0);
-
        if (atkbd->cmdcnt) {
                atkbd->cmdbuf[--atkbd->cmdcnt] = code;
                goto out;
        }
 
+       if (atkbd->translated) {
+
+               if (atkbd->emul ||
+                   !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
+                     code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
+                     code == ATKBD_RET_ERR ||
+                    (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
+                       atkbd->release = code >> 7;
+                       code &= 0x7f;
+               }
+
+               if (!atkbd->emul &&
+                    (code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
+                       atkbd->bat_xl = !atkbd->release;
+       }
+
        switch (code) {
                case ATKBD_RET_BAT:
                        serio_rescan(atkbd->serio);
@@ -238,22 +235,33 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
                case ATKBD_RET_RELEASE:
                        atkbd->release = 1;
                        goto out;
+               case ATKBD_RET_HANGUEL:
+                       atkbd_report_key(&atkbd->dev, regs, KEY_LANG1, 3);
+                       goto out;
+               case ATKBD_RET_HANJA:
+                       atkbd_report_key(&atkbd->dev, regs, KEY_LANG2, 3);
+                       goto out;
+               case ATKBD_RET_ERR:
+                       printk(KERN_WARNING "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
+                       goto out;
        }
 
+       if (atkbd->set != 3)
+               code = (code & 0x7f) | ((code & 0x80) << 1);
        if (atkbd->emul) {
                if (--atkbd->emul)
                        goto out;
-               code |= 0x100;
+               code |= (atkbd->set != 3) ? 0x80 : 0x100;
        }
 
        switch (atkbd->keycode[code]) {
                case ATKBD_KEY_NULL:
                        break;
                case ATKBD_KEY_UNKNOWN:
-                       printk(KERN_WARNING "atkbd.c: Unknown key %s (%s set %d, code %#x, data %#x, on %s).\n",
+                       printk(KERN_WARNING "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n",
                                atkbd->release ? "released" : "pressed",
                                atkbd->translated ? "translated" : "raw", 
-                               atkbd->set, code, data, serio->phys);
+                               atkbd->set, code, serio->phys);
                        break;
                default:
                        value = atkbd->release ? 0 :
@@ -273,9 +281,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
                                        break;
                        }
 
-                       input_regs(&atkbd->dev, regs);
-                       input_event(&atkbd->dev, EV_KEY, atkbd->keycode[code], value);
-                       input_sync(&atkbd->dev);
+                       atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
        }
 
        atkbd->release = 0;
@@ -369,10 +375,11 @@ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command)
 static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
        struct atkbd *atkbd = dev->private;
-       struct { int p; u8 v; } period[] =      
-               { {30, 0x00}, {25, 0x02}, {20, 0x04}, {15, 0x08}, {10, 0x0c}, {7, 0x10}, {5, 0x14}, {0, 0x14} };
-       struct { int d; u8 v; } delay[] =
-               { {1000, 0x60}, {750, 0x40}, {500, 0x20}, {250, 0x00}, {0, 0x00} };
+       const short period[32] =
+               { 33,  37,  42,  46,  50,  54,  58,  63,  67,  75,  83,  92, 100, 109, 116, 125,
+                133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
+       const short delay[4] =
+               { 250, 500, 750, 1000 };
        char param[2];
        int i, j;
 
@@ -406,11 +413,11 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
                        if (atkbd_softrepeat) return 0;
 
                        i = j = 0;
-                       while (period[i].p > dev->rep[REP_PERIOD]) i++;
-                       while (delay[j].d > dev->rep[REP_DELAY]) j++;
-                       dev->rep[REP_PERIOD] = period[i].p;
-                       dev->rep[REP_DELAY] = delay[j].d;
-                       param[0] = period[i].v | delay[j].v;
+                       while (i < 32 && period[i] < dev->rep[REP_PERIOD]) i++;
+                       while (j < 4 && delay[j] < dev->rep[REP_DELAY]) j++;
+                       dev->rep[REP_PERIOD] = period[i];
+                       dev->rep[REP_DELAY] = delay[j];
+                       param[0] = i | (j << 5);
                        atkbd_command(atkbd, param, ATKBD_CMD_SETREP);
 
                        return 0;
@@ -623,6 +630,7 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
                atkbd->dev.rep[REP_PERIOD] = 33;
        }
 
+       atkbd->ack = 1;
        atkbd->serio = serio;
 
        init_input_dev(&atkbd->dev);
@@ -665,16 +673,22 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
 
        sprintf(atkbd->phys, "%s/input0", serio->phys);
 
-       if (atkbd->set == 3)
-               memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
-       else
+       if (atkbd->translated) {
+               for (i = 0; i < 128; i++) {
+                       atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
+                       atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
+               }
+       } else if (atkbd->set == 2) {
                memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
+       } else {
+               memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
+       }
 
        atkbd->dev.name = atkbd->name;
        atkbd->dev.phys = atkbd->phys;
        atkbd->dev.id.bustype = BUS_I8042;
        atkbd->dev.id.vendor = 0x0001;
-       atkbd->dev.id.product = atkbd->set;
+       atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set;
        atkbd->dev.id.version = atkbd->id;
 
        for (i = 0; i < 512; i++)
@@ -686,7 +700,6 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
        printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
 }
 
-
 static struct serio_dev atkbd_dev = {
        .interrupt =    atkbd_interrupt,
        .connect =      atkbd_connect,
index a7fcf94e5a0dd01be84d0fdbe3d71259f4d4c31e..f9c6ad75213a907e3e7760f1b6238f74c0bb1a6e 100644 (file)
@@ -2,7 +2,6 @@
 #define __LINUX_KEYBOARD_H
 
 #include <linux/wait.h>
-#include <linux/input.h>
 
 #define KG_SHIFT       0
 #define KG_CTRL                2
@@ -17,7 +16,7 @@
 
 #define NR_SHIFT       9
 
-#define NR_KEYS                (KEY_MAX+1)
+#define NR_KEYS                255
 #define MAX_NR_KEYMAPS 256
 /* This means 128Kb if all keymaps are allocated. Only the superuser
        may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */