aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/input/keyboard
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r--drivers/input/keyboard/Kconfig185
-rw-r--r--drivers/input/keyboard/Makefile19
-rw-r--r--drivers/input/keyboard/amikbd.c241
-rw-r--r--drivers/input/keyboard/atkbd.c1148
-rw-r--r--drivers/input/keyboard/corgikbd.c361
-rw-r--r--drivers/input/keyboard/hil_kbd.c375
-rw-r--r--drivers/input/keyboard/hilkbd.c343
-rw-r--r--drivers/input/keyboard/hpps2atkbd.h110
-rw-r--r--drivers/input/keyboard/lkkbd.c752
-rw-r--r--drivers/input/keyboard/locomokbd.c309
-rw-r--r--drivers/input/keyboard/maple_keyb.c190
-rw-r--r--drivers/input/keyboard/newtonkbd.c184
-rw-r--r--drivers/input/keyboard/sunkbd.c353
-rw-r--r--drivers/input/keyboard/xtkbd.c188
14 files changed, 4758 insertions, 0 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
new file mode 100644
index 000000000000..e55dee390775
--- /dev/null
+++ b/drivers/input/keyboard/Kconfig
@@ -0,0 +1,185 @@
1#
2# Input core configuration
3#
4menuconfig INPUT_KEYBOARD
5 bool "Keyboards" if EMBEDDED || !X86
6 default y
7 help
8 Say Y here, and a list of supported keyboards will be displayed.
9 This option doesn't affect the kernel.
10
11 If unsure, say Y.
12
13if INPUT_KEYBOARD
14
15config KEYBOARD_ATKBD
16 tristate "AT keyboard" if !PC
17 default y
18 select SERIO
19 select SERIO_LIBPS2
20 select SERIO_I8042 if PC
21 select SERIO_GSCPS2 if GSC
22 help
23 Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
24 you'll need this, unless you have a different type keyboard (USB, ADB
25 or other). This also works for AT and PS/2 keyboards connected over a
26 PS/2 to serial converter.
27
28 If unsure, say Y.
29
30 To compile this driver as a module, choose M here: the
31 module will be called atkbd.
32
33config KEYBOARD_ATKBD_HP_KEYCODES
34 bool "Use HP keyboard scancodes"
35 depends on PARISC && KEYBOARD_ATKBD
36 default y
37 help
38 Say Y here if you have a PA-RISC machine and want to use an AT or
39 PS/2 keyboard, and your keyboard uses keycodes that are specific to
40 PA-RISC keyboards.
41
42 Say N if you use a standard keyboard.
43
44config KEYBOARD_ATKBD_RDI_KEYCODES
45 bool "Use PrecisionBook keyboard scancodes"
46 depends on KEYBOARD_ATKBD_HP_KEYCODES
47 default n
48 help
49 If you have an RDI PrecisionBook, say Y here if you want to use its
50 built-in keyboard (as opposed to an external keyboard).
51
52 The PrecisionBook has five keys that conflict with those used by most
53 AT and PS/2 keyboards. These are as follows:
54
55 PrecisionBook Standard AT or PS/2
56
57 F1 F12
58 Left Ctrl Left Alt
59 Caps Lock Left Ctrl
60 Right Ctrl Caps Lock
61 Left 102nd key (the key to the right of Left Shift)
62
63 If you say N here, and use the PrecisionBook keyboard, then each key
64 in the left-hand column will be interpreted as the corresponding key
65 in the right-hand column.
66
67 If you say Y here, and use an external keyboard, then each key in the
68 right-hand column will be interpreted as the key shown in the
69 left-hand column.
70
71config KEYBOARD_SUNKBD
72 tristate "Sun Type 4 and Type 5 keyboard"
73 select SERIO
74 help
75 Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
76 connected either to the Sun keyboard connector or to an serial
77 (RS-232) port via a simple adapter.
78
79 To compile this driver as a module, choose M here: the
80 module will be called sunkbd.
81
82config KEYBOARD_LKKBD
83 tristate "DECstation/VAXstation LK201/LK401 keyboard"
84 select SERIO
85 help
86 Say Y here if you want to use a LK201 or LK401 style serial
87 keyboard. This keyboard is also useable on PCs if you attach
88 it with the inputattach program. The connector pinout is
89 described within lkkbd.c.
90
91 To compile this driver as a module, choose M here: the
92 module will be called lkkbd.
93
94config KEYBOARD_LOCOMO
95 tristate "LoCoMo Keyboard Support"
96 depends on SHARP_LOCOMO
97 help
98 Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
99
100 To compile this driver as a module, choose M here: the
101 module will be called locomokbd.
102
103config KEYBOARD_XTKBD
104 tristate "XT keyboard"
105 select SERIO
106 help
107 Say Y here if you want to use the old IBM PC/XT keyboard (or
108 compatible) on your system. This is only possible with a
109 parallel port keyboard adapter, you cannot connect it to the
110 keyboard port on a PC that runs Linux.
111
112 To compile this driver as a module, choose M here: the
113 module will be called xtkbd.
114
115config KEYBOARD_NEWTON
116 tristate "Newton keyboard"
117 select SERIO
118 help
119 Say Y here if you have a Newton keyboard on a serial port.
120
121 To compile this driver as a module, choose M here: the
122 module will be called newtonkbd.
123
124config KEYBOARD_CORGI
125 tristate "Corgi keyboard"
126 depends on PXA_SHARPSL
127 default y
128 help
129 Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx
130 series of PDAs.
131
132 To compile this driver as a module, choose M here: the
133 module will be called corgikbd.
134
135config KEYBOARD_MAPLE
136 tristate "Maple bus keyboard"
137 depends on SH_DREAMCAST && MAPLE
138 help
139 Say Y here if you have a DreamCast console running Linux and have
140 a keyboard attached to its Maple bus.
141
142 To compile this driver as a module, choose M here: the
143 module will be called maple_keyb.
144
145config KEYBOARD_AMIGA
146 tristate "Amiga keyboard"
147 depends on AMIGA
148 help
149 Say Y here if you are running Linux on any AMIGA and have a keyboard
150 attached.
151
152 To compile this driver as a module, choose M here: the
153 module will be called amikbd.
154
155config KEYBOARD_HIL_OLD
156 tristate "HP HIL keyboard support (simple driver)"
157 depends on GSC
158 default y
159 help
160 The "Human Interface Loop" is a older, 8-channel USB-like
161 controller used in several Hewlett Packard models. This driver
162 was adapted from the one written for m68k/hp300, and implements
163 support for a keyboard attached to the HIL port, but not for
164 any other types of HIL input devices like mice or tablets.
165 However, it has been thoroughly tested and is stable.
166
167 If you want full HIL support including support for multiple
168 keyboards, mices and tablets, you have to enable the
169 "HP System Device Controller i8042 Support" in the input/serio
170 submenu.
171
172config KEYBOARD_HIL
173 tristate "HP HIL keyboard support"
174 depends on GSC
175 default y
176 select HP_SDC
177 select HIL_MLC
178 select SERIO
179 help
180 The "Human Interface Loop" is a older, 8-channel USB-like
181 controller used in several Hewlett Packard models.
182 This driver implements support for HIL-keyboards attached
183 to your machine, so normally you should say Y here.
184
185endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
new file mode 100644
index 000000000000..b02eeceea3c3
--- /dev/null
+++ b/drivers/input/keyboard/Makefile
@@ -0,0 +1,19 @@
1#
2# Makefile for the input core drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
8obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
9obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
10obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
11obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
12obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
13obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
14obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
15obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o
16obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
17obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
18obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
19
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
new file mode 100644
index 000000000000..4e8e8ea214ab
--- /dev/null
+++ b/drivers/input/keyboard/amikbd.c
@@ -0,0 +1,241 @@
1/*
2 * $Id: amikbd.c,v 1.13 2002/02/01 16:02:24 vojtech Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Hamish Macdonald
8 */
9
10/*
11 * Amiga keyboard driver for Linux/m68k
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/input.h>
37#include <linux/delay.h>
38#include <linux/interrupt.h>
39
40#include <asm/amigaints.h>
41#include <asm/amigahw.h>
42#include <asm/irq.h>
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION("Amiga keyboard driver");
46MODULE_LICENSE("GPL");
47
48static unsigned char amikbd_keycode[0x78] = {
49 [0] = KEY_GRAVE,
50 [1] = KEY_1,
51 [2] = KEY_2,
52 [3] = KEY_3,
53 [4] = KEY_4,
54 [5] = KEY_5,
55 [6] = KEY_6,
56 [7] = KEY_7,
57 [8] = KEY_8,
58 [9] = KEY_9,
59 [10] = KEY_0,
60 [11] = KEY_MINUS,
61 [12] = KEY_EQUAL,
62 [13] = KEY_BACKSLASH,
63 [15] = KEY_KP0,
64 [16] = KEY_Q,
65 [17] = KEY_W,
66 [18] = KEY_E,
67 [19] = KEY_R,
68 [20] = KEY_T,
69 [21] = KEY_Y,
70 [22] = KEY_U,
71 [23] = KEY_I,
72 [24] = KEY_O,
73 [25] = KEY_P,
74 [26] = KEY_LEFTBRACE,
75 [27] = KEY_RIGHTBRACE,
76 [29] = KEY_KP1,
77 [30] = KEY_KP2,
78 [31] = KEY_KP3,
79 [32] = KEY_A,
80 [33] = KEY_S,
81 [34] = KEY_D,
82 [35] = KEY_F,
83 [36] = KEY_G,
84 [37] = KEY_H,
85 [38] = KEY_J,
86 [39] = KEY_K,
87 [40] = KEY_L,
88 [41] = KEY_SEMICOLON,
89 [42] = KEY_APOSTROPHE,
90 [43] = KEY_BACKSLASH,
91 [45] = KEY_KP4,
92 [46] = KEY_KP5,
93 [47] = KEY_KP6,
94 [48] = KEY_102ND,
95 [49] = KEY_Z,
96 [50] = KEY_X,
97 [51] = KEY_C,
98 [52] = KEY_V,
99 [53] = KEY_B,
100 [54] = KEY_N,
101 [55] = KEY_M,
102 [56] = KEY_COMMA,
103 [57] = KEY_DOT,
104 [58] = KEY_SLASH,
105 [60] = KEY_KPDOT,
106 [61] = KEY_KP7,
107 [62] = KEY_KP8,
108 [63] = KEY_KP9,
109 [64] = KEY_SPACE,
110 [65] = KEY_BACKSPACE,
111 [66] = KEY_TAB,
112 [67] = KEY_KPENTER,
113 [68] = KEY_ENTER,
114 [69] = KEY_ESC,
115 [70] = KEY_DELETE,
116 [74] = KEY_KPMINUS,
117 [76] = KEY_UP,
118 [77] = KEY_DOWN,
119 [78] = KEY_RIGHT,
120 [79] = KEY_LEFT,
121 [80] = KEY_F1,
122 [81] = KEY_F2,
123 [82] = KEY_F3,
124 [83] = KEY_F4,
125 [84] = KEY_F5,
126 [85] = KEY_F6,
127 [86] = KEY_F7,
128 [87] = KEY_F8,
129 [88] = KEY_F9,
130 [89] = KEY_F10,
131 [90] = KEY_KPLEFTPAREN,
132 [91] = KEY_KPRIGHTPAREN,
133 [92] = KEY_KPSLASH,
134 [93] = KEY_KPASTERISK,
135 [94] = KEY_KPPLUS,
136 [95] = KEY_HELP,
137 [96] = KEY_LEFTSHIFT,
138 [97] = KEY_RIGHTSHIFT,
139 [98] = KEY_CAPSLOCK,
140 [99] = KEY_LEFTCTRL,
141 [100] = KEY_LEFTALT,
142 [101] = KEY_RIGHTALT,
143 [102] = KEY_LEFTMETA,
144 [103] = KEY_RIGHTMETA
145};
146
147static const char *amikbd_messages[8] = {
148 [0] = KERN_ALERT "amikbd: Ctrl-Amiga-Amiga reset warning!!\n",
149 [1] = KERN_WARNING "amikbd: keyboard lost sync\n",
150 [2] = KERN_WARNING "amikbd: keyboard buffer overflow\n",
151 [3] = KERN_WARNING "amikbd: keyboard controller failure\n",
152 [4] = KERN_ERR "amikbd: keyboard selftest failure\n",
153 [5] = KERN_INFO "amikbd: initiate power-up key stream\n",
154 [6] = KERN_INFO "amikbd: terminate power-up key stream\n",
155 [7] = KERN_WARNING "amikbd: keyboard interrupt\n"
156};
157
158static struct input_dev amikbd_dev;
159
160static char *amikbd_name = "Amiga keyboard";
161static char *amikbd_phys = "amikbd/input0";
162
163static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
164{
165 unsigned char scancode, down;
166
167 scancode = ~ciaa.sdr; /* get and invert scancode (keyboard is active low) */
168 ciaa.cra |= 0x40; /* switch SP pin to output for handshake */
169 udelay(85); /* wait until 85 us have expired */
170 ciaa.cra &= ~0x40; /* switch CIA serial port to input mode */
171
172 down = !(scancode & 1); /* lowest bit is release bit */
173 scancode >>= 1;
174
175 if (scancode < 0x78) { /* scancodes < 0x78 are keys */
176
177 scancode = amikbd_keycode[scancode];
178
179 input_regs(&amikbd_dev, fp);
180
181 if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */
182 input_report_key(&amikbd_dev, scancode, 1);
183 input_report_key(&amikbd_dev, scancode, 0);
184 input_sync(&amikbd_dev);
185 } else {
186 input_report_key(&amikbd_dev, scancode, down);
187 input_sync(&amikbd_dev);
188 }
189 } else /* scancodes >= 0x78 are error codes */
190 printk(amikbd_messages[scancode - 0x78]);
191
192 return IRQ_HANDLED;
193}
194
195static int __init amikbd_init(void)
196{
197 int i;
198
199 if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
200 return -EIO;
201
202 if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
203 return -EBUSY;
204
205 init_input_dev(&amikbd_dev);
206
207 amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
208 amikbd_dev.keycode = amikbd_keycode;
209 amikbd_dev.keycodesize = sizeof(unsigned char);
210 amikbd_dev.keycodemax = ARRAY_SIZE(amikbd_keycode);
211
212 for (i = 0; i < 0x78; i++)
213 if (amikbd_keycode[i])
214 set_bit(amikbd_keycode[i], amikbd_dev.keybit);
215
216 ciaa.cra &= ~0x41; /* serial data in, turn off TA */
217 request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
218
219 amikbd_dev.name = amikbd_name;
220 amikbd_dev.phys = amikbd_phys;
221 amikbd_dev.id.bustype = BUS_AMIGA;
222 amikbd_dev.id.vendor = 0x0001;
223 amikbd_dev.id.product = 0x0001;
224 amikbd_dev.id.version = 0x0100;
225
226 input_register_device(&amikbd_dev);
227
228 printk(KERN_INFO "input: %s\n", amikbd_name);
229
230 return 0;
231}
232
233static void __exit amikbd_exit(void)
234{
235 input_unregister_device(&amikbd_dev);
236 free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
237 release_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100);
238}
239
240module_init(amikbd_init);
241module_exit(amikbd_exit);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
new file mode 100644
index 000000000000..f7304f0ce542
--- /dev/null
+++ b/drivers/input/keyboard/atkbd.c
@@ -0,0 +1,1148 @@
1/*
2 * AT and PS/2 keyboard driver
3 *
4 * Copyright (c) 1999-2002 Vojtech Pavlik
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13/*
14 * This driver can handle standard AT keyboards and PS/2 keyboards in
15 * Translated and Raw Set 2 and Set 3, as well as AT keyboards on dumb
16 * input-only controllers and AT keyboards connected over a one way RS232
17 * converter.
18 */
19
20#include <linux/delay.h>
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <linux/slab.h>
24#include <linux/interrupt.h>
25#include <linux/init.h>
26#include <linux/input.h>
27#include <linux/serio.h>
28#include <linux/workqueue.h>
29#include <linux/libps2.h>
30
31#define DRIVER_DESC "AT and PS/2 keyboard driver"
32
33MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
34MODULE_DESCRIPTION(DRIVER_DESC);
35MODULE_LICENSE("GPL");
36
37static int atkbd_set = 2;
38module_param_named(set, atkbd_set, int, 0);
39MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)");
40
41#if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
42static int atkbd_reset;
43#else
44static int atkbd_reset = 1;
45#endif
46module_param_named(reset, atkbd_reset, bool, 0);
47MODULE_PARM_DESC(reset, "Reset keyboard during initialization");
48
49static int atkbd_softrepeat;
50module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
51MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
52
53static int atkbd_softraw = 1;
54module_param_named(softraw, atkbd_softraw, bool, 0);
55MODULE_PARM_DESC(softraw, "Use software generated rawmode");
56
57static int atkbd_scroll = 1;
58module_param_named(scroll, atkbd_scroll, bool, 0);
59MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
60
61static int atkbd_extra;
62module_param_named(extra, atkbd_extra, bool, 0);
63MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
64
65__obsolete_setup("atkbd_set=");
66__obsolete_setup("atkbd_reset");
67__obsolete_setup("atkbd_softrepeat=");
68
69/*
70 * Scancode to keycode tables. These are just the default setting, and
71 * are loadable via an userland utility.
72 */
73
74static unsigned char atkbd_set2_keycode[512] = {
75
76#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
77
78/* XXX: need a more general approach */
79
80#include "hpps2atkbd.h" /* include the keyboard scancodes */
81
82#else
83 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
84 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
85 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
86 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
87 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
88 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
89 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
90 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
91
92 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
94 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
95 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
96 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
97 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
98 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
99 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
100
101 0, 0, 0, 65, 99,
102#endif
103};
104
105static unsigned char atkbd_set3_keycode[512] = {
106
107 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60,
108 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62,
109 134, 46, 45, 32, 18, 5, 4, 63,135, 57, 47, 33, 20, 19, 6, 64,
110 136, 49, 48, 35, 34, 21, 7, 65,137,100, 50, 36, 22, 8, 9, 66,
111 125, 51, 37, 23, 24, 11, 10, 67,126, 52, 53, 38, 39, 25, 12, 68,
112 113,114, 40, 43, 26, 13, 87, 99, 97, 54, 28, 27, 43, 43, 88, 70,
113 108,105,119,103,111,107, 14,110, 0, 79,106, 75, 71,109,102,104,
114 82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55,183,
115
116 184,185,186,187, 74, 94, 92, 93, 0, 0, 0,125,126,127,112, 0,
117 0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
118 148,149,147,140
119};
120
121static unsigned char atkbd_unxlate_table[128] = {
122 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
123 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
124 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
125 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
126 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
127 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
128 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
129 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
130};
131
132#define ATKBD_CMD_SETLEDS 0x10ed
133#define ATKBD_CMD_GSCANSET 0x11f0
134#define ATKBD_CMD_SSCANSET 0x10f0
135#define ATKBD_CMD_GETID 0x02f2
136#define ATKBD_CMD_SETREP 0x10f3
137#define ATKBD_CMD_ENABLE 0x00f4
138#define ATKBD_CMD_RESET_DIS 0x00f5
139#define ATKBD_CMD_SETALL_MBR 0x00fa
140#define ATKBD_CMD_RESET_BAT 0x02ff
141#define ATKBD_CMD_RESEND 0x00fe
142#define ATKBD_CMD_EX_ENABLE 0x10ea
143#define ATKBD_CMD_EX_SETLEDS 0x20eb
144#define ATKBD_CMD_OK_GETID 0x02e8
145
146#define ATKBD_RET_ACK 0xfa
147#define ATKBD_RET_NAK 0xfe
148#define ATKBD_RET_BAT 0xaa
149#define ATKBD_RET_EMUL0 0xe0
150#define ATKBD_RET_EMUL1 0xe1
151#define ATKBD_RET_RELEASE 0xf0
152#define ATKBD_RET_HANGUEL 0xf1
153#define ATKBD_RET_HANJA 0xf2
154#define ATKBD_RET_ERR 0xff
155
156#define ATKBD_KEY_UNKNOWN 0
157#define ATKBD_KEY_NULL 255
158
159#define ATKBD_SCR_1 254
160#define ATKBD_SCR_2 253
161#define ATKBD_SCR_4 252
162#define ATKBD_SCR_8 251
163#define ATKBD_SCR_CLICK 250
164#define ATKBD_SCR_LEFT 249
165#define ATKBD_SCR_RIGHT 248
166
167#define ATKBD_SPECIAL 248
168
169static struct {
170 unsigned char keycode;
171 unsigned char set2;
172} atkbd_scroll_keys[] = {
173 { ATKBD_SCR_1, 0xc5 },
174 { ATKBD_SCR_2, 0xa9 },
175 { ATKBD_SCR_4, 0xb6 },
176 { ATKBD_SCR_8, 0xa7 },
177 { ATKBD_SCR_CLICK, 0xe0 },
178 { ATKBD_SCR_LEFT, 0xcb },
179 { ATKBD_SCR_RIGHT, 0xd2 },
180};
181
182/*
183 * The atkbd control structure
184 */
185
186struct atkbd {
187
188 struct ps2dev ps2dev;
189
190 /* Written only during init */
191 char name[64];
192 char phys[32];
193 struct input_dev dev;
194
195 unsigned short id;
196 unsigned char keycode[512];
197 unsigned char set;
198 unsigned char translated;
199 unsigned char extra;
200 unsigned char write;
201 unsigned char softrepeat;
202 unsigned char softraw;
203 unsigned char scroll;
204 unsigned char enabled;
205
206 /* Accessed only from interrupt */
207 unsigned char emul;
208 unsigned char resend;
209 unsigned char release;
210 unsigned char bat_xl;
211 unsigned int last;
212 unsigned long time;
213};
214
215static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
216 ssize_t (*handler)(struct atkbd *, char *));
217static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
218 ssize_t (*handler)(struct atkbd *, const char *, size_t));
219#define ATKBD_DEFINE_ATTR(_name) \
220static ssize_t atkbd_show_##_name(struct atkbd *, char *); \
221static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \
222static ssize_t atkbd_do_show_##_name(struct device *d, char *b) \
223{ \
224 return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \
225} \
226static ssize_t atkbd_do_set_##_name(struct device *d, const char *b, size_t s) \
227{ \
228 return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \
229} \
230static struct device_attribute atkbd_attr_##_name = \
231 __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name);
232
233ATKBD_DEFINE_ATTR(extra);
234ATKBD_DEFINE_ATTR(scroll);
235ATKBD_DEFINE_ATTR(set);
236ATKBD_DEFINE_ATTR(softrepeat);
237ATKBD_DEFINE_ATTR(softraw);
238
239
240static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value)
241{
242 input_regs(dev, regs);
243 if (value == 3) {
244 input_report_key(dev, code, 1);
245 input_sync(dev);
246 input_report_key(dev, code, 0);
247 } else
248 input_event(dev, EV_KEY, code, value);
249 input_sync(dev);
250}
251
252/*
253 * atkbd_interrupt(). Here takes place processing of data received from
254 * the keyboard into events.
255 */
256
257static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
258 unsigned int flags, struct pt_regs *regs)
259{
260 struct atkbd *atkbd = serio_get_drvdata(serio);
261 unsigned int code = data;
262 int scroll = 0, hscroll = 0, click = -1;
263 int value;
264
265#ifdef ATKBD_DEBUG
266 printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
267#endif
268
269#if !defined(__i386__) && !defined (__x86_64__)
270 if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
271 printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags);
272 serio_write(serio, ATKBD_CMD_RESEND);
273 atkbd->resend = 1;
274 goto out;
275 }
276
277 if (!flags && data == ATKBD_RET_ACK)
278 atkbd->resend = 0;
279#endif
280
281 if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK))
282 if (ps2_handle_ack(&atkbd->ps2dev, data))
283 goto out;
284
285 if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD))
286 if (ps2_handle_response(&atkbd->ps2dev, data))
287 goto out;
288
289 if (!atkbd->enabled)
290 goto out;
291
292 input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);
293
294 if (atkbd->translated) {
295
296 if (atkbd->emul ||
297 !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
298 code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
299 code == ATKBD_RET_ERR ||
300 (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
301 atkbd->release = code >> 7;
302 code &= 0x7f;
303 }
304
305 if (!atkbd->emul &&
306 (code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
307 atkbd->bat_xl = !atkbd->release;
308 }
309
310 switch (code) {
311 case ATKBD_RET_BAT:
312 atkbd->enabled = 0;
313 serio_rescan(atkbd->ps2dev.serio);
314 goto out;
315 case ATKBD_RET_EMUL0:
316 atkbd->emul = 1;
317 goto out;
318 case ATKBD_RET_EMUL1:
319 atkbd->emul = 2;
320 goto out;
321 case ATKBD_RET_RELEASE:
322 atkbd->release = 1;
323 goto out;
324 case ATKBD_RET_HANGUEL:
325 atkbd_report_key(&atkbd->dev, regs, KEY_HANGUEL, 3);
326 goto out;
327 case ATKBD_RET_HANJA:
328 atkbd_report_key(&atkbd->dev, regs, KEY_HANJA, 3);
329 goto out;
330 case ATKBD_RET_ERR:
331 printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
332 goto out;
333 }
334
335 if (atkbd->set != 3)
336 code = (code & 0x7f) | ((code & 0x80) << 1);
337 if (atkbd->emul) {
338 if (--atkbd->emul)
339 goto out;
340 code |= (atkbd->set != 3) ? 0x80 : 0x100;
341 }
342
343 if (atkbd->keycode[code] != ATKBD_KEY_NULL)
344 input_event(&atkbd->dev, EV_MSC, MSC_SCAN, code);
345
346 switch (atkbd->keycode[code]) {
347 case ATKBD_KEY_NULL:
348 break;
349 case ATKBD_KEY_UNKNOWN:
350 if (data == ATKBD_RET_ACK || data == ATKBD_RET_NAK) {
351 printk(KERN_WARNING "atkbd.c: Spurious %s on %s. Some program, "
352 "like XFree86, might be trying access hardware directly.\n",
353 data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
354 } else {
355 printk(KERN_WARNING "atkbd.c: Unknown key %s "
356 "(%s set %d, code %#x on %s).\n",
357 atkbd->release ? "released" : "pressed",
358 atkbd->translated ? "translated" : "raw",
359 atkbd->set, code, serio->phys);
360 printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x <keycode>' "
361 "to make it known.\n",
362 code & 0x80 ? "e0" : "", code & 0x7f);
363 }
364 input_sync(&atkbd->dev);
365 break;
366 case ATKBD_SCR_1:
367 scroll = 1 - atkbd->release * 2;
368 break;
369 case ATKBD_SCR_2:
370 scroll = 2 - atkbd->release * 4;
371 break;
372 case ATKBD_SCR_4:
373 scroll = 4 - atkbd->release * 8;
374 break;
375 case ATKBD_SCR_8:
376 scroll = 8 - atkbd->release * 16;
377 break;
378 case ATKBD_SCR_CLICK:
379 click = !atkbd->release;
380 break;
381 case ATKBD_SCR_LEFT:
382 hscroll = -1;
383 break;
384 case ATKBD_SCR_RIGHT:
385 hscroll = 1;
386 break;
387 default:
388 value = atkbd->release ? 0 :
389 (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
390
391 switch (value) { /* Workaround Toshiba laptop multiple keypress */
392 case 0:
393 atkbd->last = 0;
394 break;
395 case 1:
396 atkbd->last = code;
397 atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev.rep[REP_DELAY]) / 2;
398 break;
399 case 2:
400 if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
401 value = 1;
402 break;
403 }
404
405 atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
406 }
407
408 if (atkbd->scroll) {
409 input_regs(&atkbd->dev, regs);
410 if (click != -1)
411 input_report_key(&atkbd->dev, BTN_MIDDLE, click);
412 input_report_rel(&atkbd->dev, REL_WHEEL, scroll);
413 input_report_rel(&atkbd->dev, REL_HWHEEL, hscroll);
414 input_sync(&atkbd->dev);
415 }
416
417 atkbd->release = 0;
418out:
419 return IRQ_HANDLED;
420}
421
422/*
423 * Event callback from the input module. Events that change the state of
424 * the hardware are processed here.
425 */
426
427static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
428{
429 struct atkbd *atkbd = dev->private;
430 const short period[32] =
431 { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
432 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
433 const short delay[4] =
434 { 250, 500, 750, 1000 };
435 unsigned char param[2];
436 int i, j;
437
438 if (!atkbd->write)
439 return -1;
440
441 switch (type) {
442
443 case EV_LED:
444
445 param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
446 | (test_bit(LED_NUML, dev->led) ? 2 : 0)
447 | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
448 ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS);
449
450 if (atkbd->extra) {
451 param[0] = 0;
452 param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
453 | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
454 | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
455 | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
456 | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
457 ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS);
458 }
459
460 return 0;
461
462
463 case EV_REP:
464
465 if (atkbd->softrepeat) return 0;
466
467 i = j = 0;
468 while (i < 32 && period[i] < dev->rep[REP_PERIOD]) i++;
469 while (j < 4 && delay[j] < dev->rep[REP_DELAY]) j++;
470 dev->rep[REP_PERIOD] = period[i];
471 dev->rep[REP_DELAY] = delay[j];
472 param[0] = i | (j << 5);
473 ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
474
475 return 0;
476 }
477
478 return -1;
479}
480
481/*
482 * atkbd_enable() signals that interrupt handler is allowed to
483 * generate input events.
484 */
485
486static inline void atkbd_enable(struct atkbd *atkbd)
487{
488 serio_pause_rx(atkbd->ps2dev.serio);
489 atkbd->enabled = 1;
490 serio_continue_rx(atkbd->ps2dev.serio);
491}
492
493/*
494 * atkbd_disable() tells input handler that all incoming data except
495 * for ACKs and command response should be dropped.
496 */
497
498static inline void atkbd_disable(struct atkbd *atkbd)
499{
500 serio_pause_rx(atkbd->ps2dev.serio);
501 atkbd->enabled = 0;
502 serio_continue_rx(atkbd->ps2dev.serio);
503}
504
505/*
506 * atkbd_probe() probes for an AT keyboard on a serio port.
507 */
508
509static int atkbd_probe(struct atkbd *atkbd)
510{
511 struct ps2dev *ps2dev = &atkbd->ps2dev;
512 unsigned char param[2];
513
514/*
515 * Some systems, where the bit-twiddling when testing the io-lines of the
516 * controller may confuse the keyboard need a full reset of the keyboard. On
517 * these systems the BIOS also usually doesn't do it for us.
518 */
519
520 if (atkbd_reset)
521 if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT))
522 printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", ps2dev->serio->phys);
523
524/*
525 * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
526 * Some keyboards report different values, but the first byte is always 0xab or
527 * 0xac. Some old AT keyboards don't report anything. If a mouse is connected, this
528 * should make sure we don't try to set the LEDs on it.
529 */
530
531 param[0] = param[1] = 0xa5; /* initialize with invalid values */
532 if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
533
534/*
535 * If the get ID command failed, we check if we can at least set the LEDs on
536 * the keyboard. This should work on every keyboard out there. It also turns
537 * the LEDs off, which we want anyway.
538 */
539 param[0] = 0;
540 if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
541 return -1;
542 atkbd->id = 0xabba;
543 return 0;
544 }
545
546 if (param[0] != 0xab && param[0] != 0xac && /* Regular and NCD Sun keyboards */
547 param[0] != 0x2b && param[0] != 0x5d && /* Trust keyboard, raw and translated */
548 param[0] != 0x60 && param[0] != 0x47) /* NMB SGI keyboard, raw and translated */
549 return -1;
550
551 atkbd->id = (param[0] << 8) | param[1];
552
553 if (atkbd->id == 0xaca1 && atkbd->translated) {
554 printk(KERN_ERR "atkbd.c: NCD terminal keyboards are only supported on non-translating\n");
555 printk(KERN_ERR "atkbd.c: controllers. Use i8042.direct=1 to disable translation.\n");
556 return -1;
557 }
558
559 return 0;
560}
561
562/*
563 * atkbd_select_set checks if a keyboard has a working Set 3 support, and
564 * sets it into that. Unfortunately there are keyboards that can be switched
565 * to Set 3, but don't work well in that (BTC Multimedia ...)
566 */
567
568static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra)
569{
570 struct ps2dev *ps2dev = &atkbd->ps2dev;
571 unsigned char param[2];
572
573 atkbd->extra = 0;
574/*
575 * For known special keyboards we can go ahead and set the correct set.
576 * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and
577 * IBM RapidAccess / IBM EzButton / Chicony KBP-8993 keyboards.
578 */
579
580 if (atkbd->translated)
581 return 2;
582
583 if (atkbd->id == 0xaca1) {
584 param[0] = 3;
585 ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET);
586 return 3;
587 }
588
589 if (allow_extra) {
590 param[0] = 0x71;
591 if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) {
592 atkbd->extra = 1;
593 return 2;
594 }
595 }
596
597 if (target_set != 3)
598 return 2;
599
600 if (!ps2_command(ps2dev, param, ATKBD_CMD_OK_GETID)) {
601 atkbd->id = param[0] << 8 | param[1];
602 return 2;
603 }
604
605 param[0] = 3;
606 if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))
607 return 2;
608
609 param[0] = 0;
610 if (ps2_command(ps2dev, param, ATKBD_CMD_GSCANSET))
611 return 2;
612
613 if (param[0] != 3) {
614 param[0] = 2;
615 if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))
616 return 2;
617 }
618
619 ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MBR);
620
621 return 3;
622}
623
624static int atkbd_activate(struct atkbd *atkbd)
625{
626 struct ps2dev *ps2dev = &atkbd->ps2dev;
627 unsigned char param[1];
628
629/*
630 * Set the LEDs to a defined state.
631 */
632
633 param[0] = 0;
634 if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
635 return -1;
636
637/*
638 * Set autorepeat to fastest possible.
639 */
640
641 param[0] = 0;
642 if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
643 return -1;
644
645/*
646 * Enable the keyboard to receive keystrokes.
647 */
648
649 if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
650 printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
651 ps2dev->serio->phys);
652 return -1;
653 }
654
655 return 0;
656}
657
658/*
659 * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
660 * reboot.
661 */
662
663static void atkbd_cleanup(struct serio *serio)
664{
665 struct atkbd *atkbd = serio_get_drvdata(serio);
666 ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT);
667}
668
669
670/*
671 * atkbd_disconnect() closes and frees.
672 */
673
674static void atkbd_disconnect(struct serio *serio)
675{
676 struct atkbd *atkbd = serio_get_drvdata(serio);
677
678 atkbd_disable(atkbd);
679
680 /* make sure we don't have a command in flight */
681 synchronize_kernel();
682 flush_scheduled_work();
683
684 device_remove_file(&serio->dev, &atkbd_attr_extra);
685 device_remove_file(&serio->dev, &atkbd_attr_scroll);
686 device_remove_file(&serio->dev, &atkbd_attr_set);
687 device_remove_file(&serio->dev, &atkbd_attr_softrepeat);
688 device_remove_file(&serio->dev, &atkbd_attr_softraw);
689
690 input_unregister_device(&atkbd->dev);
691 serio_close(serio);
692 serio_set_drvdata(serio, NULL);
693 kfree(atkbd);
694}
695
696
697/*
698 * atkbd_set_device_attrs() initializes keyboard's keycode table
699 * according to the selected scancode set
700 */
701
702static void atkbd_set_keycode_table(struct atkbd *atkbd)
703{
704 int i, j;
705
706 memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
707
708 if (atkbd->translated) {
709 for (i = 0; i < 128; i++) {
710 atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
711 atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
712 if (atkbd->scroll)
713 for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++)
714 if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j].set2)
715 atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
716 }
717 } else if (atkbd->set == 3) {
718 memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
719 } else {
720 memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
721
722 if (atkbd->scroll)
723 for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
724 atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode;
725 }
726}
727
728/*
729 * atkbd_set_device_attrs() sets up keyboard's input device structure
730 */
731
732static void atkbd_set_device_attrs(struct atkbd *atkbd)
733{
734 int i;
735
736 memset(&atkbd->dev, 0, sizeof(struct input_dev));
737
738 init_input_dev(&atkbd->dev);
739
740 atkbd->dev.name = atkbd->name;
741 atkbd->dev.phys = atkbd->phys;
742 atkbd->dev.id.bustype = BUS_I8042;
743 atkbd->dev.id.vendor = 0x0001;
744 atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set;
745 atkbd->dev.id.version = atkbd->id;
746 atkbd->dev.event = atkbd_event;
747 atkbd->dev.private = atkbd;
748 atkbd->dev.dev = &atkbd->ps2dev.serio->dev;
749
750 atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
751
752 if (atkbd->write) {
753 atkbd->dev.evbit[0] |= BIT(EV_LED);
754 atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
755 }
756
757 if (atkbd->extra)
758 atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
759 BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
760
761 if (!atkbd->softrepeat) {
762 atkbd->dev.rep[REP_DELAY] = 250;
763 atkbd->dev.rep[REP_PERIOD] = 33;
764 }
765
766 atkbd->dev.mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
767
768 if (atkbd->scroll) {
769 atkbd->dev.evbit[0] |= BIT(EV_REL);
770 atkbd->dev.relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
771 set_bit(BTN_MIDDLE, atkbd->dev.keybit);
772 }
773
774 atkbd->dev.keycode = atkbd->keycode;
775 atkbd->dev.keycodesize = sizeof(unsigned char);
776 atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
777
778 for (i = 0; i < 512; i++)
779 if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
780 set_bit(atkbd->keycode[i], atkbd->dev.keybit);
781}
782
783/*
784 * atkbd_connect() is called when the serio module finds an interface
785 * that isn't handled yet by an appropriate device driver. We check if
786 * there is an AT keyboard out there and if yes, we register ourselves
787 * to the input module.
788 */
789
790static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
791{
792 struct atkbd *atkbd;
793 int err;
794
795 if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
796 return - ENOMEM;
797
798 memset(atkbd, 0, sizeof(struct atkbd));
799
800 ps2_init(&atkbd->ps2dev, serio);
801
802 switch (serio->id.type) {
803
804 case SERIO_8042_XL:
805 atkbd->translated = 1;
806 case SERIO_8042:
807 if (serio->write)
808 atkbd->write = 1;
809 break;
810 }
811
812 atkbd->softraw = atkbd_softraw;
813 atkbd->softrepeat = atkbd_softrepeat;
814 atkbd->scroll = atkbd_scroll;
815
816 if (!atkbd->write)
817 atkbd->softrepeat = 1;
818
819 if (atkbd->softrepeat)
820 atkbd->softraw = 1;
821
822 serio_set_drvdata(serio, atkbd);
823
824 err = serio_open(serio, drv);
825 if (err) {
826 serio_set_drvdata(serio, NULL);
827 kfree(atkbd);
828 return err;
829 }
830
831 if (atkbd->write) {
832
833 if (atkbd_probe(atkbd)) {
834 serio_close(serio);
835 serio_set_drvdata(serio, NULL);
836 kfree(atkbd);
837 return -ENODEV;
838 }
839
840 atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
841 atkbd_activate(atkbd);
842
843 } else {
844 atkbd->set = 2;
845 atkbd->id = 0xab00;
846 }
847
848 if (atkbd->extra)
849 sprintf(atkbd->name, "AT Set 2 Extra keyboard");
850 else
851 sprintf(atkbd->name, "AT %s Set %d keyboard",
852 atkbd->translated ? "Translated" : "Raw", atkbd->set);
853
854 sprintf(atkbd->phys, "%s/input0", serio->phys);
855
856 atkbd_set_keycode_table(atkbd);
857 atkbd_set_device_attrs(atkbd);
858
859 input_register_device(&atkbd->dev);
860
861 device_create_file(&serio->dev, &atkbd_attr_extra);
862 device_create_file(&serio->dev, &atkbd_attr_scroll);
863 device_create_file(&serio->dev, &atkbd_attr_set);
864 device_create_file(&serio->dev, &atkbd_attr_softrepeat);
865 device_create_file(&serio->dev, &atkbd_attr_softraw);
866
867 atkbd_enable(atkbd);
868
869 printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
870
871 return 0;
872}
873
874/*
875 * atkbd_reconnect() tries to restore keyboard into a sane state and is
876 * most likely called on resume.
877 */
878
879static int atkbd_reconnect(struct serio *serio)
880{
881 struct atkbd *atkbd = serio_get_drvdata(serio);
882 struct serio_driver *drv = serio->drv;
883 unsigned char param[1];
884
885 if (!atkbd || !drv) {
886 printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
887 return -1;
888 }
889
890 atkbd_disable(atkbd);
891
892 if (atkbd->write) {
893 param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
894 | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0)
895 | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0);
896
897 if (atkbd_probe(atkbd))
898 return -1;
899 if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
900 return -1;
901
902 atkbd_activate(atkbd);
903
904 if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
905 return -1;
906 }
907
908 atkbd_enable(atkbd);
909
910 return 0;
911}
912
913static struct serio_device_id atkbd_serio_ids[] = {
914 {
915 .type = SERIO_8042,
916 .proto = SERIO_ANY,
917 .id = SERIO_ANY,
918 .extra = SERIO_ANY,
919 },
920 {
921 .type = SERIO_8042_XL,
922 .proto = SERIO_ANY,
923 .id = SERIO_ANY,
924 .extra = SERIO_ANY,
925 },
926 {
927 .type = SERIO_RS232,
928 .proto = SERIO_PS2SER,
929 .id = SERIO_ANY,
930 .extra = SERIO_ANY,
931 },
932 { 0 }
933};
934
935MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);
936
937static struct serio_driver atkbd_drv = {
938 .driver = {
939 .name = "atkbd",
940 },
941 .description = DRIVER_DESC,
942 .id_table = atkbd_serio_ids,
943 .interrupt = atkbd_interrupt,
944 .connect = atkbd_connect,
945 .reconnect = atkbd_reconnect,
946 .disconnect = atkbd_disconnect,
947 .cleanup = atkbd_cleanup,
948};
949
950static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
951 ssize_t (*handler)(struct atkbd *, char *))
952{
953 struct serio *serio = to_serio_port(dev);
954 int retval;
955
956 retval = serio_pin_driver(serio);
957 if (retval)
958 return retval;
959
960 if (serio->drv != &atkbd_drv) {
961 retval = -ENODEV;
962 goto out;
963 }
964
965 retval = handler((struct atkbd *)serio_get_drvdata(serio), buf);
966
967out:
968 serio_unpin_driver(serio);
969 return retval;
970}
971
972static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
973 ssize_t (*handler)(struct atkbd *, const char *, size_t))
974{
975 struct serio *serio = to_serio_port(dev);
976 struct atkbd *atkbd;
977 int retval;
978
979 retval = serio_pin_driver(serio);
980 if (retval)
981 return retval;
982
983 if (serio->drv != &atkbd_drv) {
984 retval = -ENODEV;
985 goto out;
986 }
987
988 atkbd = serio_get_drvdata(serio);
989 atkbd_disable(atkbd);
990 retval = handler(atkbd, buf, count);
991 atkbd_enable(atkbd);
992
993out:
994 serio_unpin_driver(serio);
995 return retval;
996}
997
998static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
999{
1000 return sprintf(buf, "%d\n", atkbd->extra ? 1 : 0);
1001}
1002
1003static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
1004{
1005 unsigned long value;
1006 char *rest;
1007
1008 if (!atkbd->write)
1009 return -EIO;
1010
1011 value = simple_strtoul(buf, &rest, 10);
1012 if (*rest || value > 1)
1013 return -EINVAL;
1014
1015 if (atkbd->extra != value) {
1016 /* unregister device as it's properties will change */
1017 input_unregister_device(&atkbd->dev);
1018 atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
1019 atkbd_activate(atkbd);
1020 atkbd_set_device_attrs(atkbd);
1021 input_register_device(&atkbd->dev);
1022 }
1023 return count;
1024}
1025
1026static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
1027{
1028 return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0);
1029}
1030
1031static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
1032{
1033 unsigned long value;
1034 char *rest;
1035
1036 value = simple_strtoul(buf, &rest, 10);
1037 if (*rest || value > 1)
1038 return -EINVAL;
1039
1040 if (atkbd->scroll != value) {
1041 /* unregister device as it's properties will change */
1042 input_unregister_device(&atkbd->dev);
1043 atkbd->scroll = value;
1044 atkbd_set_keycode_table(atkbd);
1045 atkbd_set_device_attrs(atkbd);
1046 input_register_device(&atkbd->dev);
1047 }
1048 return count;
1049}
1050
1051static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
1052{
1053 return sprintf(buf, "%d\n", atkbd->set);
1054}
1055
1056static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
1057{
1058 unsigned long value;
1059 char *rest;
1060
1061 if (!atkbd->write)
1062 return -EIO;
1063
1064 value = simple_strtoul(buf, &rest, 10);
1065 if (*rest || (value != 2 && value != 3))
1066 return -EINVAL;
1067
1068 if (atkbd->set != value) {
1069 /* unregister device as it's properties will change */
1070 input_unregister_device(&atkbd->dev);
1071 atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
1072 atkbd_activate(atkbd);
1073 atkbd_set_keycode_table(atkbd);
1074 atkbd_set_device_attrs(atkbd);
1075 input_register_device(&atkbd->dev);
1076 }
1077 return count;
1078}
1079
1080static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
1081{
1082 return sprintf(buf, "%d\n", atkbd->softrepeat ? 1 : 0);
1083}
1084
1085static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
1086{
1087 unsigned long value;
1088 char *rest;
1089
1090 if (!atkbd->write)
1091 return -EIO;
1092
1093 value = simple_strtoul(buf, &rest, 10);
1094 if (*rest || value > 1)
1095 return -EINVAL;
1096
1097 if (atkbd->softrepeat != value) {
1098 /* unregister device as it's properties will change */
1099 input_unregister_device(&atkbd->dev);
1100 atkbd->softrepeat = value;
1101 if (atkbd->softrepeat)
1102 atkbd->softraw = 1;
1103 atkbd_set_device_attrs(atkbd);
1104 input_register_device(&atkbd->dev);
1105 }
1106
1107 return count;
1108}
1109
1110
1111static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
1112{
1113 return sprintf(buf, "%d\n", atkbd->softraw ? 1 : 0);
1114}
1115
1116static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
1117{
1118 unsigned long value;
1119 char *rest;
1120
1121 value = simple_strtoul(buf, &rest, 10);
1122 if (*rest || value > 1)
1123 return -EINVAL;
1124
1125 if (atkbd->softraw != value) {
1126 /* unregister device as it's properties will change */
1127 input_unregister_device(&atkbd->dev);
1128 atkbd->softraw = value;
1129 atkbd_set_device_attrs(atkbd);
1130 input_register_device(&atkbd->dev);
1131 }
1132 return count;
1133}
1134
1135
1136static int __init atkbd_init(void)
1137{
1138 serio_register_driver(&atkbd_drv);
1139 return 0;
1140}
1141
1142static void __exit atkbd_exit(void)
1143{
1144 serio_unregister_driver(&atkbd_drv);
1145}
1146
1147module_init(atkbd_init);
1148module_exit(atkbd_exit);
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
new file mode 100644
index 000000000000..0f1220a0ceb5
--- /dev/null
+++ b/drivers/input/keyboard/corgikbd.c
@@ -0,0 +1,361 @@
1/*
2 * Keyboard driver for Sharp Corgi models (SL-C7xx)
3 *
4 * Copyright (c) 2004-2005 Richard Purdie
5 *
6 * Based on xtkbd.c/locomkbd.c
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/delay.h>
15#include <linux/device.h>
16#include <linux/init.h>
17#include <linux/input.h>
18#include <linux/interrupt.h>
19#include <linux/module.h>
20#include <linux/slab.h>
21#include <asm/irq.h>
22
23#include <asm/arch/corgi.h>
24#include <asm/arch/hardware.h>
25#include <asm/arch/pxa-regs.h>
26#include <asm/hardware/scoop.h>
27
28#define KB_ROWS 8
29#define KB_COLS 12
30#define KB_ROWMASK(r) (1 << (r))
31#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 )
32/* zero code, 124 scancodes + 3 hinge combinations */
33#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
34#define SCAN_INTERVAL (HZ/10)
35#define CORGIKBD_PRESSED 1
36
37#define HINGE_SCAN_INTERVAL (HZ/4)
38
39#define CORGI_KEY_CALENDER KEY_F1
40#define CORGI_KEY_ADDRESS KEY_F2
41#define CORGI_KEY_FN KEY_F3
42#define CORGI_KEY_OFF KEY_SUSPEND
43#define CORGI_KEY_EXOK KEY_F5
44#define CORGI_KEY_EXCANCEL KEY_F6
45#define CORGI_KEY_EXJOGDOWN KEY_F7
46#define CORGI_KEY_EXJOGUP KEY_F8
47#define CORGI_KEY_JAP1 KEY_LEFTCTRL
48#define CORGI_KEY_JAP2 KEY_LEFTALT
49#define CORGI_KEY_OK KEY_F11
50#define CORGI_KEY_MENU KEY_F12
51#define CORGI_HINGE_0 KEY_KP0
52#define CORGI_HINGE_1 KEY_KP1
53#define CORGI_HINGE_2 KEY_KP2
54
55static unsigned char corgikbd_keycode[NR_SCANCODES] = {
56 0, /* 0 */
57 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */
58 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */
59 KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */
60 CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
61 CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */
62 KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */
63 KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */
64 CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */
65 CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */
66};
67
68
69struct corgikbd {
70 unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)];
71 struct input_dev input;
72 char phys[32];
73
74 unsigned char state[ARRAY_SIZE(corgikbd_keycode)];
75 spinlock_t lock;
76
77 struct timer_list timer;
78 struct timer_list htimer;
79};
80
81static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data)
82{
83 if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) {
84 corgikbd_data->state[scancode] |= CORGIKBD_PRESSED;
85 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1);
86 if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
87 input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
88 } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) {
89 corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED;
90 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0);
91 }
92}
93
94#define KB_DISCHARGE_DELAY 10
95#define KB_ACTIVATE_DELAY 10
96
97/* Helper functions for reading the keyboard matrix
98 * Note: We should really be using pxa_gpio_mode to alter GPDR but it
99 * requires a function call per GPIO bit which is excessive
100 * when we need to access 12 bits at once multiple times.
101 * These functions must be called within local_irq_save()/local_irq_restore()
102 * or similar.
103 */
104static inline void corgikbd_discharge_all(void)
105{
106 // STROBE All HiZ
107 GPCR2 = CORGI_GPIO_ALL_STROBE_BIT;
108 GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT;
109}
110
111static inline void corgikbd_activate_all(void)
112{
113 // STROBE ALL -> High
114 GPSR2 = CORGI_GPIO_ALL_STROBE_BIT;
115 GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT;
116
117 udelay(KB_DISCHARGE_DELAY);
118
119 // Clear any interrupts we may have triggered when altering the GPIO lines
120 GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT;
121 GEDR2 = CORGI_GPIO_LOW_SENSE_BIT;
122}
123
124static inline void corgikbd_activate_col(int col)
125{
126 // STROBE col -> High, not col -> HiZ
127 GPSR2 = CORGI_GPIO_STROBE_BIT(col);
128 GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
129}
130
131static inline void corgikbd_reset_col(int col)
132{
133 // STROBE col -> Low
134 GPCR2 = CORGI_GPIO_STROBE_BIT(col);
135 // STROBE col -> out, not col -> HiZ
136 GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
137}
138
139#define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT))
140
141/*
142 * The corgi keyboard only generates interrupts when a key is pressed.
143 * When a key is pressed, we enable a timer which then scans the
144 * keyboard to detect when the key is released.
145 */
146
147/* Scan the hardware keyboard and push any changes up through the input layer */
148static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
149{
150 unsigned int row, col, rowd, scancode;
151 unsigned long flags;
152 unsigned int num_pressed;
153
154 spin_lock_irqsave(&corgikbd_data->lock, flags);
155
156 if (regs)
157 input_regs(&corgikbd_data->input, regs);
158
159 num_pressed = 0;
160 for (col = 0; col < KB_COLS; col++) {
161 /*
162 * Discharge the output driver capacitatance
163 * in the keyboard matrix. (Yes it is significant..)
164 */
165
166 corgikbd_discharge_all();
167 udelay(KB_DISCHARGE_DELAY);
168
169 corgikbd_activate_col(col);
170 udelay(KB_ACTIVATE_DELAY);
171
172 rowd = GET_ROWS_STATUS(col);
173 for (row = 0; row < KB_ROWS; row++) {
174 scancode = SCANCODE(row, col);
175 handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data);
176 if (rowd & KB_ROWMASK(row))
177 num_pressed++;
178 }
179 corgikbd_reset_col(col);
180 }
181
182 corgikbd_activate_all();
183
184 input_sync(&corgikbd_data->input);
185
186 /* if any keys are pressed, enable the timer */
187 if (num_pressed)
188 mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL);
189
190 spin_unlock_irqrestore(&corgikbd_data->lock, flags);
191}
192
193/*
194 * corgi keyboard interrupt handler.
195 */
196static irqreturn_t corgikbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
197{
198 struct corgikbd *corgikbd_data = dev_id;
199
200 if (!timer_pending(&corgikbd_data->timer)) {
201 /** wait chattering delay **/
202 udelay(20);
203 corgikbd_scankeyboard(corgikbd_data, regs);
204 }
205
206 return IRQ_HANDLED;
207}
208
209/*
210 * corgi timer checking for released keys
211 */
212static void corgikbd_timer_callback(unsigned long data)
213{
214 struct corgikbd *corgikbd_data = (struct corgikbd *) data;
215 corgikbd_scankeyboard(corgikbd_data, NULL);
216}
217
218/*
219 * The hinge switches generate no interrupt so they need to be
220 * monitored by a timer.
221 *
222 * When we detect changes, we debounce it and then pass the three
223 * positions the system can take as keypresses to the input system.
224 */
225
226#define HINGE_STABLE_COUNT 2
227static int sharpsl_hinge_state;
228static int hinge_count;
229
230static void corgikbd_hinge_timer(unsigned long data)
231{
232 struct corgikbd *corgikbd_data = (struct corgikbd *) data;
233 unsigned long gprr;
234 unsigned long flags;
235
236 gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
237 if (gprr != sharpsl_hinge_state) {
238 hinge_count = 0;
239 sharpsl_hinge_state = gprr;
240 } else if (hinge_count < HINGE_STABLE_COUNT) {
241 hinge_count++;
242 if (hinge_count >= HINGE_STABLE_COUNT) {
243 spin_lock_irqsave(&corgikbd_data->lock, flags);
244
245 handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */
246 handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */
247 handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed */
248 input_sync(&corgikbd_data->input);
249
250 spin_unlock_irqrestore(&corgikbd_data->lock, flags);
251 }
252 }
253 mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
254}
255
256static int __init corgikbd_probe(struct device *dev)
257{
258 int i;
259 struct corgikbd *corgikbd;
260
261 corgikbd = kcalloc(1, sizeof(struct corgikbd), GFP_KERNEL);
262 if (!corgikbd)
263 return -ENOMEM;
264
265 dev_set_drvdata(dev,corgikbd);
266 strcpy(corgikbd->phys, "corgikbd/input0");
267
268 spin_lock_init(corgikbd->lock);
269
270 /* Init Keyboard rescan timer */
271 init_timer(&corgikbd->timer);
272 corgikbd->timer.function = corgikbd_timer_callback;
273 corgikbd->timer.data = (unsigned long) corgikbd;
274
275 /* Init Hinge Timer */
276 init_timer(&corgikbd->htimer);
277 corgikbd->htimer.function = corgikbd_hinge_timer;
278 corgikbd->htimer.data = (unsigned long) corgikbd;
279
280 init_input_dev(&corgikbd->input);
281 corgikbd->input.private = corgikbd;
282 corgikbd->input.name = "Corgi Keyboard";
283 corgikbd->input.dev = dev;
284 corgikbd->input.phys = corgikbd->phys;
285 corgikbd->input.id.bustype = BUS_HOST;
286 corgikbd->input.id.vendor = 0x0001;
287 corgikbd->input.id.product = 0x0001;
288 corgikbd->input.id.version = 0x0100;
289 corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR);
290 corgikbd->input.keycode = corgikbd->keycode;
291 corgikbd->input.keycodesize = sizeof(unsigned char);
292 corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
293
294 memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
295 for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
296 set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
297 clear_bit(0, corgikbd->input.keybit);
298
299 input_register_device(&corgikbd->input);
300 mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
301
302 /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
303 for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
304 pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
305 if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt,
306 SA_INTERRUPT, "corgikbd", corgikbd))
307 printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i);
308 else
309 set_irq_type(CORGI_IRQ_GPIO_KEY_SENSE(i),IRQT_RISING);
310 }
311
312 /* Set Strobe lines as outputs - set high */
313 for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
314 pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
315
316 printk(KERN_INFO "input: Corgi Keyboard Registered\n");
317
318 return 0;
319}
320
321static int corgikbd_remove(struct device *dev)
322{
323 int i;
324 struct corgikbd *corgikbd = dev_get_drvdata(dev);
325
326 for (i = 0; i < CORGI_KEY_SENSE_NUM; i++)
327 free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd);
328
329 del_timer_sync(&corgikbd->htimer);
330 del_timer_sync(&corgikbd->timer);
331
332 input_unregister_device(&corgikbd->input);
333
334 kfree(corgikbd);
335
336 return 0;
337}
338
339static struct device_driver corgikbd_driver = {
340 .name = "corgi-keyboard",
341 .bus = &platform_bus_type,
342 .probe = corgikbd_probe,
343 .remove = corgikbd_remove,
344};
345
346static int __devinit corgikbd_init(void)
347{
348 return driver_register(&corgikbd_driver);
349}
350
351static void __exit corgikbd_exit(void)
352{
353 driver_unregister(&corgikbd_driver);
354}
355
356module_init(corgikbd_init);
357module_exit(corgikbd_exit);
358
359MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
360MODULE_DESCRIPTION("Corgi Keyboard Driver");
361MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
new file mode 100644
index 000000000000..ef78bffed5e7
--- /dev/null
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -0,0 +1,375 @@
1/*
2 * Generic linux-input device driver for keyboard devices
3 *
4 * Copyright (c) 2001 Brian S. Julin
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL").
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 *
29 * References:
30 * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A
31 *
32 */
33
34#include <linux/hil.h>
35#include <linux/input.h>
36#include <linux/serio.h>
37#include <linux/kernel.h>
38#include <linux/module.h>
39#include <linux/init.h>
40#include <linux/slab.h>
41#include <linux/pci_ids.h>
42
43#define PREFIX "HIL KEYB: "
44#define HIL_GENERIC_NAME "HIL keyboard"
45
46MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
47MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
48MODULE_LICENSE("Dual BSD/GPL");
49
50#define HIL_KBD_MAX_LENGTH 16
51
52#define HIL_KBD_SET1_UPBIT 0x01
53#define HIL_KBD_SET1_SHIFT 1
54static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] =
55 { HIL_KEYCODES_SET1 };
56
57#define HIL_KBD_SET2_UPBIT 0x01
58#define HIL_KBD_SET2_SHIFT 1
59/* Set2 is user defined */
60
61#define HIL_KBD_SET3_UPBIT 0x80
62#define HIL_KBD_SET3_SHIFT 0
63static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
64 { HIL_KEYCODES_SET3 };
65
66static char hil_language[][16] = { HIL_LOCALE_MAP };
67
68struct hil_kbd {
69 struct input_dev dev;
70 struct serio *serio;
71
72 /* Input buffer and index for packets from HIL bus. */
73 hil_packet data[HIL_KBD_MAX_LENGTH];
74 int idx4; /* four counts per packet */
75
76 /* Raw device info records from HIL bus, see hil.h for fields. */
77 char idd[HIL_KBD_MAX_LENGTH]; /* DID byte and IDD record */
78 char rsc[HIL_KBD_MAX_LENGTH]; /* RSC record */
79 char exd[HIL_KBD_MAX_LENGTH]; /* EXD record */
80 char rnm[HIL_KBD_MAX_LENGTH + 1]; /* RNM record + NULL term. */
81
82 /* Something to sleep around with. */
83 struct semaphore sem;
84};
85
86/* Process a complete packet after transfer from the HIL */
87static void hil_kbd_process_record(struct hil_kbd *kbd)
88{
89 struct input_dev *dev = &kbd->dev;
90 hil_packet *data = kbd->data;
91 hil_packet p;
92 int idx, i, cnt;
93
94 idx = kbd->idx4/4;
95 p = data[idx - 1];
96
97 if ((p & ~HIL_CMDCT_POL) ==
98 (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
99 if ((p & ~HIL_CMDCT_RPL) ==
100 (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
101
102 /* Not a poll response. See if we are loading config records. */
103 switch (p & HIL_PKT_DATA_MASK) {
104 case HIL_CMD_IDD:
105 for (i = 0; i < idx; i++)
106 kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
107 for (; i < HIL_KBD_MAX_LENGTH; i++)
108 kbd->idd[i] = 0;
109 break;
110 case HIL_CMD_RSC:
111 for (i = 0; i < idx; i++)
112 kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
113 for (; i < HIL_KBD_MAX_LENGTH; i++)
114 kbd->rsc[i] = 0;
115 break;
116 case HIL_CMD_EXD:
117 for (i = 0; i < idx; i++)
118 kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
119 for (; i < HIL_KBD_MAX_LENGTH; i++)
120 kbd->exd[i] = 0;
121 break;
122 case HIL_CMD_RNM:
123 for (i = 0; i < idx; i++)
124 kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
125 for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
126 kbd->rnm[i] = '\0';
127 break;
128 default:
129 /* These occur when device isn't present */
130 if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break;
131 /* Anything else we'd like to know about. */
132 printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
133 break;
134 }
135 goto out;
136
137 report:
138 cnt = 1;
139 switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
140 case HIL_POL_CHARTYPE_NONE:
141 break;
142 case HIL_POL_CHARTYPE_ASCII:
143 while (cnt < idx - 1)
144 input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
145 break;
146 case HIL_POL_CHARTYPE_RSVD1:
147 case HIL_POL_CHARTYPE_RSVD2:
148 case HIL_POL_CHARTYPE_BINARY:
149 while (cnt < idx - 1)
150 input_report_key(dev, kbd->data[cnt++], 1);
151 break;
152 case HIL_POL_CHARTYPE_SET1:
153 while (cnt < idx - 1) {
154 unsigned int key;
155 int up;
156 key = kbd->data[cnt++];
157 up = key & HIL_KBD_SET1_UPBIT;
158 key &= (~HIL_KBD_SET1_UPBIT & 0xff);
159 key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT];
160 if (key != KEY_RESERVED)
161 input_report_key(dev, key, !up);
162 }
163 break;
164 case HIL_POL_CHARTYPE_SET2:
165 while (cnt < idx - 1) {
166 unsigned int key;
167 int up;
168 key = kbd->data[cnt++];
169 up = key & HIL_KBD_SET2_UPBIT;
170 key &= (~HIL_KBD_SET1_UPBIT & 0xff);
171 key = key >> HIL_KBD_SET2_SHIFT;
172 if (key != KEY_RESERVED)
173 input_report_key(dev, key, !up);
174 }
175 break;
176 case HIL_POL_CHARTYPE_SET3:
177 while (cnt < idx - 1) {
178 unsigned int key;
179 int up;
180 key = kbd->data[cnt++];
181 up = key & HIL_KBD_SET3_UPBIT;
182 key &= (~HIL_KBD_SET1_UPBIT & 0xff);
183 key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT];
184 if (key != KEY_RESERVED)
185 input_report_key(dev, key, !up);
186 }
187 break;
188 }
189 out:
190 kbd->idx4 = 0;
191 up(&kbd->sem);
192}
193
194static void hil_kbd_process_err(struct hil_kbd *kbd) {
195 printk(KERN_WARNING PREFIX "errored HIL packet\n");
196 kbd->idx4 = 0;
197 up(&kbd->sem);
198}
199
200static irqreturn_t hil_kbd_interrupt(struct serio *serio,
201 unsigned char data, unsigned int flags, struct pt_regs *regs)
202{
203 struct hil_kbd *kbd;
204 hil_packet packet;
205 int idx;
206
207 kbd = (struct hil_kbd *)serio->private;
208 if (kbd == NULL) {
209 BUG();
210 return IRQ_HANDLED;
211 }
212
213 if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
214 hil_kbd_process_err(kbd);
215 return IRQ_HANDLED;
216 }
217 idx = kbd->idx4/4;
218 if (!(kbd->idx4 % 4)) kbd->data[idx] = 0;
219 packet = kbd->data[idx];
220 packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
221 kbd->data[idx] = packet;
222
223 /* Records of N 4-byte hil_packets must terminate with a command. */
224 if ((++(kbd->idx4)) % 4) return IRQ_HANDLED;
225 if ((packet & 0xffff0000) != HIL_ERR_INT) {
226 hil_kbd_process_err(kbd);
227 return IRQ_HANDLED;
228 }
229 if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd);
230 return IRQ_HANDLED;
231}
232
233static void hil_kbd_disconnect(struct serio *serio)
234{
235 struct hil_kbd *kbd;
236
237 kbd = (struct hil_kbd *)serio->private;
238 if (kbd == NULL) {
239 BUG();
240 return;
241 }
242
243 input_unregister_device(&kbd->dev);
244 serio_close(serio);
245 kfree(kbd);
246}
247
248static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
249{
250 struct hil_kbd *kbd;
251 uint8_t did, *idd;
252 int i;
253
254 if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
255
256 if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return;
257 memset(kbd, 0, sizeof(struct hil_kbd));
258
259 if (serio_open(serio, drv)) goto bail0;
260
261 serio->private = kbd;
262 kbd->serio = serio;
263 kbd->dev.private = kbd;
264
265 init_MUTEX_LOCKED(&(kbd->sem));
266
267 /* Get device info. MLC driver supplies devid/status/etc. */
268 serio->write(serio, 0);
269 serio->write(serio, 0);
270 serio->write(serio, HIL_PKT_CMD >> 8);
271 serio->write(serio, HIL_CMD_IDD);
272 down(&(kbd->sem));
273
274 serio->write(serio, 0);
275 serio->write(serio, 0);
276 serio->write(serio, HIL_PKT_CMD >> 8);
277 serio->write(serio, HIL_CMD_RSC);
278 down(&(kbd->sem));
279
280 serio->write(serio, 0);
281 serio->write(serio, 0);
282 serio->write(serio, HIL_PKT_CMD >> 8);
283 serio->write(serio, HIL_CMD_RNM);
284 down(&(kbd->sem));
285
286 serio->write(serio, 0);
287 serio->write(serio, 0);
288 serio->write(serio, HIL_PKT_CMD >> 8);
289 serio->write(serio, HIL_CMD_EXD);
290 down(&(kbd->sem));
291
292 up(&(kbd->sem));
293
294 did = kbd->idd[0];
295 idd = kbd->idd + 1;
296 switch (did & HIL_IDD_DID_TYPE_MASK) {
297 case HIL_IDD_DID_TYPE_KB_INTEGRAL:
298 case HIL_IDD_DID_TYPE_KB_ITF:
299 case HIL_IDD_DID_TYPE_KB_RSVD:
300 case HIL_IDD_DID_TYPE_CHAR:
301 printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n",
302 did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
303 break;
304 default:
305 goto bail1;
306 }
307
308 if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
309 printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
310 goto bail1;
311 }
312
313
314 kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
315 kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
316 kbd->dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
317 kbd->dev.keycodesize = sizeof(hil_kbd_set1[0]);
318 kbd->dev.keycode = hil_kbd_set1;
319 kbd->dev.name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
320 kbd->dev.phys = "hpkbd/input0"; /* XXX */
321
322 kbd->dev.id.bustype = BUS_HIL;
323 kbd->dev.id.vendor = PCI_VENDOR_ID_HP;
324 kbd->dev.id.product = 0x0001; /* TODO: get from kbd->rsc */
325 kbd->dev.id.version = 0x0100; /* TODO: get from kbd->rsc */
326 kbd->dev.dev = &serio->dev;
327
328 for (i = 0; i < 128; i++) {
329 set_bit(hil_kbd_set1[i], kbd->dev.keybit);
330 set_bit(hil_kbd_set3[i], kbd->dev.keybit);
331 }
332 clear_bit(0, kbd->dev.keybit);
333
334 input_register_device(&kbd->dev);
335 printk(KERN_INFO "input: %s, ID: %d\n",
336 kbd->dev.name, did);
337
338 serio->write(serio, 0);
339 serio->write(serio, 0);
340 serio->write(serio, HIL_PKT_CMD >> 8);
341 serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
342 down(&(kbd->sem));
343 up(&(kbd->sem));
344
345 return;
346 bail1:
347 serio_close(serio);
348 bail0:
349 kfree(kbd);
350}
351
352
353struct serio_driver hil_kbd_serio_drv = {
354 .driver = {
355 .name = "hil_kbd",
356 },
357 .description = "HP HIL keyboard driver",
358 .connect = hil_kbd_connect,
359 .disconnect = hil_kbd_disconnect,
360 .interrupt = hil_kbd_interrupt
361};
362
363static int __init hil_kbd_init(void)
364{
365 serio_register_driver(&hil_kbd_serio_drv);
366 return 0;
367}
368
369static void __exit hil_kbd_exit(void)
370{
371 serio_unregister_driver(&hil_kbd_serio_drv);
372}
373
374module_init(hil_kbd_init);
375module_exit(hil_kbd_exit);
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
new file mode 100644
index 000000000000..eecb77db0847
--- /dev/null
+++ b/drivers/input/keyboard/hilkbd.c
@@ -0,0 +1,343 @@
1/*
2 * linux/drivers/hil/hilkbd.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 * Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
6 * Copyright (C) 1999-2003 Helge Deller <deller@gmx.de>
7 *
8 * Very basic HP Human Interface Loop (HIL) driver.
9 * This driver handles the keyboard on HP300 (m68k) and on some
10 * HP700 (parisc) series machines.
11 *
12 *
13 * This file is subject to the terms and conditions of the GNU General Public
14 * License version 2. See the file COPYING in the main directory of this
15 * archive for more details.
16 */
17
18#include <linux/pci_ids.h>
19#include <linux/ioport.h>
20#include <linux/module.h>
21#include <linux/config.h>
22#include <linux/errno.h>
23#include <linux/input.h>
24#include <linux/init.h>
25#include <linux/irq.h>
26#include <linux/hil.h>
27#include <linux/spinlock.h>
28
29
30MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
31MODULE_DESCRIPTION("HIL keyboard driver (basic functionality)");
32MODULE_LICENSE("GPL v2");
33
34
35#if defined(CONFIG_PARISC)
36
37 #include <asm/io.h>
38 #include <asm/hardware.h>
39 #include <asm/parisc-device.h>
40 static unsigned long hil_base; /* HPA for the HIL device */
41 static unsigned int hil_irq;
42 #define HILBASE hil_base /* HPPA (parisc) port address */
43 #define HIL_DATA 0x800
44 #define HIL_CMD 0x801
45 #define HIL_IRQ hil_irq
46 #define hil_readb(p) gsc_readb(p)
47 #define hil_writeb(v,p) gsc_writeb((v),(p))
48
49#elif defined(CONFIG_HP300)
50
51 #define HILBASE 0xf0428000 /* HP300 (m86k) port address */
52 #define HIL_DATA 0x1
53 #define HIL_CMD 0x3
54 #define HIL_IRQ 2
55 #define hil_readb(p) readb(p)
56 #define hil_writeb(v,p) writeb((v),(p))
57
58#else
59#error "HIL is not supported on this platform"
60#endif
61
62
63
64/* HIL helper functions */
65
66#define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
67#define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
68#define hil_status() (hil_readb(HILBASE + HIL_CMD))
69#define hil_command(x) do { hil_writeb((x), HILBASE + HIL_CMD); } while (0)
70#define hil_read_data() (hil_readb(HILBASE + HIL_DATA))
71#define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)
72
73/* HIL constants */
74
75#define HIL_BUSY 0x02
76#define HIL_DATA_RDY 0x01
77
78#define HIL_SETARD 0xA0 /* set auto-repeat delay */
79#define HIL_SETARR 0xA2 /* set auto-repeat rate */
80#define HIL_SETTONE 0xA3 /* set tone generator */
81#define HIL_CNMT 0xB2 /* clear nmi */
82#define HIL_INTON 0x5C /* Turn on interrupts. */
83#define HIL_INTOFF 0x5D /* Turn off interrupts. */
84
85#define HIL_READKBDSADR 0xF9
86#define HIL_WRITEKBDSADR 0xE9
87
88static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
89 { HIL_KEYCODES_SET1 };
90
91/* HIL structure */
92static struct {
93 struct input_dev dev;
94
95 unsigned int curdev;
96
97 unsigned char s;
98 unsigned char c;
99 int valid;
100
101 unsigned char data[16];
102 unsigned int ptr;
103 spinlock_t lock;
104
105 void *dev_id; /* native bus device */
106} hil_dev;
107
108
109static void poll_finished(void)
110{
111 int down;
112 int key;
113 unsigned char scode;
114
115 switch (hil_dev.data[0]) {
116 case 0x40:
117 down = (hil_dev.data[1] & 1) == 0;
118 scode = hil_dev.data[1] >> 1;
119 key = hphilkeyb_keycode[scode];
120 input_report_key(&hil_dev.dev, key, down);
121 break;
122 }
123 hil_dev.curdev = 0;
124}
125
126static inline void handle_status(unsigned char s, unsigned char c)
127{
128 if (c & 0x8) {
129 /* End of block */
130 if (c & 0x10)
131 poll_finished();
132 } else {
133 if (c & 0x10) {
134 if (hil_dev.curdev)
135 poll_finished(); /* just in case */
136 hil_dev.curdev = c & 7;
137 hil_dev.ptr = 0;
138 }
139 }
140}
141
142static inline void handle_data(unsigned char s, unsigned char c)
143{
144 if (hil_dev.curdev) {
145 hil_dev.data[hil_dev.ptr++] = c;
146 hil_dev.ptr &= 15;
147 }
148}
149
150
151/*
152 * Handle HIL interrupts.
153 */
154static irqreturn_t hil_interrupt(int irq, void *handle, struct pt_regs *regs)
155{
156 unsigned char s, c;
157
158 s = hil_status();
159 c = hil_read_data();
160
161 switch (s >> 4) {
162 case 0x5:
163 handle_status(s, c);
164 break;
165 case 0x6:
166 handle_data(s, c);
167 break;
168 case 0x4:
169 hil_dev.s = s;
170 hil_dev.c = c;
171 mb();
172 hil_dev.valid = 1;
173 break;
174 }
175 return IRQ_HANDLED;
176}
177
178/*
179 * Send a command to the HIL
180 */
181
182static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
183{
184 unsigned long flags;
185
186 spin_lock_irqsave(&hil_dev.lock, flags);
187 while (hil_busy())
188 /* wait */;
189 hil_command(cmd);
190 while (len--) {
191 while (hil_busy())
192 /* wait */;
193 hil_write_data(*(data++));
194 }
195 spin_unlock_irqrestore(&hil_dev.lock, flags);
196}
197
198
199/*
200 * Initialise HIL.
201 */
202
203static int __init
204hil_keyb_init(void)
205{
206 unsigned char c;
207 unsigned int i, kbid;
208 wait_queue_head_t hil_wait;
209
210 if (hil_dev.dev.id.bustype) {
211 return -ENODEV; /* already initialized */
212 }
213
214#if defined(CONFIG_HP300)
215 if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
216 return -ENODEV;
217
218 request_region(HILBASE+HIL_DATA, 2, "hil");
219#endif
220
221 request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
222
223 /* Turn on interrupts */
224 hil_do(HIL_INTON, NULL, 0);
225
226 /* Look for keyboards */
227 hil_dev.valid = 0; /* clear any pending data */
228 hil_do(HIL_READKBDSADR, NULL, 0);
229
230 init_waitqueue_head(&hil_wait);
231 wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ);
232 if (!hil_dev.valid) {
233 printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n");
234 }
235
236 c = hil_dev.c;
237 hil_dev.valid = 0;
238 if (c == 0) {
239 kbid = -1;
240 printk(KERN_WARNING "HIL: no keyboard present.\n");
241 } else {
242 kbid = ffz(~c);
243 /* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */
244 }
245
246 /* set it to raw mode */
247 c = 0;
248 hil_do(HIL_WRITEKBDSADR, &c, 1);
249
250 init_input_dev(&hil_dev.dev);
251
252 for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
253 if (hphilkeyb_keycode[i] != KEY_RESERVED)
254 set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit);
255
256 hil_dev.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
257 hil_dev.dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
258 hil_dev.dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
259 hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]);
260 hil_dev.dev.keycode = hphilkeyb_keycode;
261 hil_dev.dev.name = "HIL keyboard";
262 hil_dev.dev.phys = "hpkbd/input0";
263
264 hil_dev.dev.id.bustype = BUS_HIL;
265 hil_dev.dev.id.vendor = PCI_VENDOR_ID_HP;
266 hil_dev.dev.id.product = 0x0001;
267 hil_dev.dev.id.version = 0x0010;
268
269 input_register_device(&hil_dev.dev);
270 printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
271 hil_dev.dev.name, kbid, HILBASE, HIL_IRQ);
272
273 return 0;
274}
275
276#if defined(CONFIG_PARISC)
277static int __init
278hil_init_chip(struct parisc_device *dev)
279{
280 if (!dev->irq) {
281 printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa);
282 return -ENODEV;
283 }
284
285 hil_base = dev->hpa;
286 hil_irq = dev->irq;
287 hil_dev.dev_id = dev;
288
289 printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq);
290
291 return hil_keyb_init();
292}
293
294static struct parisc_device_id hil_tbl[] = {
295 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
296 { 0, }
297};
298
299MODULE_DEVICE_TABLE(parisc, hil_tbl);
300
301static struct parisc_driver hil_driver = {
302 .name = "HIL",
303 .id_table = hil_tbl,
304 .probe = hil_init_chip,
305};
306#endif /* CONFIG_PARISC */
307
308
309
310
311
312static int __init hil_init(void)
313{
314#if defined(CONFIG_PARISC)
315 return register_parisc_driver(&hil_driver);
316#else
317 return hil_keyb_init();
318#endif
319}
320
321
322static void __exit hil_exit(void)
323{
324 if (HIL_IRQ) {
325 disable_irq(HIL_IRQ);
326 free_irq(HIL_IRQ, hil_dev.dev_id);
327 }
328
329 /* Turn off interrupts */
330 hil_do(HIL_INTOFF, NULL, 0);
331
332 input_unregister_device(&hil_dev.dev);
333
334#if defined(CONFIG_PARISC)
335 unregister_parisc_driver(&hil_driver);
336#else
337 release_region(HILBASE+HIL_DATA, 2);
338#endif
339}
340
341module_init(hil_init);
342module_exit(hil_exit);
343
diff --git a/drivers/input/keyboard/hpps2atkbd.h b/drivers/input/keyboard/hpps2atkbd.h
new file mode 100644
index 000000000000..dc33f6945222
--- /dev/null
+++ b/drivers/input/keyboard/hpps2atkbd.h
@@ -0,0 +1,110 @@
1/*
2 * drivers/input/keyboard/hpps2atkbd.h
3 *
4 * Copyright (c) 2004 Helge Deller <deller@gmx.de>
5 * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
6 * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org>
7 * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
8 *
9 * HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations & Laptops
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive
13 * for more details.
14 */
15
16
17/* Is the keyboard an RDI PrecisionBook? */
18#ifndef CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES
19# define CONFLICT(x,y) x
20#else
21# define CONFLICT(x,y) y
22#endif
23
24/* sadly RDI (Tadpole) decided to ship a different keyboard layout
25 than HP for their PS/2 laptop keyboard which leads to conflicting
26 keycodes between a normal HP PS/2 keyboard and a RDI Precisionbook.
27 HP: RDI: */
28#define C_07 CONFLICT( KEY_F12, KEY_F1 )
29#define C_11 CONFLICT( KEY_LEFTALT, KEY_LEFTCTRL )
30#define C_14 CONFLICT( KEY_LEFTCTRL, KEY_CAPSLOCK )
31#define C_58 CONFLICT( KEY_CAPSLOCK, KEY_RIGHTCTRL )
32#define C_61 CONFLICT( KEY_102ND, KEY_LEFT )
33
34/* Raw SET 2 scancode table */
35
36/* 00 */ KEY_RESERVED, KEY_F9, KEY_RESERVED, KEY_F5, KEY_F3, KEY_F1, KEY_F2, C_07,
37/* 08 */ KEY_ESC, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_GRAVE, KEY_F2,
38/* 10 */ KEY_RESERVED, C_11, KEY_LEFTSHIFT, KEY_RESERVED, C_14, KEY_Q, KEY_1, KEY_F3,
39/* 18 */ KEY_RESERVED, KEY_LEFTALT, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_F4,
40/* 20 */ KEY_RESERVED, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_F5,
41/* 28 */ KEY_RESERVED, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_F6,
42/* 30 */ KEY_RESERVED, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_F7,
43/* 38 */ KEY_RESERVED, KEY_RIGHTALT, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_F8,
44/* 40 */ KEY_RESERVED, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_F9,
45/* 48 */ KEY_RESERVED, KEY_DOT, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_F10,
46/* 50 */ KEY_RESERVED, KEY_RESERVED, KEY_APOSTROPHE,KEY_RESERVED, KEY_LEFTBRACE, KEY_EQUAL, KEY_F11, KEY_SYSRQ,
47/* 58 */ C_58, KEY_RIGHTSHIFT,KEY_ENTER, KEY_RIGHTBRACE,KEY_BACKSLASH, KEY_BACKSLASH,KEY_F12, KEY_SCROLLLOCK,
48/* 60 */ KEY_DOWN, C_61, KEY_PAUSE, KEY_UP, KEY_DELETE, KEY_END, KEY_BACKSPACE, KEY_INSERT,
49/* 68 */ KEY_RESERVED, KEY_KP1, KEY_RIGHT, KEY_KP4, KEY_KP7, KEY_PAGEDOWN, KEY_HOME, KEY_PAGEUP,
50/* 70 */ KEY_KP0, KEY_KPDOT, KEY_KP2, KEY_KP5, KEY_KP6, KEY_KP8, KEY_ESC, KEY_NUMLOCK,
51/* 78 */ KEY_F11, KEY_KPPLUS, KEY_KP3, KEY_KPMINUS, KEY_KPASTERISK,KEY_KP9, KEY_SCROLLLOCK,KEY_102ND,
52/* 80 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
53/* 88 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
54/* 90 */ KEY_RESERVED, KEY_RIGHTALT, 255, KEY_RESERVED, KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
55/* 98 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_CAPSLOCK, KEY_RESERVED, KEY_LEFTMETA,
56/* a0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RIGHTMETA,
57/* a8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_COMPOSE,
58/* b0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
59/* b8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
60/* c0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
61/* c8 */ KEY_RESERVED, KEY_RESERVED, KEY_KPSLASH, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
62/* d0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
63/* d8 */ KEY_RESERVED, KEY_RESERVED, KEY_KPENTER, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
64/* e0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
65/* e8 */ KEY_RESERVED, KEY_END, KEY_RESERVED, KEY_LEFT, KEY_HOME, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
66/* f0 */ KEY_INSERT, KEY_DELETE, KEY_DOWN, KEY_RESERVED, KEY_RIGHT, KEY_UP, KEY_RESERVED, KEY_PAUSE,
67/* f8 */ KEY_RESERVED, KEY_RESERVED, KEY_PAGEDOWN, KEY_RESERVED, KEY_SYSRQ, KEY_PAGEUP, KEY_RESERVED, KEY_RESERVED,
68
69/* These are offset for escaped keycodes: */
70
71/* 00 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_F7, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
72/* 08 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
73/* 10 */ KEY_RESERVED, KEY_RIGHTALT, KEY_RESERVED, KEY_RESERVED, KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
74/* 18 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
75/* 20 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
76/* 28 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
77/* 30 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
78/* 38 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
79/* 40 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
80/* 48 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
81/* 50 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
82/* 58 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
83/* 60 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
84/* 68 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
85/* 70 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
86/* 78 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
87/* 80 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
88/* 88 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
89/* 90 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
90/* 98 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
91/* a0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
92/* a8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
93/* b0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
94/* b8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
95/* c0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
96/* c8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
97/* d0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
98/* d8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
99/* e0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
100/* e8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
101/* f0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
102/* f8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED
103
104#undef CONFLICT
105#undef C_07
106#undef C_11
107#undef C_14
108#undef C_58
109#undef C_61
110
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
new file mode 100644
index 000000000000..2694ff2b5beb
--- /dev/null
+++ b/drivers/input/keyboard/lkkbd.c
@@ -0,0 +1,752 @@
1/*
2 * Copyright (C) 2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
3 */
4
5/*
6 * LK keyboard driver for Linux, based on sunkbd.c (C) by Vojtech Pavlik
7 */
8
9/*
10 * DEC LK201 and LK401 keyboard driver for Linux (primary for DECstations
11 * and VAXstations, but can also be used on any standard RS232 with an
12 * adaptor).
13 *
14 * DISCLAIMER: This works for _me_. If you break anything by using the
15 * information given below, I will _not_ be liable!
16 *
17 * RJ10 pinout: To DE9: Or DB25:
18 * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD)
19 * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND)
20 * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD)
21 * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!!
22 *
23 * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For
24 * RJ10, it's like this:
25 *
26 * __=__ Hold the plug in front of you, cable downwards,
27 * /___/| nose is hidden behind the plug. Now, pin 1 is at
28 * |1234|| the left side, pin 4 at the right and 2 and 3 are
29 * |IIII|| in between, of course:)
30 * | ||
31 * |____|/
32 * || So the adaptor consists of three connected cables
33 * || for data transmission (RxD and TxD) and signal ground.
34 * Additionally, you have to get +12V from somewhere.
35 * Most easily, you'll get that from a floppy or HDD power connector.
36 * It's the yellow cable there (black is ground and red is +5V).
37 *
38 * The keyboard and all the commands it understands are documented in
39 * "VCB02 Video Subsystem - Technical Manual", EK-104AA-TM-001. This
40 * document is LK201 specific, but LK401 is mostly compatible. It comes
41 * up in LK201 mode and doesn't report any of the additional keys it
42 * has. These need to be switched on with the LK_CMD_ENABLE_LK401
43 * command. You'll find this document (scanned .pdf file) on MANX,
44 * a search engine specific to DEC documentation. Try
45 * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1
46 */
47
48/*
49 * This program is free software; you can redistribute it and/or modify
50 * it under the terms of the GNU General Public License as published by
51 * the Free Software Foundation; either version 2 of the License, or
52 * (at your option) any later version.
53 *
54 * This program is distributed in the hope that it will be useful,
55 * but WITHOUT ANY WARRANTY; without even the implied warranty of
56 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57 * GNU General Public License for more details.
58 *
59 * You should have received a copy of the GNU General Public License
60 * along with this program; if not, write to the Free Software
61 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
62 *
63 * Should you need to contact me, the author, you can do so either by
64 * email or by paper mail:
65 * Jan-Benedict Glaw, Lilienstraße 16, 33790 Hörste (near Halle/Westf.),
66 * Germany.
67 */
68
69#include <linux/delay.h>
70#include <linux/slab.h>
71#include <linux/module.h>
72#include <linux/moduleparam.h>
73#include <linux/interrupt.h>
74#include <linux/init.h>
75#include <linux/input.h>
76#include <linux/serio.h>
77#include <linux/workqueue.h>
78
79#define DRIVER_DESC "LK keyboard driver"
80
81MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
82MODULE_DESCRIPTION (DRIVER_DESC);
83MODULE_LICENSE ("GPL");
84
85/*
86 * Known parameters:
87 * bell_volume
88 * keyclick_volume
89 * ctrlclick_volume
90 *
91 * Please notice that there's not yet an API to set these at runtime.
92 */
93static int bell_volume = 100; /* % */
94module_param (bell_volume, int, 0);
95MODULE_PARM_DESC (bell_volume, "Bell volume (in %). default is 100%");
96
97static int keyclick_volume = 100; /* % */
98module_param (keyclick_volume, int, 0);
99MODULE_PARM_DESC (keyclick_volume, "Keyclick volume (in %), default is 100%");
100
101static int ctrlclick_volume = 100; /* % */
102module_param (ctrlclick_volume, int, 0);
103MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
104
105static int lk201_compose_is_alt = 0;
106module_param (lk201_compose_is_alt, int, 0);
107MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key "
108 "will act as an Alt key");
109
110
111
112#undef LKKBD_DEBUG
113#ifdef LKKBD_DEBUG
114#define DBG(x...) printk (x)
115#else
116#define DBG(x...) do {} while (0)
117#endif
118
119/* LED control */
120#define LK_LED_WAIT 0x81
121#define LK_LED_COMPOSE 0x82
122#define LK_LED_SHIFTLOCK 0x84
123#define LK_LED_SCROLLLOCK 0x88
124#define LK_CMD_LED_ON 0x13
125#define LK_CMD_LED_OFF 0x11
126
127/* Mode control */
128#define LK_MODE_DOWN 0x80
129#define LK_MODE_AUTODOWN 0x82
130#define LK_MODE_UPDOWN 0x86
131#define LK_CMD_SET_MODE(mode,div) ((mode) | ((div) << 3))
132
133/* Misc commands */
134#define LK_CMD_ENABLE_KEYCLICK 0x1b
135#define LK_CMD_DISABLE_KEYCLICK 0x99
136#define LK_CMD_DISABLE_BELL 0xa1
137#define LK_CMD_SOUND_BELL 0xa7
138#define LK_CMD_ENABLE_BELL 0x23
139#define LK_CMD_DISABLE_CTRCLICK 0xb9
140#define LK_CMD_ENABLE_CTRCLICK 0xbb
141#define LK_CMD_SET_DEFAULTS 0xd3
142#define LK_CMD_POWERCYCLE_RESET 0xfd
143#define LK_CMD_ENABLE_LK401 0xe9
144#define LK_CMD_REQUEST_ID 0xab
145
146/* Misc responses from keyboard */
147#define LK_STUCK_KEY 0x3d
148#define LK_SELFTEST_FAILED 0x3e
149#define LK_ALL_KEYS_UP 0xb3
150#define LK_METRONOME 0xb4
151#define LK_OUTPUT_ERROR 0xb5
152#define LK_INPUT_ERROR 0xb6
153#define LK_KBD_LOCKED 0xb7
154#define LK_KBD_TEST_MODE_ACK 0xb8
155#define LK_PREFIX_KEY_DOWN 0xb9
156#define LK_MODE_CHANGE_ACK 0xba
157#define LK_RESPONSE_RESERVED 0xbb
158
159#define LK_NUM_KEYCODES 256
160#define LK_NUM_IGNORE_BYTES 6
161typedef u_int16_t lk_keycode_t;
162
163
164
165static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = {
166 [0x56] = KEY_F1,
167 [0x57] = KEY_F2,
168 [0x58] = KEY_F3,
169 [0x59] = KEY_F4,
170 [0x5a] = KEY_F5,
171 [0x64] = KEY_F6,
172 [0x65] = KEY_F7,
173 [0x66] = KEY_F8,
174 [0x67] = KEY_F9,
175 [0x68] = KEY_F10,
176 [0x71] = KEY_F11,
177 [0x72] = KEY_F12,
178 [0x73] = KEY_F13,
179 [0x74] = KEY_F14,
180 [0x7c] = KEY_F15,
181 [0x7d] = KEY_F16,
182 [0x80] = KEY_F17,
183 [0x81] = KEY_F18,
184 [0x82] = KEY_F19,
185 [0x83] = KEY_F20,
186 [0x8a] = KEY_FIND,
187 [0x8b] = KEY_INSERT,
188 [0x8c] = KEY_DELETE,
189 [0x8d] = KEY_SELECT,
190 [0x8e] = KEY_PAGEUP,
191 [0x8f] = KEY_PAGEDOWN,
192 [0x92] = KEY_KP0,
193 [0x94] = KEY_KPDOT,
194 [0x95] = KEY_KPENTER,
195 [0x96] = KEY_KP1,
196 [0x97] = KEY_KP2,
197 [0x98] = KEY_KP3,
198 [0x99] = KEY_KP4,
199 [0x9a] = KEY_KP5,
200 [0x9b] = KEY_KP6,
201 [0x9c] = KEY_KPCOMMA,
202 [0x9d] = KEY_KP7,
203 [0x9e] = KEY_KP8,
204 [0x9f] = KEY_KP9,
205 [0xa0] = KEY_KPMINUS,
206 [0xa1] = KEY_PROG1,
207 [0xa2] = KEY_PROG2,
208 [0xa3] = KEY_PROG3,
209 [0xa4] = KEY_PROG4,
210 [0xa7] = KEY_LEFT,
211 [0xa8] = KEY_RIGHT,
212 [0xa9] = KEY_DOWN,
213 [0xaa] = KEY_UP,
214 [0xab] = KEY_RIGHTSHIFT,
215 [0xac] = KEY_LEFTALT,
216 [0xad] = KEY_COMPOSE, /* Right Compose, that is. */
217 [0xae] = KEY_LEFTSHIFT, /* Same as KEY_RIGHTSHIFT on LK201 */
218 [0xaf] = KEY_LEFTCTRL,
219 [0xb0] = KEY_CAPSLOCK,
220 [0xb1] = KEY_COMPOSE, /* Left Compose, that is. */
221 [0xb2] = KEY_RIGHTALT,
222 [0xbc] = KEY_BACKSPACE,
223 [0xbd] = KEY_ENTER,
224 [0xbe] = KEY_TAB,
225 [0xbf] = KEY_ESC,
226 [0xc0] = KEY_1,
227 [0xc1] = KEY_Q,
228 [0xc2] = KEY_A,
229 [0xc3] = KEY_Z,
230 [0xc5] = KEY_2,
231 [0xc6] = KEY_W,
232 [0xc7] = KEY_S,
233 [0xc8] = KEY_X,
234 [0xc9] = KEY_102ND,
235 [0xcb] = KEY_3,
236 [0xcc] = KEY_E,
237 [0xcd] = KEY_D,
238 [0xce] = KEY_C,
239 [0xd0] = KEY_4,
240 [0xd1] = KEY_R,
241 [0xd2] = KEY_F,
242 [0xd3] = KEY_V,
243 [0xd4] = KEY_SPACE,
244 [0xd6] = KEY_5,
245 [0xd7] = KEY_T,
246 [0xd8] = KEY_G,
247 [0xd9] = KEY_B,
248 [0xdb] = KEY_6,
249 [0xdc] = KEY_Y,
250 [0xdd] = KEY_H,
251 [0xde] = KEY_N,
252 [0xe0] = KEY_7,
253 [0xe1] = KEY_U,
254 [0xe2] = KEY_J,
255 [0xe3] = KEY_M,
256 [0xe5] = KEY_8,
257 [0xe6] = KEY_I,
258 [0xe7] = KEY_K,
259 [0xe8] = KEY_COMMA,
260 [0xea] = KEY_9,
261 [0xeb] = KEY_O,
262 [0xec] = KEY_L,
263 [0xed] = KEY_DOT,
264 [0xef] = KEY_0,
265 [0xf0] = KEY_P,
266 [0xf2] = KEY_SEMICOLON,
267 [0xf3] = KEY_SLASH,
268 [0xf5] = KEY_EQUAL,
269 [0xf6] = KEY_RIGHTBRACE,
270 [0xf7] = KEY_BACKSLASH,
271 [0xf9] = KEY_MINUS,
272 [0xfa] = KEY_LEFTBRACE,
273 [0xfb] = KEY_APOSTROPHE,
274};
275
276#define CHECK_LED(LED, BITS) do { \
277 if (test_bit (LED, lk->dev.led)) \
278 leds_on |= BITS; \
279 else \
280 leds_off |= BITS; \
281 } while (0)
282
283/*
284 * Per-keyboard data
285 */
286struct lkkbd {
287 lk_keycode_t keycode[LK_NUM_KEYCODES];
288 int ignore_bytes;
289 unsigned char id[LK_NUM_IGNORE_BYTES];
290 struct input_dev dev;
291 struct serio *serio;
292 struct work_struct tq;
293 char name[64];
294 char phys[32];
295 char type;
296 int bell_volume;
297 int keyclick_volume;
298 int ctrlclick_volume;
299};
300
301/*
302 * Calculate volume parameter byte for a given volume.
303 */
304static unsigned char
305volume_to_hw (int volume_percent)
306{
307 unsigned char ret = 0;
308
309 if (volume_percent < 0)
310 volume_percent = 0;
311 if (volume_percent > 100)
312 volume_percent = 100;
313
314 if (volume_percent >= 0)
315 ret = 7;
316 if (volume_percent >= 13) /* 12.5 */
317 ret = 6;
318 if (volume_percent >= 25)
319 ret = 5;
320 if (volume_percent >= 38) /* 37.5 */
321 ret = 4;
322 if (volume_percent >= 50)
323 ret = 3;
324 if (volume_percent >= 63) /* 62.5 */
325 ret = 2; /* This is the default volume */
326 if (volume_percent >= 75)
327 ret = 1;
328 if (volume_percent >= 88) /* 87.5 */
329 ret = 0;
330
331 ret |= 0x80;
332
333 return ret;
334}
335
336static void
337lkkbd_detection_done (struct lkkbd *lk)
338{
339 int i;
340
341 /*
342 * Reset setting for Compose key. Let Compose be KEY_COMPOSE.
343 */
344 lk->keycode[0xb1] = KEY_COMPOSE;
345
346 /*
347 * Print keyboard name and modify Compose=Alt on user's request.
348 */
349 switch (lk->id[4]) {
350 case 1:
351 sprintf (lk->name, "DEC LK201 keyboard");
352
353 if (lk201_compose_is_alt)
354 lk->keycode[0xb1] = KEY_LEFTALT;
355 break;
356
357 case 2:
358 sprintf (lk->name, "DEC LK401 keyboard");
359 break;
360
361 default:
362 sprintf (lk->name, "Unknown DEC keyboard");
363 printk (KERN_ERR "lkkbd: keyboard on %s is unknown, "
364 "please report to Jan-Benedict Glaw "
365 "<jbglaw@lug-owl.de>\n", lk->phys);
366 printk (KERN_ERR "lkkbd: keyboard ID'ed as:");
367 for (i = 0; i < LK_NUM_IGNORE_BYTES; i++)
368 printk (" 0x%02x", lk->id[i]);
369 printk ("\n");
370 break;
371 }
372 printk (KERN_INFO "lkkbd: keyboard on %s identified as: %s\n",
373 lk->phys, lk->name);
374
375 /*
376 * Report errors during keyboard boot-up.
377 */
378 switch (lk->id[2]) {
379 case 0x00:
380 /* All okay */
381 break;
382
383 case LK_STUCK_KEY:
384 printk (KERN_ERR "lkkbd: Stuck key on keyboard at "
385 "%s\n", lk->phys);
386 break;
387
388 case LK_SELFTEST_FAILED:
389 printk (KERN_ERR "lkkbd: Selftest failed on keyboard "
390 "at %s, keyboard may not work "
391 "properly\n", lk->phys);
392 break;
393
394 default:
395 printk (KERN_ERR "lkkbd: Unknown error %02x on "
396 "keyboard at %s\n", lk->id[2],
397 lk->phys);
398 break;
399 }
400
401 /*
402 * Try to hint user if there's a stuck key.
403 */
404 if (lk->id[2] == LK_STUCK_KEY && lk->id[3] != 0)
405 printk (KERN_ERR "Scancode of stuck key is 0x%02x, keycode "
406 "is 0x%04x\n", lk->id[3],
407 lk->keycode[lk->id[3]]);
408
409 return;
410}
411
412/*
413 * lkkbd_interrupt() is called by the low level driver when a character
414 * is received.
415 */
416static irqreturn_t
417lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
418 struct pt_regs *regs)
419{
420 struct lkkbd *lk = serio_get_drvdata (serio);
421 int i;
422
423 DBG (KERN_INFO "Got byte 0x%02x\n", data);
424
425 if (lk->ignore_bytes > 0) {
426 DBG (KERN_INFO "Ignoring a byte on %s\n",
427 lk->name);
428 lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
429
430 if (lk->ignore_bytes == 0)
431 lkkbd_detection_done (lk);
432
433 return IRQ_HANDLED;
434 }
435
436 switch (data) {
437 case LK_ALL_KEYS_UP:
438 input_regs (&lk->dev, regs);
439 for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++)
440 if (lk->keycode[i] != KEY_RESERVED)
441 input_report_key (&lk->dev, lk->keycode[i], 0);
442 input_sync (&lk->dev);
443 break;
444 case LK_METRONOME:
445 DBG (KERN_INFO "Got LK_METRONOME and don't "
446 "know how to handle...\n");
447 break;
448 case LK_OUTPUT_ERROR:
449 DBG (KERN_INFO "Got LK_OUTPUT_ERROR and don't "
450 "know how to handle...\n");
451 break;
452 case LK_INPUT_ERROR:
453 DBG (KERN_INFO "Got LK_INPUT_ERROR and don't "
454 "know how to handle...\n");
455 break;
456 case LK_KBD_LOCKED:
457 DBG (KERN_INFO "Got LK_KBD_LOCKED and don't "
458 "know how to handle...\n");
459 break;
460 case LK_KBD_TEST_MODE_ACK:
461 DBG (KERN_INFO "Got LK_KBD_TEST_MODE_ACK and don't "
462 "know how to handle...\n");
463 break;
464 case LK_PREFIX_KEY_DOWN:
465 DBG (KERN_INFO "Got LK_PREFIX_KEY_DOWN and don't "
466 "know how to handle...\n");
467 break;
468 case LK_MODE_CHANGE_ACK:
469 DBG (KERN_INFO "Got LK_MODE_CHANGE_ACK and ignored "
470 "it properly...\n");
471 break;
472 case LK_RESPONSE_RESERVED:
473 DBG (KERN_INFO "Got LK_RESPONSE_RESERVED and don't "
474 "know how to handle...\n");
475 break;
476 case 0x01:
477 DBG (KERN_INFO "Got 0x01, scheduling re-initialization\n");
478 lk->ignore_bytes = LK_NUM_IGNORE_BYTES;
479 lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
480 schedule_work (&lk->tq);
481 break;
482
483 default:
484 if (lk->keycode[data] != KEY_RESERVED) {
485 input_regs (&lk->dev, regs);
486 if (!test_bit (lk->keycode[data], lk->dev.key))
487 input_report_key (&lk->dev, lk->keycode[data], 1);
488 else
489 input_report_key (&lk->dev, lk->keycode[data], 0);
490 input_sync (&lk->dev);
491 } else
492 printk (KERN_WARNING "%s: Unknown key with "
493 "scancode 0x%02x on %s.\n",
494 __FILE__, data, lk->name);
495 }
496
497 return IRQ_HANDLED;
498}
499
500/*
501 * lkkbd_event() handles events from the input module.
502 */
503static int
504lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
505 int value)
506{
507 struct lkkbd *lk = dev->private;
508 unsigned char leds_on = 0;
509 unsigned char leds_off = 0;
510
511 switch (type) {
512 case EV_LED:
513 CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK);
514 CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE);
515 CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK);
516 CHECK_LED (LED_SLEEP, LK_LED_WAIT);
517 if (leds_on != 0) {
518 lk->serio->write (lk->serio, LK_CMD_LED_ON);
519 lk->serio->write (lk->serio, leds_on);
520 }
521 if (leds_off != 0) {
522 lk->serio->write (lk->serio, LK_CMD_LED_OFF);
523 lk->serio->write (lk->serio, leds_off);
524 }
525 return 0;
526
527 case EV_SND:
528 switch (code) {
529 case SND_CLICK:
530 if (value == 0) {
531 DBG ("%s: Deactivating key clicks\n", __FUNCTION__);
532 lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK);
533 lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK);
534 } else {
535 DBG ("%s: Activating key clicks\n", __FUNCTION__);
536 lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
537 lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
538 lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
539 lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume));
540 }
541 return 0;
542
543 case SND_BELL:
544 if (value != 0)
545 lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
546
547 return 0;
548 }
549 break;
550
551 default:
552 printk (KERN_ERR "%s (): Got unknown type %d, code %d, value %d\n",
553 __FUNCTION__, type, code, value);
554 }
555
556 return -1;
557}
558
559/*
560 * lkkbd_reinit() sets leds and beeps to a state the computer remembers they
561 * were in.
562 */
563static void
564lkkbd_reinit (void *data)
565{
566 struct lkkbd *lk = data;
567 int division;
568 unsigned char leds_on = 0;
569 unsigned char leds_off = 0;
570
571 /* Ask for ID */
572 lk->serio->write (lk->serio, LK_CMD_REQUEST_ID);
573
574 /* Reset parameters */
575 lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS);
576
577 /* Set LEDs */
578 CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK);
579 CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE);
580 CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK);
581 CHECK_LED (LED_SLEEP, LK_LED_WAIT);
582 if (leds_on != 0) {
583 lk->serio->write (lk->serio, LK_CMD_LED_ON);
584 lk->serio->write (lk->serio, leds_on);
585 }
586 if (leds_off != 0) {
587 lk->serio->write (lk->serio, LK_CMD_LED_OFF);
588 lk->serio->write (lk->serio, leds_off);
589 }
590
591 /*
592 * Try to activate extended LK401 mode. This command will
593 * only work with a LK401 keyboard and grants access to
594 * LAlt, RAlt, RCompose and RShift.
595 */
596 lk->serio->write (lk->serio, LK_CMD_ENABLE_LK401);
597
598 /* Set all keys to UPDOWN mode */
599 for (division = 1; division <= 14; division++)
600 lk->serio->write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN,
601 division));
602
603 /* Enable bell and set volume */
604 lk->serio->write (lk->serio, LK_CMD_ENABLE_BELL);
605 lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume));
606
607 /* Enable/disable keyclick (and possibly set volume) */
608 if (test_bit (SND_CLICK, lk->dev.snd)) {
609 lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
610 lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
611 lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
612 lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume));
613 } else {
614 lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK);
615 lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK);
616 }
617
618 /* Sound the bell if needed */
619 if (test_bit (SND_BELL, lk->dev.snd))
620 lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
621}
622
623/*
624 * lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
625 */
626static int
627lkkbd_connect (struct serio *serio, struct serio_driver *drv)
628{
629 struct lkkbd *lk;
630 int i;
631 int err;
632
633 if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
634 return -ENOMEM;
635
636 memset (lk, 0, sizeof (struct lkkbd));
637
638 init_input_dev (&lk->dev);
639 set_bit (EV_KEY, lk->dev.evbit);
640 set_bit (EV_LED, lk->dev.evbit);
641 set_bit (EV_SND, lk->dev.evbit);
642 set_bit (EV_REP, lk->dev.evbit);
643 set_bit (LED_CAPSL, lk->dev.ledbit);
644 set_bit (LED_SLEEP, lk->dev.ledbit);
645 set_bit (LED_COMPOSE, lk->dev.ledbit);
646 set_bit (LED_SCROLLL, lk->dev.ledbit);
647 set_bit (SND_BELL, lk->dev.sndbit);
648 set_bit (SND_CLICK, lk->dev.sndbit);
649
650 lk->serio = serio;
651
652 INIT_WORK (&lk->tq, lkkbd_reinit, lk);
653
654 lk->bell_volume = bell_volume;
655 lk->keyclick_volume = keyclick_volume;
656 lk->ctrlclick_volume = ctrlclick_volume;
657
658 lk->dev.keycode = lk->keycode;
659 lk->dev.keycodesize = sizeof (lk_keycode_t);
660 lk->dev.keycodemax = LK_NUM_KEYCODES;
661
662 lk->dev.event = lkkbd_event;
663 lk->dev.private = lk;
664
665 serio_set_drvdata (serio, lk);
666
667 err = serio_open (serio, drv);
668 if (err) {
669 serio_set_drvdata (serio, NULL);
670 kfree (lk);
671 return err;
672 }
673
674 sprintf (lk->name, "DEC LK keyboard");
675 sprintf (lk->phys, "%s/input0", serio->phys);
676
677 memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
678 for (i = 0; i < LK_NUM_KEYCODES; i++)
679 set_bit (lk->keycode[i], lk->dev.keybit);
680
681 lk->dev.name = lk->name;
682 lk->dev.phys = lk->phys;
683 lk->dev.id.bustype = BUS_RS232;
684 lk->dev.id.vendor = SERIO_LKKBD;
685 lk->dev.id.product = 0;
686 lk->dev.id.version = 0x0100;
687 lk->dev.dev = &serio->dev;
688
689 input_register_device (&lk->dev);
690
691 printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys);
692 lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
693
694 return 0;
695}
696
697/*
698 * lkkbd_disconnect() unregisters and closes behind us.
699 */
700static void
701lkkbd_disconnect (struct serio *serio)
702{
703 struct lkkbd *lk = serio_get_drvdata (serio);
704
705 input_unregister_device (&lk->dev);
706 serio_close (serio);
707 serio_set_drvdata (serio, NULL);
708 kfree (lk);
709}
710
711static struct serio_device_id lkkbd_serio_ids[] = {
712 {
713 .type = SERIO_RS232,
714 .proto = SERIO_LKKBD,
715 .id = SERIO_ANY,
716 .extra = SERIO_ANY,
717 },
718 { 0 }
719};
720
721MODULE_DEVICE_TABLE(serio, lkkbd_serio_ids);
722
723static struct serio_driver lkkbd_drv = {
724 .driver = {
725 .name = "lkkbd",
726 },
727 .description = DRIVER_DESC,
728 .id_table = lkkbd_serio_ids,
729 .connect = lkkbd_connect,
730 .disconnect = lkkbd_disconnect,
731 .interrupt = lkkbd_interrupt,
732};
733
734/*
735 * The functions for insering/removing us as a module.
736 */
737static int __init
738lkkbd_init (void)
739{
740 serio_register_driver(&lkkbd_drv);
741 return 0;
742}
743
744static void __exit
745lkkbd_exit (void)
746{
747 serio_unregister_driver(&lkkbd_drv);
748}
749
750module_init (lkkbd_init);
751module_exit (lkkbd_exit);
752
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
new file mode 100644
index 000000000000..d3e9dd6a13cd
--- /dev/null
+++ b/drivers/input/keyboard/locomokbd.c
@@ -0,0 +1,309 @@
1/*
2 * Copyright (c) 2005 John Lenz
3 *
4 * Based on from xtkbd.c
5 */
6
7/*
8 * LoCoMo keyboard driver for Linux/ARM
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
28#include <linux/config.h>
29#include <linux/slab.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/input.h>
33#include <linux/delay.h>
34#include <linux/device.h>
35#include <linux/interrupt.h>
36#include <linux/ioport.h>
37
38#include <asm/hardware/locomo.h>
39#include <asm/irq.h>
40
41MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
42MODULE_DESCRIPTION("LoCoMo keyboard driver");
43MODULE_LICENSE("GPL");
44
45#define LOCOMOKBD_NUMKEYS 128
46
47#define KEY_ACTIVITY KEY_F16
48#define KEY_CONTACT KEY_F18
49#define KEY_CENTER KEY_F15
50
51static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
52 0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0, /* 0 - 9 */
53 0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT, /* 10 - 19 */
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 29 */
55 0, 0, 0, KEY_CENTER, 0, KEY_MAIL, 0, 0, 0, 0, /* 30 - 39 */
56 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RIGHT, /* 40 - 49 */
57 KEY_UP, KEY_LEFT, 0, 0, KEY_P, 0, KEY_O, KEY_I, KEY_Y, KEY_T, /* 50 - 59 */
58 KEY_E, KEY_W, 0, 0, 0, 0, KEY_DOWN, KEY_ENTER, 0, 0, /* 60 - 69 */
59 KEY_BACKSPACE, 0, KEY_L, KEY_U, KEY_H, KEY_R, KEY_D, KEY_Q, 0, 0, /* 70 - 79 */
60 0, 0, 0, 0, 0, 0, KEY_ENTER, KEY_RIGHTSHIFT, KEY_K, KEY_J, /* 80 - 89 */
61 KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */
62 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */
63 KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */
64 KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */
65};
66
67#define KB_ROWS 16
68#define KB_COLS 8
69#define KB_ROWMASK(r) (1 << (r))
70#define SCANCODE(c,r) ( ((c)<<4) + (r) + 1 )
71#define NR_SCANCODES 128
72
73#define KB_DELAY 8
74#define SCAN_INTERVAL (HZ/10)
75#define LOCOMOKBD_PRESSED 1
76
77struct locomokbd {
78 unsigned char keycode[LOCOMOKBD_NUMKEYS];
79 struct input_dev input;
80 char phys[32];
81
82 struct locomo_dev *ldev;
83 unsigned long base;
84 spinlock_t lock;
85
86 struct timer_list timer;
87};
88
89/* helper functions for reading the keyboard matrix */
90static inline void locomokbd_charge_all(unsigned long membase)
91{
92 locomo_writel(0x00FF, membase + LOCOMO_KSC);
93}
94
95static inline void locomokbd_activate_all(unsigned long membase)
96{
97 unsigned long r;
98
99 locomo_writel(0, membase + LOCOMO_KSC);
100 r = locomo_readl(membase + LOCOMO_KIC);
101 r &= 0xFEFF;
102 locomo_writel(r, membase + LOCOMO_KIC);
103}
104
105static inline void locomokbd_activate_col(unsigned long membase, int col)
106{
107 unsigned short nset;
108 unsigned short nbset;
109
110 nset = 0xFF & ~(1 << col);
111 nbset = (nset << 8) + nset;
112 locomo_writel(nbset, membase + LOCOMO_KSC);
113}
114
115static inline void locomokbd_reset_col(unsigned long membase, int col)
116{
117 unsigned short nbset;
118
119 nbset = ((0xFF & ~(1 << col)) << 8) + 0xFF;
120 locomo_writel(nbset, membase + LOCOMO_KSC);
121}
122
123/*
124 * The LoCoMo keyboard only generates interrupts when a key is pressed.
125 * So when a key is pressed, we enable a timer. This timer scans the
126 * keyboard, and this is how we detect when the key is released.
127 */
128
129/* Scan the hardware keyboard and push any changes up through the input layer */
130static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs)
131{
132 unsigned int row, col, rowd, scancode;
133 unsigned long flags;
134 unsigned int num_pressed;
135 unsigned long membase = locomokbd->base;
136
137 spin_lock_irqsave(&locomokbd->lock, flags);
138
139 if (regs)
140 input_regs(&locomokbd->input, regs);
141
142 locomokbd_charge_all(membase);
143
144 num_pressed = 0;
145 for (col = 0; col < KB_COLS; col++) {
146
147 locomokbd_activate_col(membase, col);
148 udelay(KB_DELAY);
149
150 rowd = ~locomo_readl(membase + LOCOMO_KIB);
151 for (row = 0; row < KB_ROWS; row++ ) {
152 scancode = SCANCODE(col, row);
153 if (rowd & KB_ROWMASK(row)) {
154 num_pressed += 1;
155 input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 1);
156 } else {
157 input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 0);
158 }
159 }
160 locomokbd_reset_col(membase, col);
161 }
162 locomokbd_activate_all(membase);
163
164 input_sync(&locomokbd->input);
165
166 /* if any keys are pressed, enable the timer */
167 if (num_pressed)
168 mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
169
170 spin_unlock_irqrestore(&locomokbd->lock, flags);
171}
172
173/*
174 * LoCoMo keyboard interrupt handler.
175 */
176static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
177{
178 struct locomokbd *locomokbd = dev_id;
179 /** wait chattering delay **/
180 udelay(100);
181
182 locomokbd_scankeyboard(locomokbd, regs);
183
184 return IRQ_HANDLED;
185}
186
187/*
188 * LoCoMo timer checking for released keys
189 */
190static void locomokbd_timer_callback(unsigned long data)
191{
192 struct locomokbd *locomokbd = (struct locomokbd *) data;
193 locomokbd_scankeyboard(locomokbd, NULL);
194}
195
196static int locomokbd_probe(struct locomo_dev *dev)
197{
198 struct locomokbd *locomokbd;
199 int i, ret;
200
201 locomokbd = kmalloc(sizeof(struct locomokbd), GFP_KERNEL);
202 if (!locomokbd)
203 return -ENOMEM;
204
205 memset(locomokbd, 0, sizeof(struct locomokbd));
206
207 /* try and claim memory region */
208 if (!request_mem_region((unsigned long) dev->mapbase,
209 dev->length,
210 LOCOMO_DRIVER_NAME(dev))) {
211 ret = -EBUSY;
212 printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
213 goto free;
214 }
215
216 locomokbd->ldev = dev;
217 locomo_set_drvdata(dev, locomokbd);
218
219 locomokbd->base = (unsigned long) dev->mapbase;
220
221 spin_lock_init(&locomokbd->lock);
222
223 init_timer(&locomokbd->timer);
224 locomokbd->timer.function = locomokbd_timer_callback;
225 locomokbd->timer.data = (unsigned long) locomokbd;
226
227 locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
228
229 init_input_dev(&locomokbd->input);
230 locomokbd->input.keycode = locomokbd->keycode;
231 locomokbd->input.keycodesize = sizeof(unsigned char);
232 locomokbd->input.keycodemax = ARRAY_SIZE(locomokbd_keycode);
233 locomokbd->input.private = locomokbd;
234
235 memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
236 for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
237 set_bit(locomokbd->keycode[i], locomokbd->input.keybit);
238 clear_bit(0, locomokbd->input.keybit);
239
240 strcpy(locomokbd->phys, "locomokbd/input0");
241
242 locomokbd->input.name = "LoCoMo keyboard";
243 locomokbd->input.phys = locomokbd->phys;
244 locomokbd->input.id.bustype = BUS_XTKBD;
245 locomokbd->input.id.vendor = 0x0001;
246 locomokbd->input.id.product = 0x0001;
247 locomokbd->input.id.version = 0x0100;
248
249 /* attempt to get the interrupt */
250 ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
251 if (ret) {
252 printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n");
253 goto out;
254 }
255
256 input_register_device(&locomokbd->input);
257
258 printk(KERN_INFO "input: LoCoMo keyboard on locomokbd\n");
259
260 return 0;
261
262out:
263 release_mem_region((unsigned long) dev->mapbase, dev->length);
264 locomo_set_drvdata(dev, NULL);
265free:
266 kfree(locomokbd);
267
268 return ret;
269}
270
271static int locomokbd_remove(struct locomo_dev *dev)
272{
273 struct locomokbd *locomokbd = locomo_get_drvdata(dev);
274
275 free_irq(dev->irq[0], locomokbd);
276
277 del_timer_sync(&locomokbd->timer);
278
279 input_unregister_device(&locomokbd->input);
280 locomo_set_drvdata(dev, NULL);
281
282 release_mem_region((unsigned long) dev->mapbase, dev->length);
283
284 kfree(locomokbd);
285
286 return 0;
287}
288
289static struct locomo_driver keyboard_driver = {
290 .drv = {
291 .name = "locomokbd"
292 },
293 .devid = LOCOMO_DEVID_KEYBOARD,
294 .probe = locomokbd_probe,
295 .remove = locomokbd_remove,
296};
297
298static int __init locomokbd_init(void)
299{
300 return locomo_driver_register(&keyboard_driver);
301}
302
303static void __exit locomokbd_exit(void)
304{
305 locomo_driver_unregister(&keyboard_driver);
306}
307
308module_init(locomokbd_init);
309module_exit(locomokbd_exit);
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
new file mode 100644
index 000000000000..859ed771ee0a
--- /dev/null
+++ b/drivers/input/keyboard/maple_keyb.c
@@ -0,0 +1,190 @@
1/*
2 * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $
3 * SEGA Dreamcast keyboard driver
4 * Based on drivers/usb/usbkbd.c
5 */
6
7#include <linux/kernel.h>
8#include <linux/slab.h>
9#include <linux/input.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/timer.h>
13#include <linux/maple.h>
14
15MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
16MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
17MODULE_LICENSE("GPL");
18
19static unsigned char dc_kbd_keycode[256] = {
20 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
21 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
22 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
23 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
24 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
25 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
26 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
27 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
28 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
29 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
35 150,158,159,128,136,177,178,176,142,152,173,140
36};
37
38
39struct dc_kbd {
40 struct input_dev dev;
41 unsigned char new[8];
42 unsigned char old[8];
43 int open;
44};
45
46
47static void dc_scan_kbd(struct dc_kbd *kbd)
48{
49 int i;
50 struct input_dev *dev = &kbd->dev;
51
52 for(i=0; i<8; i++)
53 input_report_key(dev,
54 dc_kbd_keycode[i+224],
55 (kbd->new[0]>>i)&1);
56
57 for(i=2; i<8; i++) {
58
59 if(kbd->old[i]>3&&memscan(kbd->new+2, kbd->old[i], 6)==NULL) {
60 if(dc_kbd_keycode[kbd->old[i]])
61 input_report_key(dev,
62 dc_kbd_keycode[kbd->old[i]],
63 0);
64 else
65 printk("Unknown key (scancode %#x) released.",
66 kbd->old[i]);
67 }
68
69 if(kbd->new[i]>3&&memscan(kbd->old+2, kbd->new[i], 6)!=NULL) {
70 if(dc_kbd_keycode[kbd->new[i]])
71 input_report_key(dev,
72 dc_kbd_keycode[kbd->new[i]],
73 1);
74 else
75 printk("Unknown key (scancode %#x) pressed.",
76 kbd->new[i]);
77 }
78 }
79
80 input_sync(dev);
81
82 memcpy(kbd->old, kbd->new, 8);
83}
84
85
86static void dc_kbd_callback(struct mapleq *mq)
87{
88 struct maple_device *mapledev = mq->dev;
89 struct dc_kbd *kbd = mapledev->private_data;
90 unsigned long *buf = mq->recvbuf;
91
92 if (buf[1] == mapledev->function) {
93 memcpy(kbd->new, buf+2, 8);
94 dc_scan_kbd(kbd);
95 }
96}
97
98
99static int dc_kbd_open(struct input_dev *dev)
100{
101 struct dc_kbd *kbd = dev->private;
102 kbd->open++;
103 return 0;
104}
105
106
107static void dc_kbd_close(struct input_dev *dev)
108{
109 struct dc_kbd *kbd = dev->private;
110 kbd->open--;
111}
112
113
114static int dc_kbd_connect(struct maple_device *dev)
115{
116 int i;
117 unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
118 struct dc_kbd *kbd;
119
120 if (!(kbd = kmalloc(sizeof(struct dc_kbd), GFP_KERNEL)))
121 return -1;
122 memset(kbd, 0, sizeof(struct dc_kbd));
123
124 dev->private_data = kbd;
125
126 kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
127
128 init_input_dev(&kbd->dev);
129
130 for (i=0; i<255; i++)
131 set_bit(dc_kbd_keycode[i], kbd->dev.keybit);
132
133 clear_bit(0, kbd->dev.keybit);
134
135 kbd->dev.private = kbd;
136 kbd->dev.open = dc_kbd_open;
137 kbd->dev.close = dc_kbd_close;
138 kbd->dev.event = NULL;
139
140 kbd->dev.name = dev->product_name;
141 kbd->dev.id.bustype = BUS_MAPLE;
142
143 input_register_device(&kbd->dev);
144
145 maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
146
147 printk(KERN_INFO "input: keyboard(0x%lx): %s\n", data, kbd->dev.name);
148
149 return 0;
150}
151
152
153static void dc_kbd_disconnect(struct maple_device *dev)
154{
155 struct dc_kbd *kbd = dev->private_data;
156
157 input_unregister_device(&kbd->dev);
158 kfree(kbd);
159}
160
161
162static struct maple_driver dc_kbd_driver = {
163 .function = MAPLE_FUNC_KEYBOARD,
164 .name = "Dreamcast keyboard",
165 .connect = dc_kbd_connect,
166 .disconnect = dc_kbd_disconnect,
167};
168
169
170static int __init dc_kbd_init(void)
171{
172 maple_register_driver(&dc_kbd_driver);
173 return 0;
174}
175
176
177static void __exit dc_kbd_exit(void)
178{
179 maple_unregister_driver(&dc_kbd_driver);
180}
181
182
183module_init(dc_kbd_init);
184module_exit(dc_kbd_exit);
185
186/*
187 * Local variables:
188 * c-basic-offset: 8
189 * End:
190 */
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
new file mode 100644
index 000000000000..2e8ce1613eec
--- /dev/null
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -0,0 +1,184 @@
1/*
2 * Copyright (c) 2000 Justin Cormack
3 */
4
5/*
6 * Newton keyboard driver for Linux
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Should you need to contact me, the author, you can do so either by
25 * e-mail - mail your message to <j.cormack@doc.ic.ac.uk>, or by paper mail:
26 * Justin Cormack, 68 Dartmouth Park Road, London NW5 1SN, UK.
27 */
28
29#include <linux/slab.h>
30#include <linux/module.h>
31#include <linux/input.h>
32#include <linux/init.h>
33#include <linux/serio.h>
34
35#define DRIVER_DESC "Newton keyboard driver"
36
37MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>");
38MODULE_DESCRIPTION(DRIVER_DESC);
39MODULE_LICENSE("GPL");
40
41#define NKBD_KEY 0x7f
42#define NKBD_PRESS 0x80
43
44static unsigned char nkbd_keycode[128] = {
45 KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X,
46 KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R,
47 KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5,
48 KEY_EQUAL, KEY_9, KEY_7, KEY_MINUS, KEY_8, KEY_0, KEY_RIGHTBRACE, KEY_O,
49 KEY_U, KEY_LEFTBRACE, KEY_I, KEY_P, KEY_ENTER, KEY_L, KEY_J, KEY_APOSTROPHE,
50 KEY_K, KEY_SEMICOLON, KEY_BACKSLASH, KEY_COMMA, KEY_SLASH, KEY_N, KEY_M, KEY_DOT,
51 KEY_TAB, KEY_SPACE, KEY_GRAVE, KEY_DELETE, 0, 0, 0, KEY_LEFTMETA,
52 KEY_LEFTSHIFT, KEY_CAPSLOCK, KEY_LEFTALT, KEY_LEFTCTRL, KEY_RIGHTSHIFT, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57 KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0
58};
59
60static char *nkbd_name = "Newton Keyboard";
61
62struct nkbd {
63 unsigned char keycode[128];
64 struct input_dev dev;
65 struct serio *serio;
66 char phys[32];
67};
68
69static irqreturn_t nkbd_interrupt(struct serio *serio,
70 unsigned char data, unsigned int flags, struct pt_regs *regs)
71{
72 struct nkbd *nkbd = serio_get_drvdata(serio);
73
74 /* invalid scan codes are probably the init sequence, so we ignore them */
75 if (nkbd->keycode[data & NKBD_KEY]) {
76 input_regs(&nkbd->dev, regs);
77 input_report_key(&nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
78 input_sync(&nkbd->dev);
79 }
80
81 else if (data == 0xe7) /* end of init sequence */
82 printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
83 return IRQ_HANDLED;
84
85}
86
87static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
88{
89 struct nkbd *nkbd;
90 int i;
91 int err;
92
93 if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL)))
94 return -ENOMEM;
95
96 memset(nkbd, 0, sizeof(struct nkbd));
97
98 nkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
99
100 nkbd->serio = serio;
101
102 init_input_dev(&nkbd->dev);
103 nkbd->dev.keycode = nkbd->keycode;
104 nkbd->dev.keycodesize = sizeof(unsigned char);
105 nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode);
106 nkbd->dev.private = nkbd;
107
108 serio_set_drvdata(serio, nkbd);
109
110 err = serio_open(serio, drv);
111 if (err) {
112 serio_set_drvdata(serio, NULL);
113 kfree(nkbd);
114 return err;
115 }
116
117 memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
118 for (i = 0; i < 128; i++)
119 set_bit(nkbd->keycode[i], nkbd->dev.keybit);
120 clear_bit(0, nkbd->dev.keybit);
121
122 sprintf(nkbd->phys, "%s/input0", serio->phys);
123
124 nkbd->dev.name = nkbd_name;
125 nkbd->dev.phys = nkbd->phys;
126 nkbd->dev.id.bustype = BUS_RS232;
127 nkbd->dev.id.vendor = SERIO_NEWTON;
128 nkbd->dev.id.product = 0x0001;
129 nkbd->dev.id.version = 0x0100;
130 nkbd->dev.dev = &serio->dev;
131
132 input_register_device(&nkbd->dev);
133
134 printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
135
136 return 0;
137}
138
139static void nkbd_disconnect(struct serio *serio)
140{
141 struct nkbd *nkbd = serio_get_drvdata(serio);
142
143 input_unregister_device(&nkbd->dev);
144 serio_close(serio);
145 serio_set_drvdata(serio, NULL);
146 kfree(nkbd);
147}
148
149static struct serio_device_id nkbd_serio_ids[] = {
150 {
151 .type = SERIO_RS232,
152 .proto = SERIO_NEWTON,
153 .id = SERIO_ANY,
154 .extra = SERIO_ANY,
155 },
156 { 0 }
157};
158
159MODULE_DEVICE_TABLE(serio, nkbd_serio_ids);
160
161static struct serio_driver nkbd_drv = {
162 .driver = {
163 .name = "newtonkbd",
164 },
165 .description = DRIVER_DESC,
166 .id_table = nkbd_serio_ids,
167 .interrupt = nkbd_interrupt,
168 .connect = nkbd_connect,
169 .disconnect = nkbd_disconnect,
170};
171
172static int __init nkbd_init(void)
173{
174 serio_register_driver(&nkbd_drv);
175 return 0;
176}
177
178static void __exit nkbd_exit(void)
179{
180 serio_unregister_driver(&nkbd_drv);
181}
182
183module_init(nkbd_init);
184module_exit(nkbd_exit);
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
new file mode 100644
index 000000000000..596964ceb96d
--- /dev/null
+++ b/drivers/input/keyboard/sunkbd.c
@@ -0,0 +1,353 @@
1/*
2 * $Id: sunkbd.c,v 1.14 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Sun keyboard driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/delay.h>
32#include <linux/slab.h>
33#include <linux/module.h>
34#include <linux/interrupt.h>
35#include <linux/init.h>
36#include <linux/input.h>
37#include <linux/serio.h>
38#include <linux/workqueue.h>
39
40#define DRIVER_DESC "Sun keyboard driver"
41
42MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
43MODULE_DESCRIPTION(DRIVER_DESC);
44MODULE_LICENSE("GPL");
45
46static unsigned char sunkbd_keycode[128] = {
47 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64, 0,
48 65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3,
49 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 41, 14,110,113, 98, 55,
50 116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
51 26, 27,111,127, 71, 72, 73, 74,134,135,107, 0, 29, 30, 31, 32,
52 33, 34, 35, 36, 37, 38, 39, 40, 43, 28, 96, 75, 76, 77, 82,136,
53 104,137, 69, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,101,
54 79, 80, 81, 0, 0, 0,138, 58,125, 57,126,109, 86, 78
55};
56
57#define SUNKBD_CMD_RESET 0x1
58#define SUNKBD_CMD_BELLON 0x2
59#define SUNKBD_CMD_BELLOFF 0x3
60#define SUNKBD_CMD_CLICK 0xa
61#define SUNKBD_CMD_NOCLICK 0xb
62#define SUNKBD_CMD_SETLED 0xe
63#define SUNKBD_CMD_LAYOUT 0xf
64
65#define SUNKBD_RET_RESET 0xff
66#define SUNKBD_RET_ALLUP 0x7f
67#define SUNKBD_RET_LAYOUT 0xfe
68
69#define SUNKBD_LAYOUT_5_MASK 0x20
70#define SUNKBD_RELEASE 0x80
71#define SUNKBD_KEY 0x7f
72
73/*
74 * Per-keyboard data.
75 */
76
77struct sunkbd {
78 unsigned char keycode[128];
79 struct input_dev dev;
80 struct serio *serio;
81 struct work_struct tq;
82 wait_queue_head_t wait;
83 char name[64];
84 char phys[32];
85 char type;
86 volatile s8 reset;
87 volatile s8 layout;
88};
89
90/*
91 * sunkbd_interrupt() is called by the low level driver when a character
92 * is received.
93 */
94
95static irqreturn_t sunkbd_interrupt(struct serio *serio,
96 unsigned char data, unsigned int flags, struct pt_regs *regs)
97{
98 struct sunkbd* sunkbd = serio_get_drvdata(serio);
99
100 if (sunkbd->reset <= -1) { /* If cp[i] is 0xff, sunkbd->reset will stay -1. */
101 sunkbd->reset = data; /* The keyboard sends 0xff 0xff 0xID on powerup */
102 wake_up_interruptible(&sunkbd->wait);
103 goto out;
104 }
105
106 if (sunkbd->layout == -1) {
107 sunkbd->layout = data;
108 wake_up_interruptible(&sunkbd->wait);
109 goto out;
110 }
111
112 switch (data) {
113
114 case SUNKBD_RET_RESET:
115 schedule_work(&sunkbd->tq);
116 sunkbd->reset = -1;
117 break;
118
119 case SUNKBD_RET_LAYOUT:
120 sunkbd->layout = -1;
121 break;
122
123 case SUNKBD_RET_ALLUP: /* All keys released */
124 break;
125
126 default:
127 if (sunkbd->keycode[data & SUNKBD_KEY]) {
128 input_regs(&sunkbd->dev, regs);
129 input_report_key(&sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
130 input_sync(&sunkbd->dev);
131 } else {
132 printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n",
133 data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed");
134 }
135 }
136out:
137 return IRQ_HANDLED;
138}
139
140/*
141 * sunkbd_event() handles events from the input module.
142 */
143
144static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
145{
146 struct sunkbd *sunkbd = dev->private;
147
148 switch (type) {
149
150 case EV_LED:
151
152 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
153 sunkbd->serio->write(sunkbd->serio,
154 (!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) |
155 (!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led));
156 return 0;
157
158 case EV_SND:
159
160 switch (code) {
161
162 case SND_CLICK:
163 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value);
164 return 0;
165
166 case SND_BELL:
167 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value);
168 return 0;
169 }
170
171 break;
172 }
173
174 return -1;
175}
176
177/*
178 * sunkbd_initialize() checks for a Sun keyboard attached, and determines
179 * its type.
180 */
181
182static int sunkbd_initialize(struct sunkbd *sunkbd)
183{
184 sunkbd->reset = -2;
185 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
186 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
187 if (sunkbd->reset <0)
188 return -1;
189
190 sunkbd->type = sunkbd->reset;
191
192 if (sunkbd->type == 4) { /* Type 4 keyboard */
193 sunkbd->layout = -2;
194 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT);
195 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4);
196 if (sunkbd->layout < 0) return -1;
197 if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5;
198 }
199
200 return 0;
201}
202
203/*
204 * sunkbd_reinit() sets leds and beeps to a state the computer remembers they
205 * were in.
206 */
207
208static void sunkbd_reinit(void *data)
209{
210 struct sunkbd *sunkbd = data;
211
212 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
213
214 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
215 sunkbd->serio->write(sunkbd->serio,
216 (!!test_bit(LED_CAPSL, sunkbd->dev.led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev.led) << 2) |
217 (!!test_bit(LED_COMPOSE, sunkbd->dev.led) << 1) | !!test_bit(LED_NUML, sunkbd->dev.led));
218 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev.snd));
219 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev.snd));
220}
221
222/*
223 * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
224 */
225
226static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
227{
228 struct sunkbd *sunkbd;
229 int i;
230 int err;
231
232 if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
233 return -ENOMEM;
234
235 memset(sunkbd, 0, sizeof(struct sunkbd));
236
237 init_input_dev(&sunkbd->dev);
238 init_waitqueue_head(&sunkbd->wait);
239
240 sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
241 sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
242 sunkbd->dev.sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
243
244 sunkbd->serio = serio;
245
246 INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd);
247
248 sunkbd->dev.keycode = sunkbd->keycode;
249 sunkbd->dev.keycodesize = sizeof(unsigned char);
250 sunkbd->dev.keycodemax = ARRAY_SIZE(sunkbd_keycode);
251
252 sunkbd->dev.event = sunkbd_event;
253 sunkbd->dev.private = sunkbd;
254
255 serio_set_drvdata(serio, sunkbd);
256
257 err = serio_open(serio, drv);
258 if (err) {
259 serio_set_drvdata(serio, NULL);
260 kfree(sunkbd);
261 return err;
262 }
263
264 if (sunkbd_initialize(sunkbd) < 0) {
265 serio_close(serio);
266 serio_set_drvdata(serio, NULL);
267 kfree(sunkbd);
268 return -ENODEV;
269 }
270
271 sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
272
273 memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
274 for (i = 0; i < 128; i++)
275 set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
276 clear_bit(0, sunkbd->dev.keybit);
277
278 sprintf(sunkbd->phys, "%s/input0", serio->phys);
279
280 sunkbd->dev.name = sunkbd->name;
281 sunkbd->dev.phys = sunkbd->phys;
282 sunkbd->dev.id.bustype = BUS_RS232;
283 sunkbd->dev.id.vendor = SERIO_SUNKBD;
284 sunkbd->dev.id.product = sunkbd->type;
285 sunkbd->dev.id.version = 0x0100;
286 sunkbd->dev.dev = &serio->dev;
287
288 input_register_device(&sunkbd->dev);
289
290 printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys);
291
292 return 0;
293}
294
295/*
296 * sunkbd_disconnect() unregisters and closes behind us.
297 */
298
299static void sunkbd_disconnect(struct serio *serio)
300{
301 struct sunkbd *sunkbd = serio_get_drvdata(serio);
302 input_unregister_device(&sunkbd->dev);
303 serio_close(serio);
304 serio_set_drvdata(serio, NULL);
305 kfree(sunkbd);
306}
307
308static struct serio_device_id sunkbd_serio_ids[] = {
309 {
310 .type = SERIO_RS232,
311 .proto = SERIO_SUNKBD,
312 .id = SERIO_ANY,
313 .extra = SERIO_ANY,
314 },
315 {
316 .type = SERIO_RS232,
317 .proto = SERIO_UNKNOWN, /* sunkbd does probe */
318 .id = SERIO_ANY,
319 .extra = SERIO_ANY,
320 },
321 { 0 }
322};
323
324MODULE_DEVICE_TABLE(serio, sunkbd_serio_ids);
325
326static struct serio_driver sunkbd_drv = {
327 .driver = {
328 .name = "sunkbd",
329 },
330 .description = DRIVER_DESC,
331 .id_table = sunkbd_serio_ids,
332 .interrupt = sunkbd_interrupt,
333 .connect = sunkbd_connect,
334 .disconnect = sunkbd_disconnect,
335};
336
337/*
338 * The functions for insering/removing us as a module.
339 */
340
341static int __init sunkbd_init(void)
342{
343 serio_register_driver(&sunkbd_drv);
344 return 0;
345}
346
347static void __exit sunkbd_exit(void)
348{
349 serio_unregister_driver(&sunkbd_drv);
350}
351
352module_init(sunkbd_init);
353module_exit(sunkbd_exit);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
new file mode 100644
index 000000000000..19eaec7789d1
--- /dev/null
+++ b/drivers/input/keyboard/xtkbd.c
@@ -0,0 +1,188 @@
1/*
2 * $Id: xtkbd.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * XT keyboard driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/slab.h>
32#include <linux/module.h>
33#include <linux/input.h>
34#include <linux/init.h>
35#include <linux/serio.h>
36
37#define DRIVER_DESC "XT keyboard driver"
38
39MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
40MODULE_DESCRIPTION(DRIVER_DESC);
41MODULE_LICENSE("GPL");
42
43#define XTKBD_EMUL0 0xe0
44#define XTKBD_EMUL1 0xe1
45#define XTKBD_KEY 0x7f
46#define XTKBD_RELEASE 0x80
47
48static unsigned char xtkbd_keycode[256] = {
49 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
50 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
51 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
52 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
53 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
54 80, 81, 82, 83, 0, 0, 0, 87, 88, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 87, 88, 0, 0, 0, 0,110,111,103,108,105,
56 106
57};
58
59static char *xtkbd_name = "XT Keyboard";
60
61struct xtkbd {
62 unsigned char keycode[256];
63 struct input_dev dev;
64 struct serio *serio;
65 char phys[32];
66};
67
68static irqreturn_t xtkbd_interrupt(struct serio *serio,
69 unsigned char data, unsigned int flags, struct pt_regs *regs)
70{
71 struct xtkbd *xtkbd = serio_get_drvdata(serio);
72
73 switch (data) {
74 case XTKBD_EMUL0:
75 case XTKBD_EMUL1:
76 break;
77 default:
78
79 if (xtkbd->keycode[data & XTKBD_KEY]) {
80 input_regs(&xtkbd->dev, regs);
81 input_report_key(&xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
82 input_sync(&xtkbd->dev);
83 } else {
84 printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n",
85 data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed");
86 }
87 }
88 return IRQ_HANDLED;
89}
90
91static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
92{
93 struct xtkbd *xtkbd;
94 int i;
95 int err;
96
97 if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL)))
98 return -ENOMEM;
99
100 memset(xtkbd, 0, sizeof(struct xtkbd));
101
102 xtkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
103
104 xtkbd->serio = serio;
105
106 init_input_dev(&xtkbd->dev);
107 xtkbd->dev.keycode = xtkbd->keycode;
108 xtkbd->dev.keycodesize = sizeof(unsigned char);
109 xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode);
110 xtkbd->dev.private = xtkbd;
111
112 serio_set_drvdata(serio, xtkbd);
113
114 err = serio_open(serio, drv);
115 if (err) {
116 serio_set_drvdata(serio, NULL);
117 kfree(xtkbd);
118 return err;
119 }
120
121 memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
122 for (i = 0; i < 255; i++)
123 set_bit(xtkbd->keycode[i], xtkbd->dev.keybit);
124 clear_bit(0, xtkbd->dev.keybit);
125
126 sprintf(xtkbd->phys, "%s/input0", serio->phys);
127
128 xtkbd->dev.name = xtkbd_name;
129 xtkbd->dev.phys = xtkbd->phys;
130 xtkbd->dev.id.bustype = BUS_XTKBD;
131 xtkbd->dev.id.vendor = 0x0001;
132 xtkbd->dev.id.product = 0x0001;
133 xtkbd->dev.id.version = 0x0100;
134 xtkbd->dev.dev = &serio->dev;
135
136 input_register_device(&xtkbd->dev);
137
138 printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
139
140 return 0;
141}
142
143static void xtkbd_disconnect(struct serio *serio)
144{
145 struct xtkbd *xtkbd = serio_get_drvdata(serio);
146
147 input_unregister_device(&xtkbd->dev);
148 serio_close(serio);
149 serio_set_drvdata(serio, NULL);
150 kfree(xtkbd);
151}
152
153static struct serio_device_id xtkbd_serio_ids[] = {
154 {
155 .type = SERIO_XT,
156 .proto = SERIO_ANY,
157 .id = SERIO_ANY,
158 .extra = SERIO_ANY,
159 },
160 { 0 }
161};
162
163MODULE_DEVICE_TABLE(serio, xtkbd_serio_ids);
164
165static struct serio_driver xtkbd_drv = {
166 .driver = {
167 .name = "xtkbd",
168 },
169 .description = DRIVER_DESC,
170 .id_table = xtkbd_serio_ids,
171 .interrupt = xtkbd_interrupt,
172 .connect = xtkbd_connect,
173 .disconnect = xtkbd_disconnect,
174};
175
176static int __init xtkbd_init(void)
177{
178 serio_register_driver(&xtkbd_drv);
179 return 0;
180}
181
182static void __exit xtkbd_exit(void)
183{
184 serio_unregister_driver(&xtkbd_drv);
185}
186
187module_init(xtkbd_init);
188module_exit(xtkbd_exit);