patch-2.4.15 linux/drivers/char/hp_keyb.c
Next file: linux/drivers/char/hp_psaux.c
Previous file: linux/drivers/char/esp.c
Back to the patch index
Back to the overall index
- Lines: 520
- Date:
Fri Nov 9 14:01:21 2001
- Orig file:
v2.4.14/linux/drivers/char/hp_keyb.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.4.14/linux/drivers/char/hp_keyb.c linux/drivers/char/hp_keyb.c
@@ -0,0 +1,519 @@
+/*
+ * linux/drivers/char/hp_keyb.c
+ * helper-functions for the keyboard/psaux driver for HP-PARISC workstations
+ *
+ * based on pc_keyb.c by Geert Uytterhoeven & Martin Mares
+ *
+ * 2000/10/26 Debacker Xavier <debackex@esiee.fr>
+ * Marteau Thomas <marteaut@esiee.fr>
+ * Djoudi Malek <djoudim@esiee.fr>
+ * - fixed some keysym defines
+ *
+ * 2001/04/28 Debacker Xavier <debackex@esiee.fr>
+ * - scancode translation rewritten in handle_at_scancode()
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <linux/timer.h>
+#include <linux/random.h>
+#include <linux/ctype.h>
+#include <linux/kbd_ll.h>
+#include <linux/init.h>
+
+#include <asm/bitops.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#define KBD_REPORT_ERR
+#define KBD_REPORT_UNKN
+
+#define KBD_ESCAPEE0 0xe0 /* in */
+#define KBD_ESCAPEE1 0xe1 /* in */
+
+#define ESCE0(x) (0xe000|(x))
+#define ESCE1(x) (0xe100|(x))
+
+#define KBD_BAT 0xaa /* in */
+#define KBD_SETLEDS 0xed /* out */
+#define KBD_ECHO 0xee /* in/out */
+#define KBD_BREAK 0xf0 /* in */
+#define KBD_TYPRATEDLY 0xf3 /* out */
+#define KBD_SCANENABLE 0xf4 /* out */
+#define KBD_DEFDISABLE 0xf5 /* out */
+#define KBD_DEFAULT 0xf6 /* out */
+#define KBD_ACK 0xfa /* in */
+#define KBD_DIAGFAIL 0xfd /* in */
+#define KBD_RESEND 0xfe /* in/out */
+#define KBD_RESET 0xff /* out */
+
+#define CODE_BREAK 1
+#define CODE_ESCAPEE0 2
+#define CODE_ESCAPEE1 4
+#define CODE_ESCAPE12 8
+
+#define K_NONE 0x7f
+#define K_ESC 0x01
+#define K_F1 0x3b
+#define K_F2 0x3c
+#define K_F3 0x3d
+#define K_F4 0x3e
+#define K_F5 0x3f
+#define K_F6 0x40
+#define K_F7 0x41
+#define K_F8 0x42
+#define K_F9 0x43
+#define K_F10 0x44
+#define K_F11 0x57
+#define K_F12 0x58
+#define K_PRNT 0x54
+#define K_SCRL 0x46
+#define K_BRK 0x77
+#define K_AGR 0x29
+#define K_1 0x02
+#define K_2 0x03
+#define K_3 0x04
+#define K_4 0x05
+#define K_5 0x06
+#define K_6 0x07
+#define K_7 0x08
+#define K_8 0x09
+#define K_9 0x0a
+#define K_0 0x0b
+#define K_MINS 0x0c
+#define K_EQLS 0x0d
+#define K_BKSP 0x0e
+#define K_INS 0x6e
+#define K_HOME 0x66
+#define K_PGUP 0x68
+#define K_NUML 0x45
+#define KP_SLH 0x62
+#define KP_STR 0x37
+#define KP_MNS 0x4a
+#define K_TAB 0x0f
+#define K_Q 0x10
+#define K_W 0x11
+#define K_E 0x12
+#define K_R 0x13
+#define K_T 0x14
+#define K_Y 0x15
+#define K_U 0x16
+#define K_I 0x17
+#define K_O 0x18
+#define K_P 0x19
+#define K_LSBK 0x1a
+#define K_RSBK 0x1b
+#define K_ENTR 0x1c
+#define K_DEL 111
+#define K_END 0x6b
+#define K_PGDN 0x6d
+#define KP_7 0x47
+#define KP_8 0x48
+#define KP_9 0x49
+#define KP_PLS 0x4e
+#define K_CAPS 0x3a
+#define K_A 0x1e
+#define K_S 0x1f
+#define K_D 0x20
+#define K_F 0x21
+#define K_G 0x22
+#define K_H 0x23
+#define K_J 0x24
+#define K_K 0x25
+#define K_L 0x26
+#define K_SEMI 0x27
+#define K_SQOT 0x28
+#define K_HASH K_NONE
+#define KP_4 0x4b
+#define KP_5 0x4c
+#define KP_6 0x4d
+#define K_LSFT 0x2a
+#define K_BSLH 0x2b
+#define K_Z 0x2c
+#define K_X 0x2d
+#define K_C 0x2e
+#define K_V 0x2f
+#define K_B 0x30
+#define K_N 0x31
+#define K_M 0x32
+#define K_COMA 0x33
+#define K_DOT 0x34
+#define K_FSLH 0x35
+#define K_RSFT 0x36
+#define K_UP 0x67
+#define KP_1 0x4f
+#define KP_2 0x50
+#define KP_3 0x51
+#define KP_ENT 0x60
+#define K_LCTL 0x1d
+#define K_LALT 0x38
+#define K_SPCE 0x39
+#define K_RALT 0x64
+#define K_RCTL 0x61
+#define K_LEFT 0x69
+#define K_DOWN 0x6c
+#define K_RGHT 0x6a
+#define KP_0 0x52
+#define KP_DOT 0x53
+
+static unsigned char keycode_translate[256] =
+{
+/* 00 */ K_NONE, K_F9 , K_NONE, K_F5 , K_F3 , K_F1 , K_F2 , K_F12 ,
+/* 08 */ K_NONE, K_F10 , K_F8 , K_F6 , K_F4 , K_TAB , K_AGR , K_NONE,
+/* 10 */ K_NONE, K_LALT, K_LSFT, K_NONE, K_LCTL, K_Q , K_1 , K_NONE,
+/* 18 */ K_NONE, K_NONE, K_Z , K_S , K_A , K_W , K_2 , K_NONE,
+/* 20 */ K_NONE, K_C , K_X , K_D , K_E , K_4 , K_3 , K_NONE,
+/* 28 */ K_NONE, K_SPCE, K_V , K_F , K_T , K_R , K_5 , K_NONE,
+/* 30 */ K_NONE, K_N , K_B , K_H , K_G , K_Y , K_6 , K_NONE,
+/* 38 */ K_NONE, K_NONE, K_M , K_J , K_U , K_7 , K_8 , K_NONE,
+/* 40 */ K_NONE, K_COMA, K_K , K_I , K_O , K_0 , K_9 , K_NONE,
+/* 48 */ K_NONE, K_DOT , K_FSLH, K_L , K_SEMI, K_P , K_MINS, K_NONE,
+/* 50 */ K_NONE, K_NONE, K_SQOT, K_NONE, K_LSBK, K_EQLS, K_NONE, K_NONE,
+/* 58 */ K_CAPS, K_RSFT, K_ENTR, K_RSBK, K_NONE, K_BSLH, K_NONE, K_NONE,
+/* 60 */ K_NONE, K_HASH, K_NONE, K_NONE, K_NONE, K_NONE, K_BKSP, K_NONE,
+/* 68 */ K_NONE, KP_1 , K_NONE, KP_4 , KP_7 , K_NONE, K_NONE, K_NONE,
+/* 70 */ KP_0 , KP_DOT, KP_2 , KP_5 , KP_6 , KP_8 , K_ESC , K_NUML,
+/* 78 */ K_F11 , KP_PLS, KP_3 , KP_MNS, KP_STR, KP_9 , K_SCRL, K_PRNT,
+/* 80 */ K_NONE, K_NONE, K_NONE, K_F7 , K_NONE, K_NONE, K_NONE, K_NONE,
+/* 88 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* 90 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* 98 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* a0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* a8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* b0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* b8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* c0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* c8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* d0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* d8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* e0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* e8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* f0 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+/* f8 */ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, KBD_RESEND, K_NONE
+};
+
+/* ----- the following code stolen from pc_keyb.c */
+
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char hp_ps2kbd_sysrq_xlate[128] =
+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+ "\r\000/"; /* 0x60 - 0x6f */
+#endif
+
+/*
+ * Translation of escaped scancodes to keycodes.
+ * This is now user-settable.
+ * The keycodes 1-88,96-111,119 are fairly standard, and
+ * should probably not be changed - changing might confuse X.
+ * X also interprets scancode 0x5d (KEY_Begin).
+ *
+ * For 1-88 keycode equals scancode.
+ */
+
+#define E0_KPENTER 96
+#define E0_RCTRL 97
+#define E0_KPSLASH 98
+#define E0_PRSCR 99
+#define E0_RALT 100
+#define E0_BREAK 101 /* (control-pause) */
+#define E0_HOME 102
+#define E0_UP 103
+#define E0_PGUP 104
+#define E0_LEFT 105
+#define E0_RIGHT 106
+#define E0_END 107
+#define E0_DOWN 108
+#define E0_PGDN 109
+#define E0_INS 110
+#define E0_DEL 111
+
+#define E1_PAUSE 119
+
+/*
+ * The keycodes below are randomly located in 89-95,112-118,120-127.
+ * They could be thrown away (and all occurrences below replaced by 0),
+ * but that would force many users to use the `setkeycodes' utility, where
+ * they needed not before. It does not matter that there are duplicates, as
+ * long as no duplication occurs for any single keyboard.
+ */
+#define SC_LIM 89 /* 0x59 == 89 */
+
+#define FOCUS_PF1 85 /* actual code! */
+#define FOCUS_PF2 89
+#define FOCUS_PF3 90
+#define FOCUS_PF4 91
+#define FOCUS_PF5 92
+#define FOCUS_PF6 93
+#define FOCUS_PF7 94
+#define FOCUS_PF8 95
+#define FOCUS_PF9 120
+#define FOCUS_PF10 121
+#define FOCUS_PF11 122
+#define FOCUS_PF12 123
+
+#define JAP_86 124
+/* tfj@olivia.ping.dk:
+ * The four keys are located over the numeric keypad, and are
+ * labelled A1-A4. It's an rc930 keyboard, from
+ * Regnecentralen/RC International, Now ICL.
+ * Scancodes: 59, 5a, 5b, 5c.
+ */
+#define RGN1 124
+#define RGN2 125
+#define RGN3 126
+#define RGN4 127
+
+static unsigned char high_keys[128 - SC_LIM] = {
+ RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
+ 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
+ 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
+ FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
+ FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
+};
+
+/* BTC */
+#define E0_MACRO 112
+/* LK450 */
+#define E0_F13 113
+#define E0_F14 114
+#define E0_HELP 115
+#define E0_DO 116
+#define E0_F17 117
+#define E0_KPMINPLUS 118
+/*
+ * My OmniKey generates e0 4c for the "OMNI" key and the
+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
+ */
+#define E0_OK 124
+/*
+ * New microsoft keyboard is rumoured to have
+ * e0 5b (left window button), e0 5c (right window button),
+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
+ * [or: Windows_L, Windows_R, TaskMan]
+ */
+#define E0_MSLW 125
+#define E0_MSRW 126
+#define E0_MSTM 127
+
+static unsigned char e0_keys[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
+ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
+ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
+ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
+ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
+ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
+ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
+ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
+ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
+};
+
+int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+ if (scancode < SC_LIM || scancode > 255 || keycode > 127)
+ return -EINVAL;
+ if (scancode < 128)
+ high_keys[scancode - SC_LIM] = keycode;
+ else
+ e0_keys[scancode - 128] = keycode;
+ return 0;
+}
+
+int pckbd_getkeycode(unsigned int scancode)
+{
+ return
+ (scancode < SC_LIM || scancode > 255) ? -EINVAL :
+ (scancode < 128) ? high_keys[scancode - SC_LIM] :
+ e0_keys[scancode - 128];
+}
+
+int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode)
+{
+ static int prev_scancode;
+
+ /* special prefix scancodes.. */
+ if (scancode == 0xe0 || scancode == 0xe1) {
+ prev_scancode = scancode;
+ return 0;
+ }
+
+ /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
+ if (scancode == 0x00 || scancode == 0xff) {
+ prev_scancode = 0;
+ return 0;
+ }
+ scancode &= 0x7f;
+
+ if (prev_scancode) {
+ /*
+ * usually it will be 0xe0, but a Pause key generates
+ * e1 1d 45 e1 9d c5 when pressed, and nothing when released
+ */
+ if (prev_scancode != 0xe0) {
+ if (prev_scancode == 0xe1 && scancode == 0x1d) {
+ prev_scancode = 0x100;
+ return 0;
+ } else if (prev_scancode == 0x100 && scancode == 0x45) {
+ *keycode = E1_PAUSE;
+ prev_scancode = 0;
+ } else {
+#ifdef KBD_REPORT_UNKN
+ if (!raw_mode)
+ printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
+#endif
+ prev_scancode = 0;
+ return 0;
+ }
+ } else {
+ prev_scancode = 0;
+ /*
+ * The keyboard maintains its own internal caps lock and
+ * num lock statuses. In caps lock mode E0 AA precedes make
+ * code and E0 2A follows break code. In num lock mode,
+ * E0 2A precedes make code and E0 AA follows break code.
+ * We do our own book-keeping, so we will just ignore these.
+ */
+ /*
+ * For my keyboard there is no caps lock mode, but there are
+ * both Shift-L and Shift-R modes. The former mode generates
+ * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
+ * So, we should also ignore the latter. - aeb@cwi.nl
+ */
+ if (scancode == 0x2a || scancode == 0x36)
+ return 0;
+
+ if (e0_keys[scancode])
+ *keycode = e0_keys[scancode];
+ else {
+#ifdef KBD_REPORT_UNKN
+ if (!raw_mode)
+ printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
+ scancode);
+#endif
+ return 0;
+ }
+ }
+ } else if (scancode >= SC_LIM) {
+ /* This happens with the FOCUS 9000 keyboard
+ Its keys PF1..PF12 are reported to generate
+ 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
+ Moreover, unless repeated, they do not generate
+ key-down events, so we have to zero up_flag below */
+ /* Also, Japanese 86/106 keyboards are reported to
+ generate 0x73 and 0x7d for \ - and \ | respectively. */
+ /* Also, some Brazilian keyboard is reported to produce
+ 0x73 and 0x7e for \ ? and KP-dot, respectively. */
+
+ *keycode = high_keys[scancode - SC_LIM];
+
+ if (!*keycode) {
+ if (!raw_mode) {
+#ifdef KBD_REPORT_UNKN
+ printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
+ " - ignored\n", scancode);
+#endif
+ }
+ return 0;
+ }
+ } else
+ *keycode = scancode;
+
+ return 1;
+}
+
+/* ----- end of stolen part ------ */
+
+
+void kbd_reset_setup(void)
+{
+}
+
+void handle_at_scancode(int keyval)
+{
+ static int brk;
+ static int esc0;
+ static int esc1;
+ int scancode = 0;
+
+ switch (keyval) {
+ case KBD_BREAK :
+ /* sets the "release_key" bit when a key is
+ released. HP keyboard send f0 followed by
+ the keycode while AT keyboard send the keycode
+ with this bit set. */
+ brk = 0x80;
+ return;
+ case KBD_ESCAPEE0 :
+ /* 2chars sequence, commonly used to differenciate
+ the two ALT keys and the two ENTER keys and so
+ on... */
+ esc0 = 2; /* e0-xx are 2 chars */
+ scancode = keyval;
+ break;
+ case KBD_ESCAPEE1 :
+ /* 3chars sequence, only used by the Pause key. */
+ esc1 = 3; /* e1-xx-xx are 3 chars */
+ scancode = keyval;
+ break;
+#if 0
+ case KBD_RESEND :
+ /* dunno what to do when it happens. RFC */
+ printk(KERN_INFO "keyboard: KBD_RESEND received.\n");
+ return;
+#endif
+ case 0x14 :
+ /* translate e1-14-77-e1-f0-14-f0-77 to
+ e1-1d-45-e1-9d-c5 (the Pause key) */
+ if (esc1==2) scancode = brk | 0x1d;
+ break;
+ case 0x77 :
+ if (esc1==1) scancode = brk | 0x45;
+ break;
+ case 0x12 :
+ /* an extended key is e0-12-e0-xx e0-f0-xx-e0-f0-12
+ on HP, while it is e0-2a-e0-xx e0-(xx|80)-f0-aa
+ on AT. */
+ if (esc0==1) scancode = brk | 0x2a;
+ break;
+ }
+
+
+ /* translates HP scancodes to AT scancodes */
+ if (!scancode) scancode = brk | keycode_translate[keyval];
+
+
+ if (!scancode) printk(KERN_INFO "keyboard: unexpected key code %02x\n",keyval);
+
+ /* now behave like an AT keyboard */
+ handle_scancode(scancode,!(scancode&0x80));
+
+ if (esc0) esc0--;
+ if (esc1) esc1--;
+
+ /* release key bit must be unset for the next key */
+ brk = 0;
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)