Commit 46716383 authored by Vojtech Pavlik's avatar Vojtech Pavlik

[PATCH] Fixes for keyboard 2.4 compatibility

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.
parent f5af7c4c
......@@ -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) {
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) {
......
......@@ -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,14 +80,10 @@ 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] = {
......@@ -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,6 +191,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd->resend = 0;
#endif
if (!atkbd->ack)
switch (code) {
case ATKBD_RET_ACK:
atkbd->ack = 1;
......@@ -193,36 +201,25 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
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->cmdcnt) {
atkbd->cmdbuf[--atkbd->cmdcnt] = code;
goto out;
}
if (atkbd->cmdcnt)
break;
if (atkbd->translated) {
code = atkbd_unxlate_table[code & 0x7f];
atkbd->release = 1;
} while (0);
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->cmdcnt) {
atkbd->cmdbuf[--atkbd->cmdcnt] = code;
goto out;
if (!atkbd->emul &&
(code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
atkbd->bat_xl = !atkbd->release;
}
switch (code) {
......@@ -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,
......
......@@ -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. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment