diff options
Diffstat (limited to 'drivers/input/keyboard/xtkbd.c')
-rw-r--r-- | drivers/input/keyboard/xtkbd.c | 188 |
1 files changed, 188 insertions, 0 deletions
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 | |||
39 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | ||
40 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | #define XTKBD_EMUL0 0xe0 | ||
44 | #define XTKBD_EMUL1 0xe1 | ||
45 | #define XTKBD_KEY 0x7f | ||
46 | #define XTKBD_RELEASE 0x80 | ||
47 | |||
48 | static 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 | |||
59 | static char *xtkbd_name = "XT Keyboard"; | ||
60 | |||
61 | struct xtkbd { | ||
62 | unsigned char keycode[256]; | ||
63 | struct input_dev dev; | ||
64 | struct serio *serio; | ||
65 | char phys[32]; | ||
66 | }; | ||
67 | |||
68 | static 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 | |||
91 | static 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 | |||
143 | static 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 | |||
153 | static 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 | |||
163 | MODULE_DEVICE_TABLE(serio, xtkbd_serio_ids); | ||
164 | |||
165 | static 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 | |||
176 | static int __init xtkbd_init(void) | ||
177 | { | ||
178 | serio_register_driver(&xtkbd_drv); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static void __exit xtkbd_exit(void) | ||
183 | { | ||
184 | serio_unregister_driver(&xtkbd_drv); | ||
185 | } | ||
186 | |||
187 | module_init(xtkbd_init); | ||
188 | module_exit(xtkbd_exit); | ||