blob: cbb93669d1cef7b9a3188ee74a008de927c1f2c7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
Ingo Molnar33d3f072006-02-19 00:22:18 -050030#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#define DRIVER_DESC "AT and PS/2 keyboard driver"
33
34MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
35MODULE_DESCRIPTION(DRIVER_DESC);
36MODULE_LICENSE("GPL");
37
38static int atkbd_set = 2;
39module_param_named(set, atkbd_set, int, 0);
40MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)");
41
42#if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
43static int atkbd_reset;
44#else
45static int atkbd_reset = 1;
46#endif
47module_param_named(reset, atkbd_reset, bool, 0);
48MODULE_PARM_DESC(reset, "Reset keyboard during initialization");
49
50static int atkbd_softrepeat;
51module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
52MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
53
54static int atkbd_softraw = 1;
55module_param_named(softraw, atkbd_softraw, bool, 0);
56MODULE_PARM_DESC(softraw, "Use software generated rawmode");
57
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -040058static int atkbd_scroll;
Linus Torvalds1da177e2005-04-16 15:20:36 -070059module_param_named(scroll, atkbd_scroll, bool, 0);
60MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
61
62static int atkbd_extra;
63module_param_named(extra, atkbd_extra, bool, 0);
64MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
65
66__obsolete_setup("atkbd_set=");
67__obsolete_setup("atkbd_reset");
68__obsolete_setup("atkbd_softrepeat=");
69
70/*
71 * Scancode to keycode tables. These are just the default setting, and
72 * are loadable via an userland utility.
73 */
74
75static unsigned char atkbd_set2_keycode[512] = {
76
77#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
78
79/* XXX: need a more general approach */
80
81#include "hpps2atkbd.h" /* include the keyboard scancodes */
82
83#else
84 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
85 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
86 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
87 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
88 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
89 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
90 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
91 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
92
93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
95 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
96 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
97 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
98 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
100 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
101
102 0, 0, 0, 65, 99,
103#endif
104};
105
106static unsigned char atkbd_set3_keycode[512] = {
107
108 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60,
109 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62,
110 134, 46, 45, 32, 18, 5, 4, 63,135, 57, 47, 33, 20, 19, 6, 64,
111 136, 49, 48, 35, 34, 21, 7, 65,137,100, 50, 36, 22, 8, 9, 66,
112 125, 51, 37, 23, 24, 11, 10, 67,126, 52, 53, 38, 39, 25, 12, 68,
113 113,114, 40, 43, 26, 13, 87, 99, 97, 54, 28, 27, 43, 43, 88, 70,
114 108,105,119,103,111,107, 14,110, 0, 79,106, 75, 71,109,102,104,
115 82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55,183,
116
117 184,185,186,187, 74, 94, 92, 93, 0, 0, 0,125,126,127,112, 0,
118 0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
119 148,149,147,140
120};
121
122static unsigned char atkbd_unxlate_table[128] = {
123 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
124 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
125 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
126 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
127 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
128 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
129 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
130 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
131};
132
133#define ATKBD_CMD_SETLEDS 0x10ed
134#define ATKBD_CMD_GSCANSET 0x11f0
135#define ATKBD_CMD_SSCANSET 0x10f0
136#define ATKBD_CMD_GETID 0x02f2
137#define ATKBD_CMD_SETREP 0x10f3
138#define ATKBD_CMD_ENABLE 0x00f4
139#define ATKBD_CMD_RESET_DIS 0x00f5
140#define ATKBD_CMD_SETALL_MBR 0x00fa
141#define ATKBD_CMD_RESET_BAT 0x02ff
142#define ATKBD_CMD_RESEND 0x00fe
143#define ATKBD_CMD_EX_ENABLE 0x10ea
144#define ATKBD_CMD_EX_SETLEDS 0x20eb
145#define ATKBD_CMD_OK_GETID 0x02e8
146
147#define ATKBD_RET_ACK 0xfa
148#define ATKBD_RET_NAK 0xfe
149#define ATKBD_RET_BAT 0xaa
150#define ATKBD_RET_EMUL0 0xe0
151#define ATKBD_RET_EMUL1 0xe1
152#define ATKBD_RET_RELEASE 0xf0
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400153#define ATKBD_RET_HANJA 0xf1
154#define ATKBD_RET_HANGEUL 0xf2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155#define ATKBD_RET_ERR 0xff
156
157#define ATKBD_KEY_UNKNOWN 0
158#define ATKBD_KEY_NULL 255
159
160#define ATKBD_SCR_1 254
161#define ATKBD_SCR_2 253
162#define ATKBD_SCR_4 252
163#define ATKBD_SCR_8 251
164#define ATKBD_SCR_CLICK 250
165#define ATKBD_SCR_LEFT 249
166#define ATKBD_SCR_RIGHT 248
167
168#define ATKBD_SPECIAL 248
169
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500170#define ATKBD_LED_EVENT_BIT 0
171#define ATKBD_REP_EVENT_BIT 1
172
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400173#define ATKBD_XL_ERR 0x01
174#define ATKBD_XL_BAT 0x02
175#define ATKBD_XL_ACK 0x04
176#define ATKBD_XL_NAK 0x08
177#define ATKBD_XL_HANGEUL 0x10
178#define ATKBD_XL_HANJA 0x20
179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180static struct {
181 unsigned char keycode;
182 unsigned char set2;
183} atkbd_scroll_keys[] = {
184 { ATKBD_SCR_1, 0xc5 },
Vojtech Pavlik5212dd52005-05-28 15:51:47 -0700185 { ATKBD_SCR_2, 0x9d },
186 { ATKBD_SCR_4, 0xa4 },
187 { ATKBD_SCR_8, 0x9b },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 { ATKBD_SCR_CLICK, 0xe0 },
189 { ATKBD_SCR_LEFT, 0xcb },
190 { ATKBD_SCR_RIGHT, 0xd2 },
191};
192
193/*
194 * The atkbd control structure
195 */
196
197struct atkbd {
198
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500199 struct ps2dev ps2dev;
200 struct input_dev *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202 /* Written only during init */
203 char name[64];
204 char phys[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
206 unsigned short id;
207 unsigned char keycode[512];
208 unsigned char set;
209 unsigned char translated;
210 unsigned char extra;
211 unsigned char write;
212 unsigned char softrepeat;
213 unsigned char softraw;
214 unsigned char scroll;
215 unsigned char enabled;
216
217 /* Accessed only from interrupt */
218 unsigned char emul;
219 unsigned char resend;
220 unsigned char release;
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400221 unsigned long xl_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 unsigned int last;
223 unsigned long time;
Dmitry Torokhov86255d92006-10-11 01:44:46 -0400224 unsigned long err_count;
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500225
226 struct work_struct event_work;
Ingo Molnar33d3f072006-02-19 00:22:18 -0500227 struct mutex event_mutex;
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500228 unsigned long event_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229};
230
231static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
232 ssize_t (*handler)(struct atkbd *, char *));
233static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
234 ssize_t (*handler)(struct atkbd *, const char *, size_t));
235#define ATKBD_DEFINE_ATTR(_name) \
236static ssize_t atkbd_show_##_name(struct atkbd *, char *); \
237static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \
Dmitry Torokhov86255d92006-10-11 01:44:46 -0400238static ssize_t atkbd_do_show_##_name(struct device *d, \
239 struct device_attribute *attr, char *b) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240{ \
241 return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \
242} \
Dmitry Torokhov86255d92006-10-11 01:44:46 -0400243static ssize_t atkbd_do_set_##_name(struct device *d, \
244 struct device_attribute *attr, const char *b, size_t s) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245{ \
246 return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \
247} \
Dmitry Torokhovd083e902005-05-29 02:28:42 -0500248static struct device_attribute atkbd_attr_##_name = \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name);
250
251ATKBD_DEFINE_ATTR(extra);
252ATKBD_DEFINE_ATTR(scroll);
253ATKBD_DEFINE_ATTR(set);
254ATKBD_DEFINE_ATTR(softrepeat);
255ATKBD_DEFINE_ATTR(softraw);
256
Dmitry Torokhov86255d92006-10-11 01:44:46 -0400257#define ATKBD_DEFINE_RO_ATTR(_name) \
258static ssize_t atkbd_show_##_name(struct atkbd *, char *); \
259static ssize_t atkbd_do_show_##_name(struct device *d, \
260 struct device_attribute *attr, char *b) \
261{ \
262 return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \
263} \
264static struct device_attribute atkbd_attr_##_name = \
265 __ATTR(_name, S_IRUGO, atkbd_do_show_##_name, NULL);
266
267ATKBD_DEFINE_RO_ATTR(err_count);
268
269static struct attribute *atkbd_attributes[] = {
270 &atkbd_attr_extra.attr,
271 &atkbd_attr_scroll.attr,
272 &atkbd_attr_set.attr,
273 &atkbd_attr_softrepeat.attr,
274 &atkbd_attr_softraw.attr,
275 &atkbd_attr_err_count.attr,
276 NULL
277};
278
279static struct attribute_group atkbd_attribute_group = {
280 .attrs = atkbd_attributes,
281};
282
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400283static const unsigned int xl_table[] = {
284 ATKBD_RET_BAT, ATKBD_RET_ERR, ATKBD_RET_ACK,
285 ATKBD_RET_NAK, ATKBD_RET_HANJA, ATKBD_RET_HANGEUL,
286};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400288/*
289 * Checks if we should mangle the scancode to extract 'release' bit
290 * in translated mode.
291 */
292static int atkbd_need_xlate(unsigned long xl_bit, unsigned char code)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293{
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400294 int i;
295
296 if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1)
297 return 0;
298
299 for (i = 0; i < ARRAY_SIZE(xl_table); i++)
300 if (code == xl_table[i])
301 return test_bit(i, &xl_bit);
302
303 return 1;
304}
305
306/*
307 * Calculates new value of xl_bit so the driver can distinguish
308 * between make/break pair of scancodes for select keys and PS/2
309 * protocol responses.
310 */
311static void atkbd_calculate_xl_bit(struct atkbd *atkbd, unsigned char code)
312{
313 int i;
314
315 for (i = 0; i < ARRAY_SIZE(xl_table); i++) {
316 if (!((code ^ xl_table[i]) & 0x7f)) {
317 if (code & 0x80)
318 __clear_bit(i, &atkbd->xl_bit);
319 else
320 __set_bit(i, &atkbd->xl_bit);
321 break;
322 }
323 }
324}
325
326/*
327 * Encode the scancode, 0xe0 prefix, and high bit into a single integer,
328 * keeping kernel 2.4 compatibility for set 2
329 */
330static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code)
331{
332 if (atkbd->set == 3) {
333 if (atkbd->emul == 1)
334 code |= 0x100;
335 } else {
336 code = (code & 0x7f) | ((code & 0x80) << 1);
337 if (atkbd->emul == 1)
338 code |= 0x80;
339 }
340
341 return code;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342}
343
344/*
345 * atkbd_interrupt(). Here takes place processing of data received from
346 * the keyboard into events.
347 */
348
349static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
David Howells7d12e782006-10-05 14:55:46 +0100350 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351{
352 struct atkbd *atkbd = serio_get_drvdata(serio);
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400353 struct input_dev *dev = atkbd->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 unsigned int code = data;
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400355 int scroll = 0, hscroll = 0, click = -1, add_release_event = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 int value;
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400357 unsigned char keycode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358
359#ifdef ATKBD_DEBUG
360 printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
361#endif
362
363#if !defined(__i386__) && !defined (__x86_64__)
364 if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
365 printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags);
366 serio_write(serio, ATKBD_CMD_RESEND);
367 atkbd->resend = 1;
368 goto out;
369 }
370
371 if (!flags && data == ATKBD_RET_ACK)
372 atkbd->resend = 0;
373#endif
374
375 if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK))
376 if (ps2_handle_ack(&atkbd->ps2dev, data))
377 goto out;
378
379 if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD))
380 if (ps2_handle_response(&atkbd->ps2dev, data))
381 goto out;
382
383 if (!atkbd->enabled)
384 goto out;
385
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400386 input_event(dev, EV_MSC, MSC_RAW, code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
388 if (atkbd->translated) {
389
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400390 if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 atkbd->release = code >> 7;
392 code &= 0x7f;
393 }
394
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400395 if (!atkbd->emul)
396 atkbd_calculate_xl_bit(atkbd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 }
398
399 switch (code) {
400 case ATKBD_RET_BAT:
401 atkbd->enabled = 0;
Dmitry Torokhovdbc26342006-01-05 23:00:13 -0500402 serio_reconnect(atkbd->ps2dev.serio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 goto out;
404 case ATKBD_RET_EMUL0:
405 atkbd->emul = 1;
406 goto out;
407 case ATKBD_RET_EMUL1:
408 atkbd->emul = 2;
409 goto out;
410 case ATKBD_RET_RELEASE:
411 atkbd->release = 1;
412 goto out;
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400413 case ATKBD_RET_ACK:
414 case ATKBD_RET_NAK:
415 printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
416 "Some program might be trying access hardware directly.\n",
417 data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
418 goto out;
Jerome Pinotb9ab58d2006-06-26 01:51:23 -0400419 case ATKBD_RET_HANGEUL:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 case ATKBD_RET_HANJA:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400421 /*
422 * These keys do not report release and thus need to be
423 * flagged properly
424 */
425 add_release_event = 1;
426 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 case ATKBD_RET_ERR:
Dmitry Torokhov86255d92006-10-11 01:44:46 -0400428 atkbd->err_count++;
429#ifdef ATKBD_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
Dmitry Torokhov86255d92006-10-11 01:44:46 -0400431#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 goto out;
433 }
434
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400435 code = atkbd_compat_scancode(atkbd, code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400437 if (atkbd->emul && --atkbd->emul)
438 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400440 keycode = atkbd->keycode[code];
441
442 if (keycode != ATKBD_KEY_NULL)
443 input_event(dev, EV_MSC, MSC_SCAN, code);
444
445 switch (keycode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 case ATKBD_KEY_NULL:
447 break;
448 case ATKBD_KEY_UNKNOWN:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400449 printk(KERN_WARNING
450 "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n",
451 atkbd->release ? "released" : "pressed",
452 atkbd->translated ? "translated" : "raw",
453 atkbd->set, code, serio->phys);
454 printk(KERN_WARNING
455 "atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.\n",
456 code & 0x80 ? "e0" : "", code & 0x7f);
457 input_sync(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 break;
459 case ATKBD_SCR_1:
460 scroll = 1 - atkbd->release * 2;
461 break;
462 case ATKBD_SCR_2:
463 scroll = 2 - atkbd->release * 4;
464 break;
465 case ATKBD_SCR_4:
466 scroll = 4 - atkbd->release * 8;
467 break;
468 case ATKBD_SCR_8:
469 scroll = 8 - atkbd->release * 16;
470 break;
471 case ATKBD_SCR_CLICK:
472 click = !atkbd->release;
473 break;
474 case ATKBD_SCR_LEFT:
475 hscroll = -1;
476 break;
477 case ATKBD_SCR_RIGHT:
478 hscroll = 1;
479 break;
480 default:
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400481 if (atkbd->release) {
482 value = 0;
483 atkbd->last = 0;
484 } else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) {
485 /* Workaround Toshiba laptop multiple keypress */
486 value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2;
487 } else {
488 value = 1;
489 atkbd->last = code;
490 atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 }
492
Dmitry Torokhovf8b4c462006-06-27 23:42:17 -0400493 input_event(dev, EV_KEY, keycode, value);
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400494 input_sync(dev);
495
496 if (value && add_release_event) {
497 input_report_key(dev, keycode, 0);
498 input_sync(dev);
499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 }
501
502 if (atkbd->scroll) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 if (click != -1)
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400504 input_report_key(dev, BTN_MIDDLE, click);
505 input_report_rel(dev, REL_WHEEL, scroll);
506 input_report_rel(dev, REL_HWHEEL, hscroll);
507 input_sync(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 }
509
510 atkbd->release = 0;
511out:
512 return IRQ_HANDLED;
513}
514
Dmitry Torokhov3d0f0fa2006-08-04 22:52:46 -0400515static int atkbd_set_repeat_rate(struct atkbd *atkbd)
516{
517 const short period[32] =
518 { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
519 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
520 const short delay[4] =
521 { 250, 500, 750, 1000 };
522
523 struct input_dev *dev = atkbd->dev;
524 unsigned char param;
525 int i = 0, j = 0;
526
527 while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD])
528 i++;
529 dev->rep[REP_PERIOD] = period[i];
530
Florin Malita8ea371f2006-08-23 00:45:33 -0400531 while (j < ARRAY_SIZE(delay) - 1 && delay[j] < dev->rep[REP_DELAY])
Dmitry Torokhov3d0f0fa2006-08-04 22:52:46 -0400532 j++;
533 dev->rep[REP_DELAY] = delay[j];
534
535 param = i | (j << 5);
536 return ps2_command(&atkbd->ps2dev, &param, ATKBD_CMD_SETREP);
537}
538
539static int atkbd_set_leds(struct atkbd *atkbd)
540{
541 struct input_dev *dev = atkbd->dev;
542 unsigned char param[2];
543
544 param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
545 | (test_bit(LED_NUML, dev->led) ? 2 : 0)
546 | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
547 if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
548 return -1;
549
550 if (atkbd->extra) {
551 param[0] = 0;
552 param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
553 | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
554 | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
555 | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
556 | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
557 if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS))
558 return -1;
559 }
560
561 return 0;
562}
563
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564/*
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500565 * atkbd_event_work() is used to complete processing of events that
566 * can not be processed by input_event() which is often called from
567 * interrupt context.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 */
569
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500570static void atkbd_event_work(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500572 struct atkbd *atkbd = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573
Ingo Molnar33d3f072006-02-19 00:22:18 -0500574 mutex_lock(&atkbd->event_mutex);
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500575
Dmitry Torokhov3d0f0fa2006-08-04 22:52:46 -0400576 if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
577 atkbd_set_leds(atkbd);
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500578
Dmitry Torokhov3d0f0fa2006-08-04 22:52:46 -0400579 if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
580 atkbd_set_repeat_rate(atkbd);
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500581
Ingo Molnar33d3f072006-02-19 00:22:18 -0500582 mutex_unlock(&atkbd->event_mutex);
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500583}
584
585/*
586 * Event callback from the input module. Events that change the state of
587 * the hardware are processed here. If action can not be performed in
588 * interrupt context it is offloaded to atkbd_event_work.
589 */
590
591static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
592{
593 struct atkbd *atkbd = dev->private;
594
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 if (!atkbd->write)
596 return -1;
597
598 switch (type) {
599
600 case EV_LED:
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500601 set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask);
602 wmb();
603 schedule_work(&atkbd->event_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 return 0;
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 case EV_REP:
607
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500608 if (!atkbd->softrepeat) {
609 set_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask);
610 wmb();
611 schedule_work(&atkbd->event_work);
612 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
614 return 0;
615 }
616
617 return -1;
618}
619
620/*
621 * atkbd_enable() signals that interrupt handler is allowed to
622 * generate input events.
623 */
624
625static inline void atkbd_enable(struct atkbd *atkbd)
626{
627 serio_pause_rx(atkbd->ps2dev.serio);
628 atkbd->enabled = 1;
629 serio_continue_rx(atkbd->ps2dev.serio);
630}
631
632/*
633 * atkbd_disable() tells input handler that all incoming data except
634 * for ACKs and command response should be dropped.
635 */
636
637static inline void atkbd_disable(struct atkbd *atkbd)
638{
639 serio_pause_rx(atkbd->ps2dev.serio);
640 atkbd->enabled = 0;
641 serio_continue_rx(atkbd->ps2dev.serio);
642}
643
644/*
645 * atkbd_probe() probes for an AT keyboard on a serio port.
646 */
647
648static int atkbd_probe(struct atkbd *atkbd)
649{
650 struct ps2dev *ps2dev = &atkbd->ps2dev;
651 unsigned char param[2];
652
653/*
654 * Some systems, where the bit-twiddling when testing the io-lines of the
655 * controller may confuse the keyboard need a full reset of the keyboard. On
656 * these systems the BIOS also usually doesn't do it for us.
657 */
658
659 if (atkbd_reset)
660 if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT))
661 printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", ps2dev->serio->phys);
662
663/*
664 * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
665 * Some keyboards report different values, but the first byte is always 0xab or
666 * 0xac. Some old AT keyboards don't report anything. If a mouse is connected, this
667 * should make sure we don't try to set the LEDs on it.
668 */
669
670 param[0] = param[1] = 0xa5; /* initialize with invalid values */
671 if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
672
673/*
674 * If the get ID command failed, we check if we can at least set the LEDs on
675 * the keyboard. This should work on every keyboard out there. It also turns
676 * the LEDs off, which we want anyway.
677 */
678 param[0] = 0;
679 if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
680 return -1;
681 atkbd->id = 0xabba;
682 return 0;
683 }
684
Dmitry Torokhov98078792006-09-14 01:31:27 -0400685 if (!ps2_is_keyboard_id(param[0]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 return -1;
687
688 atkbd->id = (param[0] << 8) | param[1];
689
690 if (atkbd->id == 0xaca1 && atkbd->translated) {
691 printk(KERN_ERR "atkbd.c: NCD terminal keyboards are only supported on non-translating\n");
692 printk(KERN_ERR "atkbd.c: controllers. Use i8042.direct=1 to disable translation.\n");
693 return -1;
694 }
695
696 return 0;
697}
698
699/*
700 * atkbd_select_set checks if a keyboard has a working Set 3 support, and
701 * sets it into that. Unfortunately there are keyboards that can be switched
702 * to Set 3, but don't work well in that (BTC Multimedia ...)
703 */
704
705static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra)
706{
707 struct ps2dev *ps2dev = &atkbd->ps2dev;
708 unsigned char param[2];
709
710 atkbd->extra = 0;
711/*
712 * For known special keyboards we can go ahead and set the correct set.
713 * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and
714 * IBM RapidAccess / IBM EzButton / Chicony KBP-8993 keyboards.
715 */
716
717 if (atkbd->translated)
718 return 2;
719
720 if (atkbd->id == 0xaca1) {
721 param[0] = 3;
722 ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET);
723 return 3;
724 }
725
726 if (allow_extra) {
727 param[0] = 0x71;
728 if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) {
729 atkbd->extra = 1;
730 return 2;
731 }
732 }
733
734 if (target_set != 3)
735 return 2;
736
737 if (!ps2_command(ps2dev, param, ATKBD_CMD_OK_GETID)) {
738 atkbd->id = param[0] << 8 | param[1];
739 return 2;
740 }
741
742 param[0] = 3;
743 if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))
744 return 2;
745
746 param[0] = 0;
747 if (ps2_command(ps2dev, param, ATKBD_CMD_GSCANSET))
748 return 2;
749
750 if (param[0] != 3) {
751 param[0] = 2;
752 if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))
753 return 2;
754 }
755
756 ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MBR);
757
758 return 3;
759}
760
761static int atkbd_activate(struct atkbd *atkbd)
762{
763 struct ps2dev *ps2dev = &atkbd->ps2dev;
764 unsigned char param[1];
765
766/*
767 * Set the LEDs to a defined state.
768 */
769
770 param[0] = 0;
771 if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
772 return -1;
773
774/*
775 * Set autorepeat to fastest possible.
776 */
777
778 param[0] = 0;
779 if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
780 return -1;
781
782/*
783 * Enable the keyboard to receive keystrokes.
784 */
785
786 if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
787 printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
788 ps2dev->serio->phys);
789 return -1;
790 }
791
792 return 0;
793}
794
795/*
796 * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
797 * reboot.
798 */
799
800static void atkbd_cleanup(struct serio *serio)
801{
802 struct atkbd *atkbd = serio_get_drvdata(serio);
803 ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT);
804}
805
806
807/*
808 * atkbd_disconnect() closes and frees.
809 */
810
811static void atkbd_disconnect(struct serio *serio)
812{
813 struct atkbd *atkbd = serio_get_drvdata(serio);
814
815 atkbd_disable(atkbd);
816
817 /* make sure we don't have a command in flight */
Paul E. McKenneyfbd568a3e2005-05-01 08:59:04 -0700818 synchronize_sched(); /* Allow atkbd_interrupt()s to complete. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 flush_scheduled_work();
820
Dmitry Torokhov86255d92006-10-11 01:44:46 -0400821 sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500822 input_unregister_device(atkbd->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 serio_close(serio);
824 serio_set_drvdata(serio, NULL);
825 kfree(atkbd);
826}
827
828
829/*
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500830 * atkbd_set_keycode_table() initializes keyboard's keycode table
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 * according to the selected scancode set
832 */
833
834static void atkbd_set_keycode_table(struct atkbd *atkbd)
835{
836 int i, j;
837
838 memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
839
840 if (atkbd->translated) {
841 for (i = 0; i < 128; i++) {
842 atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
843 atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
844 if (atkbd->scroll)
845 for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++)
846 if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j].set2)
847 atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
848 }
849 } else if (atkbd->set == 3) {
850 memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
851 } else {
852 memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
853
854 if (atkbd->scroll)
855 for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
856 atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode;
857 }
Dmitry Torokhov0ae051a2006-06-26 01:52:34 -0400858
859 atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL)] = KEY_HANGUEL;
860 atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA)] = KEY_HANJA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861}
862
863/*
864 * atkbd_set_device_attrs() sets up keyboard's input device structure
865 */
866
867static void atkbd_set_device_attrs(struct atkbd *atkbd)
868{
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500869 struct input_dev *input_dev = atkbd->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 int i;
871
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500872 if (atkbd->extra)
Dmitry Torokhovea08c6f2006-06-26 01:46:17 -0400873 snprintf(atkbd->name, sizeof(atkbd->name),
874 "AT Set 2 Extra keyboard");
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500875 else
Dmitry Torokhovea08c6f2006-06-26 01:46:17 -0400876 snprintf(atkbd->name, sizeof(atkbd->name),
877 "AT %s Set %d keyboard",
878 atkbd->translated ? "Translated" : "Raw", atkbd->set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
Dmitry Torokhovea08c6f2006-06-26 01:46:17 -0400880 snprintf(atkbd->phys, sizeof(atkbd->phys),
881 "%s/input0", atkbd->ps2dev.serio->phys);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500883 input_dev->name = atkbd->name;
884 input_dev->phys = atkbd->phys;
885 input_dev->id.bustype = BUS_I8042;
886 input_dev->id.vendor = 0x0001;
887 input_dev->id.product = atkbd->translated ? 1 : atkbd->set;
888 input_dev->id.version = atkbd->id;
889 input_dev->event = atkbd_event;
890 input_dev->private = atkbd;
891 input_dev->cdev.dev = &atkbd->ps2dev.serio->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500893 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894
895 if (atkbd->write) {
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500896 input_dev->evbit[0] |= BIT(EV_LED);
897 input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 }
899
900 if (atkbd->extra)
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500901 input_dev->ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
903
904 if (!atkbd->softrepeat) {
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500905 input_dev->rep[REP_DELAY] = 250;
906 input_dev->rep[REP_PERIOD] = 33;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 }
908
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500909 input_dev->mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910
911 if (atkbd->scroll) {
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500912 input_dev->evbit[0] |= BIT(EV_REL);
913 input_dev->relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
914 set_bit(BTN_MIDDLE, input_dev->keybit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 }
916
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500917 input_dev->keycode = atkbd->keycode;
918 input_dev->keycodesize = sizeof(unsigned char);
919 input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
921 for (i = 0; i < 512; i++)
922 if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500923 set_bit(atkbd->keycode[i], input_dev->keybit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924}
925
926/*
927 * atkbd_connect() is called when the serio module finds an interface
928 * that isn't handled yet by an appropriate device driver. We check if
929 * there is an AT keyboard out there and if yes, we register ourselves
930 * to the input module.
931 */
932
933static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
934{
935 struct atkbd *atkbd;
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500936 struct input_dev *dev;
937 int err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500939 atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
940 dev = input_allocate_device();
941 if (!atkbd || !dev)
942 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500944 atkbd->dev = dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 ps2_init(&atkbd->ps2dev, serio);
Dmitry Torokhov0d4c8592005-11-20 00:49:42 -0500946 INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd);
Ingo Molnar33d3f072006-02-19 00:22:18 -0500947 mutex_init(&atkbd->event_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 switch (serio->id.type) {
950
951 case SERIO_8042_XL:
952 atkbd->translated = 1;
953 case SERIO_8042:
954 if (serio->write)
955 atkbd->write = 1;
956 break;
957 }
958
959 atkbd->softraw = atkbd_softraw;
960 atkbd->softrepeat = atkbd_softrepeat;
961 atkbd->scroll = atkbd_scroll;
962
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 if (atkbd->softrepeat)
964 atkbd->softraw = 1;
965
966 serio_set_drvdata(serio, atkbd);
967
968 err = serio_open(serio, drv);
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500969 if (err)
970 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
972 if (atkbd->write) {
973
974 if (atkbd_probe(atkbd)) {
975 serio_close(serio);
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500976 err = -ENODEV;
977 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 }
979
980 atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
981 atkbd_activate(atkbd);
982
983 } else {
984 atkbd->set = 2;
985 atkbd->id = 0xab00;
986 }
987
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 atkbd_set_keycode_table(atkbd);
989 atkbd_set_device_attrs(atkbd);
990
Dmitry Torokhov86255d92006-10-11 01:44:46 -0400991 sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
993 atkbd_enable(atkbd);
994
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500995 input_register_device(atkbd->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 return 0;
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -0500998
999 fail: serio_set_drvdata(serio, NULL);
1000 input_free_device(dev);
1001 kfree(atkbd);
1002 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003}
1004
1005/*
1006 * atkbd_reconnect() tries to restore keyboard into a sane state and is
1007 * most likely called on resume.
1008 */
1009
1010static int atkbd_reconnect(struct serio *serio)
1011{
1012 struct atkbd *atkbd = serio_get_drvdata(serio);
1013 struct serio_driver *drv = serio->drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014
1015 if (!atkbd || !drv) {
1016 printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
1017 return -1;
1018 }
1019
1020 atkbd_disable(atkbd);
1021
1022 if (atkbd->write) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 if (atkbd_probe(atkbd))
1024 return -1;
1025 if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
1026 return -1;
1027
1028 atkbd_activate(atkbd);
1029
Dmitry Torokhov3d0f0fa2006-08-04 22:52:46 -04001030/*
1031 * Restore repeat rate and LEDs (that were reset by atkbd_activate)
1032 * to pre-resume state
1033 */
1034 if (!atkbd->softrepeat)
1035 atkbd_set_repeat_rate(atkbd);
1036 atkbd_set_leds(atkbd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 }
1038
1039 atkbd_enable(atkbd);
1040
1041 return 0;
1042}
1043
1044static struct serio_device_id atkbd_serio_ids[] = {
1045 {
1046 .type = SERIO_8042,
1047 .proto = SERIO_ANY,
1048 .id = SERIO_ANY,
1049 .extra = SERIO_ANY,
1050 },
1051 {
1052 .type = SERIO_8042_XL,
1053 .proto = SERIO_ANY,
1054 .id = SERIO_ANY,
1055 .extra = SERIO_ANY,
1056 },
1057 {
1058 .type = SERIO_RS232,
1059 .proto = SERIO_PS2SER,
1060 .id = SERIO_ANY,
1061 .extra = SERIO_ANY,
1062 },
1063 { 0 }
1064};
1065
1066MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);
1067
1068static struct serio_driver atkbd_drv = {
1069 .driver = {
1070 .name = "atkbd",
1071 },
1072 .description = DRIVER_DESC,
1073 .id_table = atkbd_serio_ids,
1074 .interrupt = atkbd_interrupt,
1075 .connect = atkbd_connect,
1076 .reconnect = atkbd_reconnect,
1077 .disconnect = atkbd_disconnect,
1078 .cleanup = atkbd_cleanup,
1079};
1080
1081static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
1082 ssize_t (*handler)(struct atkbd *, char *))
1083{
1084 struct serio *serio = to_serio_port(dev);
1085 int retval;
1086
1087 retval = serio_pin_driver(serio);
1088 if (retval)
1089 return retval;
1090
1091 if (serio->drv != &atkbd_drv) {
1092 retval = -ENODEV;
1093 goto out;
1094 }
1095
1096 retval = handler((struct atkbd *)serio_get_drvdata(serio), buf);
1097
1098out:
1099 serio_unpin_driver(serio);
1100 return retval;
1101}
1102
1103static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
1104 ssize_t (*handler)(struct atkbd *, const char *, size_t))
1105{
1106 struct serio *serio = to_serio_port(dev);
1107 struct atkbd *atkbd;
1108 int retval;
1109
1110 retval = serio_pin_driver(serio);
1111 if (retval)
1112 return retval;
1113
1114 if (serio->drv != &atkbd_drv) {
1115 retval = -ENODEV;
1116 goto out;
1117 }
1118
1119 atkbd = serio_get_drvdata(serio);
1120 atkbd_disable(atkbd);
1121 retval = handler(atkbd, buf, count);
1122 atkbd_enable(atkbd);
1123
1124out:
1125 serio_unpin_driver(serio);
1126 return retval;
1127}
1128
1129static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
1130{
1131 return sprintf(buf, "%d\n", atkbd->extra ? 1 : 0);
1132}
1133
1134static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
1135{
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001136 struct input_dev *new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 unsigned long value;
1138 char *rest;
1139
1140 if (!atkbd->write)
1141 return -EIO;
1142
1143 value = simple_strtoul(buf, &rest, 10);
1144 if (*rest || value > 1)
1145 return -EINVAL;
1146
1147 if (atkbd->extra != value) {
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001148 /*
1149 * Since device's properties will change we need to
1150 * unregister old device. But allocate new one first
1151 * to make sure we have it.
1152 */
1153 if (!(new_dev = input_allocate_device()))
1154 return -ENOMEM;
1155 input_unregister_device(atkbd->dev);
1156 atkbd->dev = new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
1158 atkbd_activate(atkbd);
1159 atkbd_set_device_attrs(atkbd);
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001160 input_register_device(atkbd->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 }
1162 return count;
1163}
1164
1165static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
1166{
1167 return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0);
1168}
1169
1170static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
1171{
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001172 struct input_dev *new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 unsigned long value;
1174 char *rest;
1175
1176 value = simple_strtoul(buf, &rest, 10);
1177 if (*rest || value > 1)
1178 return -EINVAL;
1179
1180 if (atkbd->scroll != value) {
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001181 if (!(new_dev = input_allocate_device()))
1182 return -ENOMEM;
1183 input_unregister_device(atkbd->dev);
1184 atkbd->dev = new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 atkbd->scroll = value;
1186 atkbd_set_keycode_table(atkbd);
1187 atkbd_set_device_attrs(atkbd);
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001188 input_register_device(atkbd->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 }
1190 return count;
1191}
1192
1193static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
1194{
1195 return sprintf(buf, "%d\n", atkbd->set);
1196}
1197
1198static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
1199{
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001200 struct input_dev *new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 unsigned long value;
1202 char *rest;
1203
1204 if (!atkbd->write)
1205 return -EIO;
1206
1207 value = simple_strtoul(buf, &rest, 10);
1208 if (*rest || (value != 2 && value != 3))
1209 return -EINVAL;
1210
1211 if (atkbd->set != value) {
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001212 if (!(new_dev = input_allocate_device()))
1213 return -ENOMEM;
1214 input_unregister_device(atkbd->dev);
1215 atkbd->dev = new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
1217 atkbd_activate(atkbd);
1218 atkbd_set_keycode_table(atkbd);
1219 atkbd_set_device_attrs(atkbd);
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001220 input_register_device(atkbd->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 }
1222 return count;
1223}
1224
1225static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
1226{
1227 return sprintf(buf, "%d\n", atkbd->softrepeat ? 1 : 0);
1228}
1229
1230static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
1231{
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001232 struct input_dev *new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 unsigned long value;
1234 char *rest;
1235
1236 if (!atkbd->write)
1237 return -EIO;
1238
1239 value = simple_strtoul(buf, &rest, 10);
1240 if (*rest || value > 1)
1241 return -EINVAL;
1242
1243 if (atkbd->softrepeat != value) {
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001244 if (!(new_dev = input_allocate_device()))
1245 return -ENOMEM;
1246 input_unregister_device(atkbd->dev);
1247 atkbd->dev = new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 atkbd->softrepeat = value;
1249 if (atkbd->softrepeat)
1250 atkbd->softraw = 1;
1251 atkbd_set_device_attrs(atkbd);
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001252 input_register_device(atkbd->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 return count;
1255}
1256
1257
1258static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
1259{
1260 return sprintf(buf, "%d\n", atkbd->softraw ? 1 : 0);
1261}
1262
1263static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
1264{
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001265 struct input_dev *new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 unsigned long value;
1267 char *rest;
1268
1269 value = simple_strtoul(buf, &rest, 10);
1270 if (*rest || value > 1)
1271 return -EINVAL;
1272
1273 if (atkbd->softraw != value) {
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001274 if (!(new_dev = input_allocate_device()))
1275 return -ENOMEM;
1276 input_unregister_device(atkbd->dev);
1277 atkbd->dev = new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 atkbd->softraw = value;
1279 atkbd_set_device_attrs(atkbd);
Dmitry Torokhov3c42f0c2005-09-15 02:01:45 -05001280 input_register_device(atkbd->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 }
1282 return count;
1283}
1284
Dmitry Torokhov86255d92006-10-11 01:44:46 -04001285static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf)
1286{
1287 return sprintf(buf, "%lu\n", atkbd->err_count);
1288}
1289
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
1291static int __init atkbd_init(void)
1292{
1293 serio_register_driver(&atkbd_drv);
1294 return 0;
1295}
1296
1297static void __exit atkbd_exit(void)
1298{
1299 serio_unregister_driver(&atkbd_drv);
1300}
1301
1302module_init(atkbd_init);
1303module_exit(atkbd_exit);