1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * AT and PS/2 keyboard driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 1999-2002 Vojtech Pavlik
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun /*
10*4882a593Smuzhiyun * This driver can handle standard AT keyboards and PS/2 keyboards in
11*4882a593Smuzhiyun * Translated and Raw Set 2 and Set 3, as well as AT keyboards on dumb
12*4882a593Smuzhiyun * input-only controllers and AT keyboards connected over a one way RS232
13*4882a593Smuzhiyun * converter.
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <linux/slab.h>
19*4882a593Smuzhiyun #include <linux/interrupt.h>
20*4882a593Smuzhiyun #include <linux/init.h>
21*4882a593Smuzhiyun #include <linux/input.h>
22*4882a593Smuzhiyun #include <linux/serio.h>
23*4882a593Smuzhiyun #include <linux/workqueue.h>
24*4882a593Smuzhiyun #include <linux/libps2.h>
25*4882a593Smuzhiyun #include <linux/mutex.h>
26*4882a593Smuzhiyun #include <linux/dmi.h>
27*4882a593Smuzhiyun #include <linux/property.h>
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define DRIVER_DESC "AT and PS/2 keyboard driver"
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
32*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
33*4882a593Smuzhiyun MODULE_LICENSE("GPL");
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun static int atkbd_set = 2;
36*4882a593Smuzhiyun module_param_named(set, atkbd_set, int, 0);
37*4882a593Smuzhiyun MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)");
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
40*4882a593Smuzhiyun static bool atkbd_reset;
41*4882a593Smuzhiyun #else
42*4882a593Smuzhiyun static bool atkbd_reset = true;
43*4882a593Smuzhiyun #endif
44*4882a593Smuzhiyun module_param_named(reset, atkbd_reset, bool, 0);
45*4882a593Smuzhiyun MODULE_PARM_DESC(reset, "Reset keyboard during initialization");
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static bool atkbd_softrepeat;
48*4882a593Smuzhiyun module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
49*4882a593Smuzhiyun MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun static bool atkbd_softraw = true;
52*4882a593Smuzhiyun module_param_named(softraw, atkbd_softraw, bool, 0);
53*4882a593Smuzhiyun MODULE_PARM_DESC(softraw, "Use software generated rawmode");
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun static bool atkbd_scroll;
56*4882a593Smuzhiyun module_param_named(scroll, atkbd_scroll, bool, 0);
57*4882a593Smuzhiyun MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun static bool atkbd_extra;
60*4882a593Smuzhiyun module_param_named(extra, atkbd_extra, bool, 0);
61*4882a593Smuzhiyun MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static bool atkbd_terminal;
64*4882a593Smuzhiyun module_param_named(terminal, atkbd_terminal, bool, 0);
65*4882a593Smuzhiyun MODULE_PARM_DESC(terminal, "Enable break codes on an IBM Terminal keyboard connected via AT/PS2");
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #define MAX_FUNCTION_ROW_KEYS 24
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #define SCANCODE(keymap) ((keymap >> 16) & 0xFFFF)
70*4882a593Smuzhiyun #define KEYCODE(keymap) (keymap & 0xFFFF)
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /*
73*4882a593Smuzhiyun * Scancode to keycode tables. These are just the default setting, and
74*4882a593Smuzhiyun * are loadable via a userland utility.
75*4882a593Smuzhiyun */
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #define ATKBD_KEYMAP_SIZE 512
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = {
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* XXX: need a more general approach */
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun #include "hpps2atkbd.h" /* include the keyboard scancodes */
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun #else
88*4882a593Smuzhiyun 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
89*4882a593Smuzhiyun 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
90*4882a593Smuzhiyun 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
91*4882a593Smuzhiyun 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
92*4882a593Smuzhiyun 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
93*4882a593Smuzhiyun 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
94*4882a593Smuzhiyun 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
95*4882a593Smuzhiyun 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98*4882a593Smuzhiyun 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
99*4882a593Smuzhiyun 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
100*4882a593Smuzhiyun 159, 0,115, 0,164, 0, 0,116,158, 0,172,166, 0, 0, 0,142,
101*4882a593Smuzhiyun 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
102*4882a593Smuzhiyun 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
103*4882a593Smuzhiyun 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
104*4882a593Smuzhiyun 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun 0, 0, 0, 65, 99,
107*4882a593Smuzhiyun #endif
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun static const unsigned short atkbd_set3_keycode[ATKBD_KEYMAP_SIZE] = {
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60,
113*4882a593Smuzhiyun 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62,
114*4882a593Smuzhiyun 134, 46, 45, 32, 18, 5, 4, 63,135, 57, 47, 33, 20, 19, 6, 64,
115*4882a593Smuzhiyun 136, 49, 48, 35, 34, 21, 7, 65,137,100, 50, 36, 22, 8, 9, 66,
116*4882a593Smuzhiyun 125, 51, 37, 23, 24, 11, 10, 67,126, 52, 53, 38, 39, 25, 12, 68,
117*4882a593Smuzhiyun 113,114, 40, 43, 26, 13, 87, 99, 97, 54, 28, 27, 43, 43, 88, 70,
118*4882a593Smuzhiyun 108,105,119,103,111,107, 14,110, 0, 79,106, 75, 71,109,102,104,
119*4882a593Smuzhiyun 82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55,183,
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun 184,185,186,187, 74, 94, 92, 93, 0, 0, 0,125,126,127,112, 0,
122*4882a593Smuzhiyun 0,139,172,163,165,115,152,172,166,140,160,154,113,114,167,168,
123*4882a593Smuzhiyun 148,149,147,140
124*4882a593Smuzhiyun };
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun static const unsigned short atkbd_unxlate_table[128] = {
127*4882a593Smuzhiyun 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
128*4882a593Smuzhiyun 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
129*4882a593Smuzhiyun 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
130*4882a593Smuzhiyun 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
131*4882a593Smuzhiyun 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
132*4882a593Smuzhiyun 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
133*4882a593Smuzhiyun 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
134*4882a593Smuzhiyun 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun #define ATKBD_CMD_SETLEDS 0x10ed
138*4882a593Smuzhiyun #define ATKBD_CMD_GSCANSET 0x11f0
139*4882a593Smuzhiyun #define ATKBD_CMD_SSCANSET 0x10f0
140*4882a593Smuzhiyun #define ATKBD_CMD_GETID 0x02f2
141*4882a593Smuzhiyun #define ATKBD_CMD_SETREP 0x10f3
142*4882a593Smuzhiyun #define ATKBD_CMD_ENABLE 0x00f4
143*4882a593Smuzhiyun #define ATKBD_CMD_RESET_DIS 0x00f5 /* Reset to defaults and disable */
144*4882a593Smuzhiyun #define ATKBD_CMD_RESET_DEF 0x00f6 /* Reset to defaults */
145*4882a593Smuzhiyun #define ATKBD_CMD_SETALL_MB 0x00f8 /* Set all keys to give break codes */
146*4882a593Smuzhiyun #define ATKBD_CMD_SETALL_MBR 0x00fa /* ... and repeat */
147*4882a593Smuzhiyun #define ATKBD_CMD_RESET_BAT 0x02ff
148*4882a593Smuzhiyun #define ATKBD_CMD_RESEND 0x00fe
149*4882a593Smuzhiyun #define ATKBD_CMD_EX_ENABLE 0x10ea
150*4882a593Smuzhiyun #define ATKBD_CMD_EX_SETLEDS 0x20eb
151*4882a593Smuzhiyun #define ATKBD_CMD_OK_GETID 0x02e8
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun #define ATKBD_RET_ACK 0xfa
154*4882a593Smuzhiyun #define ATKBD_RET_NAK 0xfe
155*4882a593Smuzhiyun #define ATKBD_RET_BAT 0xaa
156*4882a593Smuzhiyun #define ATKBD_RET_EMUL0 0xe0
157*4882a593Smuzhiyun #define ATKBD_RET_EMUL1 0xe1
158*4882a593Smuzhiyun #define ATKBD_RET_RELEASE 0xf0
159*4882a593Smuzhiyun #define ATKBD_RET_HANJA 0xf1
160*4882a593Smuzhiyun #define ATKBD_RET_HANGEUL 0xf2
161*4882a593Smuzhiyun #define ATKBD_RET_ERR 0xff
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun #define ATKBD_KEY_UNKNOWN 0
164*4882a593Smuzhiyun #define ATKBD_KEY_NULL 255
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun #define ATKBD_SCR_1 0xfffe
167*4882a593Smuzhiyun #define ATKBD_SCR_2 0xfffd
168*4882a593Smuzhiyun #define ATKBD_SCR_4 0xfffc
169*4882a593Smuzhiyun #define ATKBD_SCR_8 0xfffb
170*4882a593Smuzhiyun #define ATKBD_SCR_CLICK 0xfffa
171*4882a593Smuzhiyun #define ATKBD_SCR_LEFT 0xfff9
172*4882a593Smuzhiyun #define ATKBD_SCR_RIGHT 0xfff8
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun #define ATKBD_SPECIAL ATKBD_SCR_RIGHT
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun #define ATKBD_LED_EVENT_BIT 0
177*4882a593Smuzhiyun #define ATKBD_REP_EVENT_BIT 1
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun #define ATKBD_XL_ERR 0x01
180*4882a593Smuzhiyun #define ATKBD_XL_BAT 0x02
181*4882a593Smuzhiyun #define ATKBD_XL_ACK 0x04
182*4882a593Smuzhiyun #define ATKBD_XL_NAK 0x08
183*4882a593Smuzhiyun #define ATKBD_XL_HANGEUL 0x10
184*4882a593Smuzhiyun #define ATKBD_XL_HANJA 0x20
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun static const struct {
187*4882a593Smuzhiyun unsigned short keycode;
188*4882a593Smuzhiyun unsigned char set2;
189*4882a593Smuzhiyun } atkbd_scroll_keys[] = {
190*4882a593Smuzhiyun { ATKBD_SCR_1, 0xc5 },
191*4882a593Smuzhiyun { ATKBD_SCR_2, 0x9d },
192*4882a593Smuzhiyun { ATKBD_SCR_4, 0xa4 },
193*4882a593Smuzhiyun { ATKBD_SCR_8, 0x9b },
194*4882a593Smuzhiyun { ATKBD_SCR_CLICK, 0xe0 },
195*4882a593Smuzhiyun { ATKBD_SCR_LEFT, 0xcb },
196*4882a593Smuzhiyun { ATKBD_SCR_RIGHT, 0xd2 },
197*4882a593Smuzhiyun };
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun /*
200*4882a593Smuzhiyun * The atkbd control structure
201*4882a593Smuzhiyun */
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun struct atkbd {
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun struct ps2dev ps2dev;
206*4882a593Smuzhiyun struct input_dev *dev;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* Written only during init */
209*4882a593Smuzhiyun char name[64];
210*4882a593Smuzhiyun char phys[32];
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun unsigned short id;
213*4882a593Smuzhiyun unsigned short keycode[ATKBD_KEYMAP_SIZE];
214*4882a593Smuzhiyun DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE);
215*4882a593Smuzhiyun unsigned char set;
216*4882a593Smuzhiyun bool translated;
217*4882a593Smuzhiyun bool extra;
218*4882a593Smuzhiyun bool write;
219*4882a593Smuzhiyun bool softrepeat;
220*4882a593Smuzhiyun bool softraw;
221*4882a593Smuzhiyun bool scroll;
222*4882a593Smuzhiyun bool enabled;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun /* Accessed only from interrupt */
225*4882a593Smuzhiyun unsigned char emul;
226*4882a593Smuzhiyun bool resend;
227*4882a593Smuzhiyun bool release;
228*4882a593Smuzhiyun unsigned long xl_bit;
229*4882a593Smuzhiyun unsigned int last;
230*4882a593Smuzhiyun unsigned long time;
231*4882a593Smuzhiyun unsigned long err_count;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun struct delayed_work event_work;
234*4882a593Smuzhiyun unsigned long event_jiffies;
235*4882a593Smuzhiyun unsigned long event_mask;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun /* Serializes reconnect(), attr->set() and event work */
238*4882a593Smuzhiyun struct mutex mutex;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun u32 function_row_physmap[MAX_FUNCTION_ROW_KEYS];
241*4882a593Smuzhiyun int num_function_row_keys;
242*4882a593Smuzhiyun };
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun /*
245*4882a593Smuzhiyun * System-specific keymap fixup routine
246*4882a593Smuzhiyun */
247*4882a593Smuzhiyun static void (*atkbd_platform_fixup)(struct atkbd *, const void *data);
248*4882a593Smuzhiyun static void *atkbd_platform_fixup_data;
249*4882a593Smuzhiyun static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /*
252*4882a593Smuzhiyun * Certain keyboards to not like ATKBD_CMD_RESET_DIS and stop responding
253*4882a593Smuzhiyun * to many commands until full reset (ATKBD_CMD_RESET_BAT) is performed.
254*4882a593Smuzhiyun */
255*4882a593Smuzhiyun static bool atkbd_skip_deactivate;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
258*4882a593Smuzhiyun ssize_t (*handler)(struct atkbd *, char *));
259*4882a593Smuzhiyun static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
260*4882a593Smuzhiyun ssize_t (*handler)(struct atkbd *, const char *, size_t));
261*4882a593Smuzhiyun #define ATKBD_DEFINE_ATTR(_name) \
262*4882a593Smuzhiyun static ssize_t atkbd_show_##_name(struct atkbd *, char *); \
263*4882a593Smuzhiyun static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \
264*4882a593Smuzhiyun static ssize_t atkbd_do_show_##_name(struct device *d, \
265*4882a593Smuzhiyun struct device_attribute *attr, char *b) \
266*4882a593Smuzhiyun { \
267*4882a593Smuzhiyun return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \
268*4882a593Smuzhiyun } \
269*4882a593Smuzhiyun static ssize_t atkbd_do_set_##_name(struct device *d, \
270*4882a593Smuzhiyun struct device_attribute *attr, const char *b, size_t s) \
271*4882a593Smuzhiyun { \
272*4882a593Smuzhiyun return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \
273*4882a593Smuzhiyun } \
274*4882a593Smuzhiyun static struct device_attribute atkbd_attr_##_name = \
275*4882a593Smuzhiyun __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name);
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun ATKBD_DEFINE_ATTR(extra);
278*4882a593Smuzhiyun ATKBD_DEFINE_ATTR(force_release);
279*4882a593Smuzhiyun ATKBD_DEFINE_ATTR(scroll);
280*4882a593Smuzhiyun ATKBD_DEFINE_ATTR(set);
281*4882a593Smuzhiyun ATKBD_DEFINE_ATTR(softrepeat);
282*4882a593Smuzhiyun ATKBD_DEFINE_ATTR(softraw);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun #define ATKBD_DEFINE_RO_ATTR(_name) \
285*4882a593Smuzhiyun static ssize_t atkbd_show_##_name(struct atkbd *, char *); \
286*4882a593Smuzhiyun static ssize_t atkbd_do_show_##_name(struct device *d, \
287*4882a593Smuzhiyun struct device_attribute *attr, char *b) \
288*4882a593Smuzhiyun { \
289*4882a593Smuzhiyun return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \
290*4882a593Smuzhiyun } \
291*4882a593Smuzhiyun static struct device_attribute atkbd_attr_##_name = \
292*4882a593Smuzhiyun __ATTR(_name, S_IRUGO, atkbd_do_show_##_name, NULL);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun ATKBD_DEFINE_RO_ATTR(err_count);
295*4882a593Smuzhiyun ATKBD_DEFINE_RO_ATTR(function_row_physmap);
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun static struct attribute *atkbd_attributes[] = {
298*4882a593Smuzhiyun &atkbd_attr_extra.attr,
299*4882a593Smuzhiyun &atkbd_attr_force_release.attr,
300*4882a593Smuzhiyun &atkbd_attr_scroll.attr,
301*4882a593Smuzhiyun &atkbd_attr_set.attr,
302*4882a593Smuzhiyun &atkbd_attr_softrepeat.attr,
303*4882a593Smuzhiyun &atkbd_attr_softraw.attr,
304*4882a593Smuzhiyun &atkbd_attr_err_count.attr,
305*4882a593Smuzhiyun &atkbd_attr_function_row_physmap.attr,
306*4882a593Smuzhiyun NULL
307*4882a593Smuzhiyun };
308*4882a593Smuzhiyun
atkbd_show_function_row_physmap(struct atkbd * atkbd,char * buf)309*4882a593Smuzhiyun static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun ssize_t size = 0;
312*4882a593Smuzhiyun int i;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun if (!atkbd->num_function_row_keys)
315*4882a593Smuzhiyun return 0;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun for (i = 0; i < atkbd->num_function_row_keys; i++)
318*4882a593Smuzhiyun size += scnprintf(buf + size, PAGE_SIZE - size, "%02X ",
319*4882a593Smuzhiyun atkbd->function_row_physmap[i]);
320*4882a593Smuzhiyun size += scnprintf(buf + size, PAGE_SIZE - size, "\n");
321*4882a593Smuzhiyun return size;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
atkbd_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)324*4882a593Smuzhiyun static umode_t atkbd_attr_is_visible(struct kobject *kobj,
325*4882a593Smuzhiyun struct attribute *attr, int i)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun struct device *dev = container_of(kobj, struct device, kobj);
328*4882a593Smuzhiyun struct serio *serio = to_serio_port(dev);
329*4882a593Smuzhiyun struct atkbd *atkbd = serio_get_drvdata(serio);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun if (attr == &atkbd_attr_function_row_physmap.attr &&
332*4882a593Smuzhiyun !atkbd->num_function_row_keys)
333*4882a593Smuzhiyun return 0;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun return attr->mode;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun static struct attribute_group atkbd_attribute_group = {
339*4882a593Smuzhiyun .attrs = atkbd_attributes,
340*4882a593Smuzhiyun .is_visible = atkbd_attr_is_visible,
341*4882a593Smuzhiyun };
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun static const unsigned int xl_table[] = {
344*4882a593Smuzhiyun ATKBD_RET_BAT, ATKBD_RET_ERR, ATKBD_RET_ACK,
345*4882a593Smuzhiyun ATKBD_RET_NAK, ATKBD_RET_HANJA, ATKBD_RET_HANGEUL,
346*4882a593Smuzhiyun };
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun /*
349*4882a593Smuzhiyun * Checks if we should mangle the scancode to extract 'release' bit
350*4882a593Smuzhiyun * in translated mode.
351*4882a593Smuzhiyun */
atkbd_need_xlate(unsigned long xl_bit,unsigned char code)352*4882a593Smuzhiyun static bool atkbd_need_xlate(unsigned long xl_bit, unsigned char code)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun int i;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1)
357*4882a593Smuzhiyun return false;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(xl_table); i++)
360*4882a593Smuzhiyun if (code == xl_table[i])
361*4882a593Smuzhiyun return test_bit(i, &xl_bit);
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun return true;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun /*
367*4882a593Smuzhiyun * Calculates new value of xl_bit so the driver can distinguish
368*4882a593Smuzhiyun * between make/break pair of scancodes for select keys and PS/2
369*4882a593Smuzhiyun * protocol responses.
370*4882a593Smuzhiyun */
atkbd_calculate_xl_bit(struct atkbd * atkbd,unsigned char code)371*4882a593Smuzhiyun static void atkbd_calculate_xl_bit(struct atkbd *atkbd, unsigned char code)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun int i;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(xl_table); i++) {
376*4882a593Smuzhiyun if (!((code ^ xl_table[i]) & 0x7f)) {
377*4882a593Smuzhiyun if (code & 0x80)
378*4882a593Smuzhiyun __clear_bit(i, &atkbd->xl_bit);
379*4882a593Smuzhiyun else
380*4882a593Smuzhiyun __set_bit(i, &atkbd->xl_bit);
381*4882a593Smuzhiyun break;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun /*
387*4882a593Smuzhiyun * Encode the scancode, 0xe0 prefix, and high bit into a single integer,
388*4882a593Smuzhiyun * keeping kernel 2.4 compatibility for set 2
389*4882a593Smuzhiyun */
atkbd_compat_scancode(struct atkbd * atkbd,unsigned int code)390*4882a593Smuzhiyun static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun if (atkbd->set == 3) {
393*4882a593Smuzhiyun if (atkbd->emul == 1)
394*4882a593Smuzhiyun code |= 0x100;
395*4882a593Smuzhiyun } else {
396*4882a593Smuzhiyun code = (code & 0x7f) | ((code & 0x80) << 1);
397*4882a593Smuzhiyun if (atkbd->emul == 1)
398*4882a593Smuzhiyun code |= 0x80;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun return code;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun /*
405*4882a593Smuzhiyun * atkbd_interrupt(). Here takes place processing of data received from
406*4882a593Smuzhiyun * the keyboard into events.
407*4882a593Smuzhiyun */
408*4882a593Smuzhiyun
atkbd_interrupt(struct serio * serio,unsigned char data,unsigned int flags)409*4882a593Smuzhiyun static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
410*4882a593Smuzhiyun unsigned int flags)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun struct atkbd *atkbd = serio_get_drvdata(serio);
413*4882a593Smuzhiyun struct input_dev *dev = atkbd->dev;
414*4882a593Smuzhiyun unsigned int code = data;
415*4882a593Smuzhiyun int scroll = 0, hscroll = 0, click = -1;
416*4882a593Smuzhiyun int value;
417*4882a593Smuzhiyun unsigned short keycode;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun #if !defined(__i386__) && !defined (__x86_64__)
422*4882a593Smuzhiyun if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
423*4882a593Smuzhiyun dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags);
424*4882a593Smuzhiyun serio_write(serio, ATKBD_CMD_RESEND);
425*4882a593Smuzhiyun atkbd->resend = true;
426*4882a593Smuzhiyun goto out;
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun if (!flags && data == ATKBD_RET_ACK)
430*4882a593Smuzhiyun atkbd->resend = false;
431*4882a593Smuzhiyun #endif
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK))
434*4882a593Smuzhiyun if (ps2_handle_ack(&atkbd->ps2dev, data))
435*4882a593Smuzhiyun goto out;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD))
438*4882a593Smuzhiyun if (ps2_handle_response(&atkbd->ps2dev, data))
439*4882a593Smuzhiyun goto out;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun pm_wakeup_event(&serio->dev, 0);
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun if (!atkbd->enabled)
444*4882a593Smuzhiyun goto out;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun input_event(dev, EV_MSC, MSC_RAW, code);
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun if (atkbd_platform_scancode_fixup)
449*4882a593Smuzhiyun code = atkbd_platform_scancode_fixup(atkbd, code);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun if (atkbd->translated) {
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) {
454*4882a593Smuzhiyun atkbd->release = code >> 7;
455*4882a593Smuzhiyun code &= 0x7f;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun if (!atkbd->emul)
459*4882a593Smuzhiyun atkbd_calculate_xl_bit(atkbd, data);
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun switch (code) {
463*4882a593Smuzhiyun case ATKBD_RET_BAT:
464*4882a593Smuzhiyun atkbd->enabled = false;
465*4882a593Smuzhiyun serio_reconnect(atkbd->ps2dev.serio);
466*4882a593Smuzhiyun goto out;
467*4882a593Smuzhiyun case ATKBD_RET_EMUL0:
468*4882a593Smuzhiyun atkbd->emul = 1;
469*4882a593Smuzhiyun goto out;
470*4882a593Smuzhiyun case ATKBD_RET_EMUL1:
471*4882a593Smuzhiyun atkbd->emul = 2;
472*4882a593Smuzhiyun goto out;
473*4882a593Smuzhiyun case ATKBD_RET_RELEASE:
474*4882a593Smuzhiyun atkbd->release = true;
475*4882a593Smuzhiyun goto out;
476*4882a593Smuzhiyun case ATKBD_RET_ACK:
477*4882a593Smuzhiyun case ATKBD_RET_NAK:
478*4882a593Smuzhiyun if (printk_ratelimit())
479*4882a593Smuzhiyun dev_warn(&serio->dev,
480*4882a593Smuzhiyun "Spurious %s on %s. "
481*4882a593Smuzhiyun "Some program might be trying to access hardware directly.\n",
482*4882a593Smuzhiyun data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
483*4882a593Smuzhiyun goto out;
484*4882a593Smuzhiyun case ATKBD_RET_ERR:
485*4882a593Smuzhiyun atkbd->err_count++;
486*4882a593Smuzhiyun dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n",
487*4882a593Smuzhiyun serio->phys);
488*4882a593Smuzhiyun goto out;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun code = atkbd_compat_scancode(atkbd, code);
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun if (atkbd->emul && --atkbd->emul)
494*4882a593Smuzhiyun goto out;
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun keycode = atkbd->keycode[code];
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun if (!(atkbd->release && test_bit(code, atkbd->force_release_mask)))
499*4882a593Smuzhiyun if (keycode != ATKBD_KEY_NULL)
500*4882a593Smuzhiyun input_event(dev, EV_MSC, MSC_SCAN, code);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun switch (keycode) {
503*4882a593Smuzhiyun case ATKBD_KEY_NULL:
504*4882a593Smuzhiyun break;
505*4882a593Smuzhiyun case ATKBD_KEY_UNKNOWN:
506*4882a593Smuzhiyun dev_warn(&serio->dev,
507*4882a593Smuzhiyun "Unknown key %s (%s set %d, code %#x on %s).\n",
508*4882a593Smuzhiyun atkbd->release ? "released" : "pressed",
509*4882a593Smuzhiyun atkbd->translated ? "translated" : "raw",
510*4882a593Smuzhiyun atkbd->set, code, serio->phys);
511*4882a593Smuzhiyun dev_warn(&serio->dev,
512*4882a593Smuzhiyun "Use 'setkeycodes %s%02x <keycode>' to make it known.\n",
513*4882a593Smuzhiyun code & 0x80 ? "e0" : "", code & 0x7f);
514*4882a593Smuzhiyun input_sync(dev);
515*4882a593Smuzhiyun break;
516*4882a593Smuzhiyun case ATKBD_SCR_1:
517*4882a593Smuzhiyun scroll = 1;
518*4882a593Smuzhiyun break;
519*4882a593Smuzhiyun case ATKBD_SCR_2:
520*4882a593Smuzhiyun scroll = 2;
521*4882a593Smuzhiyun break;
522*4882a593Smuzhiyun case ATKBD_SCR_4:
523*4882a593Smuzhiyun scroll = 4;
524*4882a593Smuzhiyun break;
525*4882a593Smuzhiyun case ATKBD_SCR_8:
526*4882a593Smuzhiyun scroll = 8;
527*4882a593Smuzhiyun break;
528*4882a593Smuzhiyun case ATKBD_SCR_CLICK:
529*4882a593Smuzhiyun click = !atkbd->release;
530*4882a593Smuzhiyun break;
531*4882a593Smuzhiyun case ATKBD_SCR_LEFT:
532*4882a593Smuzhiyun hscroll = -1;
533*4882a593Smuzhiyun break;
534*4882a593Smuzhiyun case ATKBD_SCR_RIGHT:
535*4882a593Smuzhiyun hscroll = 1;
536*4882a593Smuzhiyun break;
537*4882a593Smuzhiyun default:
538*4882a593Smuzhiyun if (atkbd->release) {
539*4882a593Smuzhiyun value = 0;
540*4882a593Smuzhiyun atkbd->last = 0;
541*4882a593Smuzhiyun } else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) {
542*4882a593Smuzhiyun /* Workaround Toshiba laptop multiple keypress */
543*4882a593Smuzhiyun value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2;
544*4882a593Smuzhiyun } else {
545*4882a593Smuzhiyun value = 1;
546*4882a593Smuzhiyun atkbd->last = code;
547*4882a593Smuzhiyun atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun input_event(dev, EV_KEY, keycode, value);
551*4882a593Smuzhiyun input_sync(dev);
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun if (value && test_bit(code, atkbd->force_release_mask)) {
554*4882a593Smuzhiyun input_event(dev, EV_MSC, MSC_SCAN, code);
555*4882a593Smuzhiyun input_report_key(dev, keycode, 0);
556*4882a593Smuzhiyun input_sync(dev);
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun if (atkbd->scroll) {
561*4882a593Smuzhiyun if (click != -1)
562*4882a593Smuzhiyun input_report_key(dev, BTN_MIDDLE, click);
563*4882a593Smuzhiyun input_report_rel(dev, REL_WHEEL,
564*4882a593Smuzhiyun atkbd->release ? -scroll : scroll);
565*4882a593Smuzhiyun input_report_rel(dev, REL_HWHEEL, hscroll);
566*4882a593Smuzhiyun input_sync(dev);
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun atkbd->release = false;
570*4882a593Smuzhiyun out:
571*4882a593Smuzhiyun return IRQ_HANDLED;
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun
atkbd_set_repeat_rate(struct atkbd * atkbd)574*4882a593Smuzhiyun static int atkbd_set_repeat_rate(struct atkbd *atkbd)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun const short period[32] =
577*4882a593Smuzhiyun { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
578*4882a593Smuzhiyun 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
579*4882a593Smuzhiyun const short delay[4] =
580*4882a593Smuzhiyun { 250, 500, 750, 1000 };
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun struct input_dev *dev = atkbd->dev;
583*4882a593Smuzhiyun unsigned char param;
584*4882a593Smuzhiyun int i = 0, j = 0;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD])
587*4882a593Smuzhiyun i++;
588*4882a593Smuzhiyun dev->rep[REP_PERIOD] = period[i];
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun while (j < ARRAY_SIZE(delay) - 1 && delay[j] < dev->rep[REP_DELAY])
591*4882a593Smuzhiyun j++;
592*4882a593Smuzhiyun dev->rep[REP_DELAY] = delay[j];
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun param = i | (j << 5);
595*4882a593Smuzhiyun return ps2_command(&atkbd->ps2dev, ¶m, ATKBD_CMD_SETREP);
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
atkbd_set_leds(struct atkbd * atkbd)598*4882a593Smuzhiyun static int atkbd_set_leds(struct atkbd *atkbd)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun struct input_dev *dev = atkbd->dev;
601*4882a593Smuzhiyun unsigned char param[2];
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
604*4882a593Smuzhiyun | (test_bit(LED_NUML, dev->led) ? 2 : 0)
605*4882a593Smuzhiyun | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
606*4882a593Smuzhiyun if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
607*4882a593Smuzhiyun return -1;
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun if (atkbd->extra) {
610*4882a593Smuzhiyun param[0] = 0;
611*4882a593Smuzhiyun param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
612*4882a593Smuzhiyun | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
613*4882a593Smuzhiyun | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
614*4882a593Smuzhiyun | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
615*4882a593Smuzhiyun | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
616*4882a593Smuzhiyun if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS))
617*4882a593Smuzhiyun return -1;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun return 0;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun /*
624*4882a593Smuzhiyun * atkbd_event_work() is used to complete processing of events that
625*4882a593Smuzhiyun * can not be processed by input_event() which is often called from
626*4882a593Smuzhiyun * interrupt context.
627*4882a593Smuzhiyun */
628*4882a593Smuzhiyun
atkbd_event_work(struct work_struct * work)629*4882a593Smuzhiyun static void atkbd_event_work(struct work_struct *work)
630*4882a593Smuzhiyun {
631*4882a593Smuzhiyun struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun mutex_lock(&atkbd->mutex);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun if (!atkbd->enabled) {
636*4882a593Smuzhiyun /*
637*4882a593Smuzhiyun * Serio ports are resumed asynchronously so while driver core
638*4882a593Smuzhiyun * thinks that device is already fully operational in reality
639*4882a593Smuzhiyun * it may not be ready yet. In this case we need to keep
640*4882a593Smuzhiyun * rescheduling till reconnect completes.
641*4882a593Smuzhiyun */
642*4882a593Smuzhiyun schedule_delayed_work(&atkbd->event_work,
643*4882a593Smuzhiyun msecs_to_jiffies(100));
644*4882a593Smuzhiyun } else {
645*4882a593Smuzhiyun if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
646*4882a593Smuzhiyun atkbd_set_leds(atkbd);
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
649*4882a593Smuzhiyun atkbd_set_repeat_rate(atkbd);
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun mutex_unlock(&atkbd->mutex);
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun /*
656*4882a593Smuzhiyun * Schedule switch for execution. We need to throttle requests,
657*4882a593Smuzhiyun * otherwise keyboard may become unresponsive.
658*4882a593Smuzhiyun */
atkbd_schedule_event_work(struct atkbd * atkbd,int event_bit)659*4882a593Smuzhiyun static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun unsigned long delay = msecs_to_jiffies(50);
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun if (time_after(jiffies, atkbd->event_jiffies + delay))
664*4882a593Smuzhiyun delay = 0;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun atkbd->event_jiffies = jiffies;
667*4882a593Smuzhiyun set_bit(event_bit, &atkbd->event_mask);
668*4882a593Smuzhiyun mb();
669*4882a593Smuzhiyun schedule_delayed_work(&atkbd->event_work, delay);
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun /*
673*4882a593Smuzhiyun * Event callback from the input module. Events that change the state of
674*4882a593Smuzhiyun * the hardware are processed here. If action can not be performed in
675*4882a593Smuzhiyun * interrupt context it is offloaded to atkbd_event_work.
676*4882a593Smuzhiyun */
677*4882a593Smuzhiyun
atkbd_event(struct input_dev * dev,unsigned int type,unsigned int code,int value)678*4882a593Smuzhiyun static int atkbd_event(struct input_dev *dev,
679*4882a593Smuzhiyun unsigned int type, unsigned int code, int value)
680*4882a593Smuzhiyun {
681*4882a593Smuzhiyun struct atkbd *atkbd = input_get_drvdata(dev);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun if (!atkbd->write)
684*4882a593Smuzhiyun return -1;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun switch (type) {
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun case EV_LED:
689*4882a593Smuzhiyun atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
690*4882a593Smuzhiyun return 0;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun case EV_REP:
693*4882a593Smuzhiyun if (!atkbd->softrepeat)
694*4882a593Smuzhiyun atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);
695*4882a593Smuzhiyun return 0;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun default:
698*4882a593Smuzhiyun return -1;
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun /*
703*4882a593Smuzhiyun * atkbd_enable() signals that interrupt handler is allowed to
704*4882a593Smuzhiyun * generate input events.
705*4882a593Smuzhiyun */
706*4882a593Smuzhiyun
atkbd_enable(struct atkbd * atkbd)707*4882a593Smuzhiyun static inline void atkbd_enable(struct atkbd *atkbd)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun serio_pause_rx(atkbd->ps2dev.serio);
710*4882a593Smuzhiyun atkbd->enabled = true;
711*4882a593Smuzhiyun serio_continue_rx(atkbd->ps2dev.serio);
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun /*
715*4882a593Smuzhiyun * atkbd_disable() tells input handler that all incoming data except
716*4882a593Smuzhiyun * for ACKs and command response should be dropped.
717*4882a593Smuzhiyun */
718*4882a593Smuzhiyun
atkbd_disable(struct atkbd * atkbd)719*4882a593Smuzhiyun static inline void atkbd_disable(struct atkbd *atkbd)
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun serio_pause_rx(atkbd->ps2dev.serio);
722*4882a593Smuzhiyun atkbd->enabled = false;
723*4882a593Smuzhiyun serio_continue_rx(atkbd->ps2dev.serio);
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun
atkbd_activate(struct atkbd * atkbd)726*4882a593Smuzhiyun static int atkbd_activate(struct atkbd *atkbd)
727*4882a593Smuzhiyun {
728*4882a593Smuzhiyun struct ps2dev *ps2dev = &atkbd->ps2dev;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun /*
731*4882a593Smuzhiyun * Enable the keyboard to receive keystrokes.
732*4882a593Smuzhiyun */
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
735*4882a593Smuzhiyun dev_err(&ps2dev->serio->dev,
736*4882a593Smuzhiyun "Failed to enable keyboard on %s\n",
737*4882a593Smuzhiyun ps2dev->serio->phys);
738*4882a593Smuzhiyun return -1;
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun return 0;
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun /*
745*4882a593Smuzhiyun * atkbd_deactivate() resets and disables the keyboard from sending
746*4882a593Smuzhiyun * keystrokes.
747*4882a593Smuzhiyun */
748*4882a593Smuzhiyun
atkbd_deactivate(struct atkbd * atkbd)749*4882a593Smuzhiyun static void atkbd_deactivate(struct atkbd *atkbd)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun struct ps2dev *ps2dev = &atkbd->ps2dev;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_DIS))
754*4882a593Smuzhiyun dev_err(&ps2dev->serio->dev,
755*4882a593Smuzhiyun "Failed to deactivate keyboard on %s\n",
756*4882a593Smuzhiyun ps2dev->serio->phys);
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun /*
760*4882a593Smuzhiyun * atkbd_probe() probes for an AT keyboard on a serio port.
761*4882a593Smuzhiyun */
762*4882a593Smuzhiyun
atkbd_probe(struct atkbd * atkbd)763*4882a593Smuzhiyun static int atkbd_probe(struct atkbd *atkbd)
764*4882a593Smuzhiyun {
765*4882a593Smuzhiyun struct ps2dev *ps2dev = &atkbd->ps2dev;
766*4882a593Smuzhiyun unsigned char param[2];
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun /*
769*4882a593Smuzhiyun * Some systems, where the bit-twiddling when testing the io-lines of the
770*4882a593Smuzhiyun * controller may confuse the keyboard need a full reset of the keyboard. On
771*4882a593Smuzhiyun * these systems the BIOS also usually doesn't do it for us.
772*4882a593Smuzhiyun */
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun if (atkbd_reset)
775*4882a593Smuzhiyun if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT))
776*4882a593Smuzhiyun dev_warn(&ps2dev->serio->dev,
777*4882a593Smuzhiyun "keyboard reset failed on %s\n",
778*4882a593Smuzhiyun ps2dev->serio->phys);
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun /*
781*4882a593Smuzhiyun * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
782*4882a593Smuzhiyun * Some keyboards report different values, but the first byte is always 0xab or
783*4882a593Smuzhiyun * 0xac. Some old AT keyboards don't report anything. If a mouse is connected, this
784*4882a593Smuzhiyun * should make sure we don't try to set the LEDs on it.
785*4882a593Smuzhiyun */
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun param[0] = param[1] = 0xa5; /* initialize with invalid values */
788*4882a593Smuzhiyun if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun /*
791*4882a593Smuzhiyun * If the get ID command failed, we check if we can at least set the LEDs on
792*4882a593Smuzhiyun * the keyboard. This should work on every keyboard out there. It also turns
793*4882a593Smuzhiyun * the LEDs off, which we want anyway.
794*4882a593Smuzhiyun */
795*4882a593Smuzhiyun param[0] = 0;
796*4882a593Smuzhiyun if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
797*4882a593Smuzhiyun return -1;
798*4882a593Smuzhiyun atkbd->id = 0xabba;
799*4882a593Smuzhiyun return 0;
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun if (!ps2_is_keyboard_id(param[0]))
803*4882a593Smuzhiyun return -1;
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun atkbd->id = (param[0] << 8) | param[1];
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun if (atkbd->id == 0xaca1 && atkbd->translated) {
808*4882a593Smuzhiyun dev_err(&ps2dev->serio->dev,
809*4882a593Smuzhiyun "NCD terminal keyboards are only supported on non-translating controllers. "
810*4882a593Smuzhiyun "Use i8042.direct=1 to disable translation.\n");
811*4882a593Smuzhiyun return -1;
812*4882a593Smuzhiyun }
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun /*
815*4882a593Smuzhiyun * Make sure nothing is coming from the keyboard and disturbs our
816*4882a593Smuzhiyun * internal state.
817*4882a593Smuzhiyun */
818*4882a593Smuzhiyun if (!atkbd_skip_deactivate)
819*4882a593Smuzhiyun atkbd_deactivate(atkbd);
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun return 0;
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun /*
825*4882a593Smuzhiyun * atkbd_select_set checks if a keyboard has a working Set 3 support, and
826*4882a593Smuzhiyun * sets it into that. Unfortunately there are keyboards that can be switched
827*4882a593Smuzhiyun * to Set 3, but don't work well in that (BTC Multimedia ...)
828*4882a593Smuzhiyun */
829*4882a593Smuzhiyun
atkbd_select_set(struct atkbd * atkbd,int target_set,int allow_extra)830*4882a593Smuzhiyun static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra)
831*4882a593Smuzhiyun {
832*4882a593Smuzhiyun struct ps2dev *ps2dev = &atkbd->ps2dev;
833*4882a593Smuzhiyun unsigned char param[2];
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun atkbd->extra = false;
836*4882a593Smuzhiyun /*
837*4882a593Smuzhiyun * For known special keyboards we can go ahead and set the correct set.
838*4882a593Smuzhiyun * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and
839*4882a593Smuzhiyun * IBM RapidAccess / IBM EzButton / Chicony KBP-8993 keyboards.
840*4882a593Smuzhiyun */
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun if (atkbd->translated)
843*4882a593Smuzhiyun return 2;
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun if (atkbd->id == 0xaca1) {
846*4882a593Smuzhiyun param[0] = 3;
847*4882a593Smuzhiyun ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET);
848*4882a593Smuzhiyun return 3;
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun if (allow_extra) {
852*4882a593Smuzhiyun param[0] = 0x71;
853*4882a593Smuzhiyun if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) {
854*4882a593Smuzhiyun atkbd->extra = true;
855*4882a593Smuzhiyun return 2;
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun if (atkbd_terminal) {
860*4882a593Smuzhiyun ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MB);
861*4882a593Smuzhiyun return 3;
862*4882a593Smuzhiyun }
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun if (target_set != 3)
865*4882a593Smuzhiyun return 2;
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun if (!ps2_command(ps2dev, param, ATKBD_CMD_OK_GETID)) {
868*4882a593Smuzhiyun atkbd->id = param[0] << 8 | param[1];
869*4882a593Smuzhiyun return 2;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun param[0] = 3;
873*4882a593Smuzhiyun if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))
874*4882a593Smuzhiyun return 2;
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun param[0] = 0;
877*4882a593Smuzhiyun if (ps2_command(ps2dev, param, ATKBD_CMD_GSCANSET))
878*4882a593Smuzhiyun return 2;
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun if (param[0] != 3) {
881*4882a593Smuzhiyun param[0] = 2;
882*4882a593Smuzhiyun if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))
883*4882a593Smuzhiyun return 2;
884*4882a593Smuzhiyun }
885*4882a593Smuzhiyun
886*4882a593Smuzhiyun ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MBR);
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun return 3;
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun
atkbd_reset_state(struct atkbd * atkbd)891*4882a593Smuzhiyun static int atkbd_reset_state(struct atkbd *atkbd)
892*4882a593Smuzhiyun {
893*4882a593Smuzhiyun struct ps2dev *ps2dev = &atkbd->ps2dev;
894*4882a593Smuzhiyun unsigned char param[1];
895*4882a593Smuzhiyun
896*4882a593Smuzhiyun /*
897*4882a593Smuzhiyun * Set the LEDs to a predefined state (all off).
898*4882a593Smuzhiyun */
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun param[0] = 0;
901*4882a593Smuzhiyun if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
902*4882a593Smuzhiyun return -1;
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun /*
905*4882a593Smuzhiyun * Set autorepeat to fastest possible.
906*4882a593Smuzhiyun */
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun param[0] = 0;
909*4882a593Smuzhiyun if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
910*4882a593Smuzhiyun return -1;
911*4882a593Smuzhiyun
912*4882a593Smuzhiyun return 0;
913*4882a593Smuzhiyun }
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun /*
916*4882a593Smuzhiyun * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
917*4882a593Smuzhiyun * reboot.
918*4882a593Smuzhiyun */
919*4882a593Smuzhiyun
atkbd_cleanup(struct serio * serio)920*4882a593Smuzhiyun static void atkbd_cleanup(struct serio *serio)
921*4882a593Smuzhiyun {
922*4882a593Smuzhiyun struct atkbd *atkbd = serio_get_drvdata(serio);
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun atkbd_disable(atkbd);
925*4882a593Smuzhiyun ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF);
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun /*
930*4882a593Smuzhiyun * atkbd_disconnect() closes and frees.
931*4882a593Smuzhiyun */
932*4882a593Smuzhiyun
atkbd_disconnect(struct serio * serio)933*4882a593Smuzhiyun static void atkbd_disconnect(struct serio *serio)
934*4882a593Smuzhiyun {
935*4882a593Smuzhiyun struct atkbd *atkbd = serio_get_drvdata(serio);
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun atkbd_disable(atkbd);
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun input_unregister_device(atkbd->dev);
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun /*
944*4882a593Smuzhiyun * Make sure we don't have a command in flight.
945*4882a593Smuzhiyun * Note that since atkbd->enabled is false event work will keep
946*4882a593Smuzhiyun * rescheduling itself until it gets canceled and will not try
947*4882a593Smuzhiyun * accessing freed input device or serio port.
948*4882a593Smuzhiyun */
949*4882a593Smuzhiyun cancel_delayed_work_sync(&atkbd->event_work);
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun serio_close(serio);
952*4882a593Smuzhiyun serio_set_drvdata(serio, NULL);
953*4882a593Smuzhiyun kfree(atkbd);
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun
956*4882a593Smuzhiyun /*
957*4882a593Smuzhiyun * generate release events for the keycodes given in data
958*4882a593Smuzhiyun */
atkbd_apply_forced_release_keylist(struct atkbd * atkbd,const void * data)959*4882a593Smuzhiyun static void atkbd_apply_forced_release_keylist(struct atkbd* atkbd,
960*4882a593Smuzhiyun const void *data)
961*4882a593Smuzhiyun {
962*4882a593Smuzhiyun const unsigned int *keys = data;
963*4882a593Smuzhiyun unsigned int i;
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun if (atkbd->set == 2)
966*4882a593Smuzhiyun for (i = 0; keys[i] != -1U; i++)
967*4882a593Smuzhiyun __set_bit(keys[i], atkbd->force_release_mask);
968*4882a593Smuzhiyun }
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun /*
971*4882a593Smuzhiyun * Most special keys (Fn+F?) on Dell laptops do not generate release
972*4882a593Smuzhiyun * events so we have to do it ourselves.
973*4882a593Smuzhiyun */
974*4882a593Smuzhiyun static unsigned int atkbd_dell_laptop_forced_release_keys[] = {
975*4882a593Smuzhiyun 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, -1U
976*4882a593Smuzhiyun };
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun /*
979*4882a593Smuzhiyun * Perform fixup for HP system that doesn't generate release
980*4882a593Smuzhiyun * for its video switch
981*4882a593Smuzhiyun */
982*4882a593Smuzhiyun static unsigned int atkbd_hp_forced_release_keys[] = {
983*4882a593Smuzhiyun 0x94, -1U
984*4882a593Smuzhiyun };
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun /*
987*4882a593Smuzhiyun * Samsung NC10,NC20 with Fn+F? key release not working
988*4882a593Smuzhiyun */
989*4882a593Smuzhiyun static unsigned int atkbd_samsung_forced_release_keys[] = {
990*4882a593Smuzhiyun 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U
991*4882a593Smuzhiyun };
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun /*
994*4882a593Smuzhiyun * Amilo Pi 3525 key release for Fn+Volume keys not working
995*4882a593Smuzhiyun */
996*4882a593Smuzhiyun static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = {
997*4882a593Smuzhiyun 0x20, 0xa0, 0x2e, 0xae, 0x30, 0xb0, -1U
998*4882a593Smuzhiyun };
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun /*
1001*4882a593Smuzhiyun * Amilo Xi 3650 key release for light touch bar not working
1002*4882a593Smuzhiyun */
1003*4882a593Smuzhiyun static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = {
1004*4882a593Smuzhiyun 0x67, 0xed, 0x90, 0xa2, 0x99, 0xa4, 0xae, 0xb0, -1U
1005*4882a593Smuzhiyun };
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun /*
1008*4882a593Smuzhiyun * Soltech TA12 system with broken key release on volume keys and mute key
1009*4882a593Smuzhiyun */
1010*4882a593Smuzhiyun static unsigned int atkdb_soltech_ta12_forced_release_keys[] = {
1011*4882a593Smuzhiyun 0xa0, 0xae, 0xb0, -1U
1012*4882a593Smuzhiyun };
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun /*
1015*4882a593Smuzhiyun * Many notebooks don't send key release event for volume up/down
1016*4882a593Smuzhiyun * keys, with key list below common among them
1017*4882a593Smuzhiyun */
1018*4882a593Smuzhiyun static unsigned int atkbd_volume_forced_release_keys[] = {
1019*4882a593Smuzhiyun 0xae, 0xb0, -1U
1020*4882a593Smuzhiyun };
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun /*
1023*4882a593Smuzhiyun * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas
1024*4882a593Smuzhiyun * they should be generating e4-e6 (0x80 | code).
1025*4882a593Smuzhiyun */
atkbd_oqo_01plus_scancode_fixup(struct atkbd * atkbd,unsigned int code)1026*4882a593Smuzhiyun static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd,
1027*4882a593Smuzhiyun unsigned int code)
1028*4882a593Smuzhiyun {
1029*4882a593Smuzhiyun if (atkbd->translated && atkbd->emul == 1 &&
1030*4882a593Smuzhiyun (code == 0x64 || code == 0x65 || code == 0x66)) {
1031*4882a593Smuzhiyun atkbd->emul = 0;
1032*4882a593Smuzhiyun code |= 0x80;
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun return code;
1036*4882a593Smuzhiyun }
1037*4882a593Smuzhiyun
atkbd_get_keymap_from_fwnode(struct atkbd * atkbd)1038*4882a593Smuzhiyun static int atkbd_get_keymap_from_fwnode(struct atkbd *atkbd)
1039*4882a593Smuzhiyun {
1040*4882a593Smuzhiyun struct device *dev = &atkbd->ps2dev.serio->dev;
1041*4882a593Smuzhiyun int i, n;
1042*4882a593Smuzhiyun u32 *ptr;
1043*4882a593Smuzhiyun u16 scancode, keycode;
1044*4882a593Smuzhiyun
1045*4882a593Smuzhiyun /* Parse "linux,keymap" property */
1046*4882a593Smuzhiyun n = device_property_count_u32(dev, "linux,keymap");
1047*4882a593Smuzhiyun if (n <= 0 || n > ATKBD_KEYMAP_SIZE)
1048*4882a593Smuzhiyun return -ENXIO;
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun ptr = kcalloc(n, sizeof(u32), GFP_KERNEL);
1051*4882a593Smuzhiyun if (!ptr)
1052*4882a593Smuzhiyun return -ENOMEM;
1053*4882a593Smuzhiyun
1054*4882a593Smuzhiyun if (device_property_read_u32_array(dev, "linux,keymap", ptr, n)) {
1055*4882a593Smuzhiyun dev_err(dev, "problem parsing FW keymap property\n");
1056*4882a593Smuzhiyun kfree(ptr);
1057*4882a593Smuzhiyun return -EINVAL;
1058*4882a593Smuzhiyun }
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
1061*4882a593Smuzhiyun for (i = 0; i < n; i++) {
1062*4882a593Smuzhiyun scancode = SCANCODE(ptr[i]);
1063*4882a593Smuzhiyun keycode = KEYCODE(ptr[i]);
1064*4882a593Smuzhiyun atkbd->keycode[scancode] = keycode;
1065*4882a593Smuzhiyun }
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun kfree(ptr);
1068*4882a593Smuzhiyun return 0;
1069*4882a593Smuzhiyun }
1070*4882a593Smuzhiyun
1071*4882a593Smuzhiyun /*
1072*4882a593Smuzhiyun * atkbd_set_keycode_table() initializes keyboard's keycode table
1073*4882a593Smuzhiyun * according to the selected scancode set
1074*4882a593Smuzhiyun */
1075*4882a593Smuzhiyun
atkbd_set_keycode_table(struct atkbd * atkbd)1076*4882a593Smuzhiyun static void atkbd_set_keycode_table(struct atkbd *atkbd)
1077*4882a593Smuzhiyun {
1078*4882a593Smuzhiyun struct device *dev = &atkbd->ps2dev.serio->dev;
1079*4882a593Smuzhiyun unsigned int scancode;
1080*4882a593Smuzhiyun int i, j;
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
1083*4882a593Smuzhiyun bitmap_zero(atkbd->force_release_mask, ATKBD_KEYMAP_SIZE);
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun if (!atkbd_get_keymap_from_fwnode(atkbd)) {
1086*4882a593Smuzhiyun dev_dbg(dev, "Using FW keymap\n");
1087*4882a593Smuzhiyun } else if (atkbd->translated) {
1088*4882a593Smuzhiyun for (i = 0; i < 128; i++) {
1089*4882a593Smuzhiyun scancode = atkbd_unxlate_table[i];
1090*4882a593Smuzhiyun atkbd->keycode[i] = atkbd_set2_keycode[scancode];
1091*4882a593Smuzhiyun atkbd->keycode[i | 0x80] = atkbd_set2_keycode[scancode | 0x80];
1092*4882a593Smuzhiyun if (atkbd->scroll)
1093*4882a593Smuzhiyun for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++)
1094*4882a593Smuzhiyun if ((scancode | 0x80) == atkbd_scroll_keys[j].set2)
1095*4882a593Smuzhiyun atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
1096*4882a593Smuzhiyun }
1097*4882a593Smuzhiyun } else if (atkbd->set == 3) {
1098*4882a593Smuzhiyun memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
1099*4882a593Smuzhiyun } else {
1100*4882a593Smuzhiyun memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun if (atkbd->scroll)
1103*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++) {
1104*4882a593Smuzhiyun scancode = atkbd_scroll_keys[i].set2;
1105*4882a593Smuzhiyun atkbd->keycode[scancode] = atkbd_scroll_keys[i].keycode;
1106*4882a593Smuzhiyun }
1107*4882a593Smuzhiyun }
1108*4882a593Smuzhiyun
1109*4882a593Smuzhiyun /*
1110*4882a593Smuzhiyun * HANGEUL and HANJA keys do not send release events so we need to
1111*4882a593Smuzhiyun * generate such events ourselves
1112*4882a593Smuzhiyun */
1113*4882a593Smuzhiyun scancode = atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL);
1114*4882a593Smuzhiyun atkbd->keycode[scancode] = KEY_HANGEUL;
1115*4882a593Smuzhiyun __set_bit(scancode, atkbd->force_release_mask);
1116*4882a593Smuzhiyun
1117*4882a593Smuzhiyun scancode = atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA);
1118*4882a593Smuzhiyun atkbd->keycode[scancode] = KEY_HANJA;
1119*4882a593Smuzhiyun __set_bit(scancode, atkbd->force_release_mask);
1120*4882a593Smuzhiyun
1121*4882a593Smuzhiyun /*
1122*4882a593Smuzhiyun * Perform additional fixups
1123*4882a593Smuzhiyun */
1124*4882a593Smuzhiyun if (atkbd_platform_fixup)
1125*4882a593Smuzhiyun atkbd_platform_fixup(atkbd, atkbd_platform_fixup_data);
1126*4882a593Smuzhiyun }
1127*4882a593Smuzhiyun
1128*4882a593Smuzhiyun /*
1129*4882a593Smuzhiyun * atkbd_set_device_attrs() sets up keyboard's input device structure
1130*4882a593Smuzhiyun */
1131*4882a593Smuzhiyun
atkbd_set_device_attrs(struct atkbd * atkbd)1132*4882a593Smuzhiyun static void atkbd_set_device_attrs(struct atkbd *atkbd)
1133*4882a593Smuzhiyun {
1134*4882a593Smuzhiyun struct input_dev *input_dev = atkbd->dev;
1135*4882a593Smuzhiyun int i;
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun if (atkbd->extra)
1138*4882a593Smuzhiyun snprintf(atkbd->name, sizeof(atkbd->name),
1139*4882a593Smuzhiyun "AT Set 2 Extra keyboard");
1140*4882a593Smuzhiyun else
1141*4882a593Smuzhiyun snprintf(atkbd->name, sizeof(atkbd->name),
1142*4882a593Smuzhiyun "AT %s Set %d keyboard",
1143*4882a593Smuzhiyun atkbd->translated ? "Translated" : "Raw", atkbd->set);
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyun snprintf(atkbd->phys, sizeof(atkbd->phys),
1146*4882a593Smuzhiyun "%s/input0", atkbd->ps2dev.serio->phys);
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun input_dev->name = atkbd->name;
1149*4882a593Smuzhiyun input_dev->phys = atkbd->phys;
1150*4882a593Smuzhiyun input_dev->id.bustype = BUS_I8042;
1151*4882a593Smuzhiyun input_dev->id.vendor = 0x0001;
1152*4882a593Smuzhiyun input_dev->id.product = atkbd->translated ? 1 : atkbd->set;
1153*4882a593Smuzhiyun input_dev->id.version = atkbd->id;
1154*4882a593Smuzhiyun input_dev->event = atkbd_event;
1155*4882a593Smuzhiyun input_dev->dev.parent = &atkbd->ps2dev.serio->dev;
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun input_set_drvdata(input_dev, atkbd);
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
1160*4882a593Smuzhiyun BIT_MASK(EV_MSC);
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun if (atkbd->write) {
1163*4882a593Smuzhiyun input_dev->evbit[0] |= BIT_MASK(EV_LED);
1164*4882a593Smuzhiyun input_dev->ledbit[0] = BIT_MASK(LED_NUML) |
1165*4882a593Smuzhiyun BIT_MASK(LED_CAPSL) | BIT_MASK(LED_SCROLLL);
1166*4882a593Smuzhiyun }
1167*4882a593Smuzhiyun
1168*4882a593Smuzhiyun if (atkbd->extra)
1169*4882a593Smuzhiyun input_dev->ledbit[0] |= BIT_MASK(LED_COMPOSE) |
1170*4882a593Smuzhiyun BIT_MASK(LED_SUSPEND) | BIT_MASK(LED_SLEEP) |
1171*4882a593Smuzhiyun BIT_MASK(LED_MUTE) | BIT_MASK(LED_MISC);
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun if (!atkbd->softrepeat) {
1174*4882a593Smuzhiyun input_dev->rep[REP_DELAY] = 250;
1175*4882a593Smuzhiyun input_dev->rep[REP_PERIOD] = 33;
1176*4882a593Smuzhiyun }
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun input_dev->mscbit[0] = atkbd->softraw ? BIT_MASK(MSC_SCAN) :
1179*4882a593Smuzhiyun BIT_MASK(MSC_RAW) | BIT_MASK(MSC_SCAN);
1180*4882a593Smuzhiyun
1181*4882a593Smuzhiyun if (atkbd->scroll) {
1182*4882a593Smuzhiyun input_dev->evbit[0] |= BIT_MASK(EV_REL);
1183*4882a593Smuzhiyun input_dev->relbit[0] = BIT_MASK(REL_WHEEL) |
1184*4882a593Smuzhiyun BIT_MASK(REL_HWHEEL);
1185*4882a593Smuzhiyun __set_bit(BTN_MIDDLE, input_dev->keybit);
1186*4882a593Smuzhiyun }
1187*4882a593Smuzhiyun
1188*4882a593Smuzhiyun input_dev->keycode = atkbd->keycode;
1189*4882a593Smuzhiyun input_dev->keycodesize = sizeof(unsigned short);
1190*4882a593Smuzhiyun input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
1191*4882a593Smuzhiyun
1192*4882a593Smuzhiyun for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) {
1193*4882a593Smuzhiyun if (atkbd->keycode[i] != KEY_RESERVED &&
1194*4882a593Smuzhiyun atkbd->keycode[i] != ATKBD_KEY_NULL &&
1195*4882a593Smuzhiyun atkbd->keycode[i] < ATKBD_SPECIAL) {
1196*4882a593Smuzhiyun __set_bit(atkbd->keycode[i], input_dev->keybit);
1197*4882a593Smuzhiyun }
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun }
1200*4882a593Smuzhiyun
atkbd_parse_fwnode_data(struct serio * serio)1201*4882a593Smuzhiyun static void atkbd_parse_fwnode_data(struct serio *serio)
1202*4882a593Smuzhiyun {
1203*4882a593Smuzhiyun struct atkbd *atkbd = serio_get_drvdata(serio);
1204*4882a593Smuzhiyun struct device *dev = &serio->dev;
1205*4882a593Smuzhiyun int n;
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun /* Parse "function-row-physmap" property */
1208*4882a593Smuzhiyun n = device_property_count_u32(dev, "function-row-physmap");
1209*4882a593Smuzhiyun if (n > 0 && n <= MAX_FUNCTION_ROW_KEYS &&
1210*4882a593Smuzhiyun !device_property_read_u32_array(dev, "function-row-physmap",
1211*4882a593Smuzhiyun atkbd->function_row_physmap, n)) {
1212*4882a593Smuzhiyun atkbd->num_function_row_keys = n;
1213*4882a593Smuzhiyun dev_dbg(dev, "FW reported %d function-row key locations\n", n);
1214*4882a593Smuzhiyun }
1215*4882a593Smuzhiyun }
1216*4882a593Smuzhiyun
1217*4882a593Smuzhiyun /*
1218*4882a593Smuzhiyun * atkbd_connect() is called when the serio module finds an interface
1219*4882a593Smuzhiyun * that isn't handled yet by an appropriate device driver. We check if
1220*4882a593Smuzhiyun * there is an AT keyboard out there and if yes, we register ourselves
1221*4882a593Smuzhiyun * to the input module.
1222*4882a593Smuzhiyun */
1223*4882a593Smuzhiyun
atkbd_connect(struct serio * serio,struct serio_driver * drv)1224*4882a593Smuzhiyun static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
1225*4882a593Smuzhiyun {
1226*4882a593Smuzhiyun struct atkbd *atkbd;
1227*4882a593Smuzhiyun struct input_dev *dev;
1228*4882a593Smuzhiyun int err = -ENOMEM;
1229*4882a593Smuzhiyun
1230*4882a593Smuzhiyun atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
1231*4882a593Smuzhiyun dev = input_allocate_device();
1232*4882a593Smuzhiyun if (!atkbd || !dev)
1233*4882a593Smuzhiyun goto fail1;
1234*4882a593Smuzhiyun
1235*4882a593Smuzhiyun atkbd->dev = dev;
1236*4882a593Smuzhiyun ps2_init(&atkbd->ps2dev, serio);
1237*4882a593Smuzhiyun INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
1238*4882a593Smuzhiyun mutex_init(&atkbd->mutex);
1239*4882a593Smuzhiyun
1240*4882a593Smuzhiyun switch (serio->id.type) {
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun case SERIO_8042_XL:
1243*4882a593Smuzhiyun atkbd->translated = true;
1244*4882a593Smuzhiyun fallthrough;
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun case SERIO_8042:
1247*4882a593Smuzhiyun if (serio->write)
1248*4882a593Smuzhiyun atkbd->write = true;
1249*4882a593Smuzhiyun break;
1250*4882a593Smuzhiyun }
1251*4882a593Smuzhiyun
1252*4882a593Smuzhiyun atkbd->softraw = atkbd_softraw;
1253*4882a593Smuzhiyun atkbd->softrepeat = atkbd_softrepeat;
1254*4882a593Smuzhiyun atkbd->scroll = atkbd_scroll;
1255*4882a593Smuzhiyun
1256*4882a593Smuzhiyun if (atkbd->softrepeat)
1257*4882a593Smuzhiyun atkbd->softraw = true;
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun serio_set_drvdata(serio, atkbd);
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun err = serio_open(serio, drv);
1262*4882a593Smuzhiyun if (err)
1263*4882a593Smuzhiyun goto fail2;
1264*4882a593Smuzhiyun
1265*4882a593Smuzhiyun if (atkbd->write) {
1266*4882a593Smuzhiyun
1267*4882a593Smuzhiyun if (atkbd_probe(atkbd)) {
1268*4882a593Smuzhiyun err = -ENODEV;
1269*4882a593Smuzhiyun goto fail3;
1270*4882a593Smuzhiyun }
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
1273*4882a593Smuzhiyun atkbd_reset_state(atkbd);
1274*4882a593Smuzhiyun
1275*4882a593Smuzhiyun } else {
1276*4882a593Smuzhiyun atkbd->set = 2;
1277*4882a593Smuzhiyun atkbd->id = 0xab00;
1278*4882a593Smuzhiyun }
1279*4882a593Smuzhiyun
1280*4882a593Smuzhiyun atkbd_parse_fwnode_data(serio);
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun atkbd_set_keycode_table(atkbd);
1283*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1284*4882a593Smuzhiyun
1285*4882a593Smuzhiyun err = sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
1286*4882a593Smuzhiyun if (err)
1287*4882a593Smuzhiyun goto fail3;
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun atkbd_enable(atkbd);
1290*4882a593Smuzhiyun if (serio->write)
1291*4882a593Smuzhiyun atkbd_activate(atkbd);
1292*4882a593Smuzhiyun
1293*4882a593Smuzhiyun err = input_register_device(atkbd->dev);
1294*4882a593Smuzhiyun if (err)
1295*4882a593Smuzhiyun goto fail4;
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun return 0;
1298*4882a593Smuzhiyun
1299*4882a593Smuzhiyun fail4: sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
1300*4882a593Smuzhiyun fail3: serio_close(serio);
1301*4882a593Smuzhiyun fail2: serio_set_drvdata(serio, NULL);
1302*4882a593Smuzhiyun fail1: input_free_device(dev);
1303*4882a593Smuzhiyun kfree(atkbd);
1304*4882a593Smuzhiyun return err;
1305*4882a593Smuzhiyun }
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun /*
1308*4882a593Smuzhiyun * atkbd_reconnect() tries to restore keyboard into a sane state and is
1309*4882a593Smuzhiyun * most likely called on resume.
1310*4882a593Smuzhiyun */
1311*4882a593Smuzhiyun
atkbd_reconnect(struct serio * serio)1312*4882a593Smuzhiyun static int atkbd_reconnect(struct serio *serio)
1313*4882a593Smuzhiyun {
1314*4882a593Smuzhiyun struct atkbd *atkbd = serio_get_drvdata(serio);
1315*4882a593Smuzhiyun struct serio_driver *drv = serio->drv;
1316*4882a593Smuzhiyun int retval = -1;
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun if (!atkbd || !drv) {
1319*4882a593Smuzhiyun dev_dbg(&serio->dev,
1320*4882a593Smuzhiyun "reconnect request, but serio is disconnected, ignoring...\n");
1321*4882a593Smuzhiyun return -1;
1322*4882a593Smuzhiyun }
1323*4882a593Smuzhiyun
1324*4882a593Smuzhiyun mutex_lock(&atkbd->mutex);
1325*4882a593Smuzhiyun
1326*4882a593Smuzhiyun atkbd_disable(atkbd);
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun if (atkbd->write) {
1329*4882a593Smuzhiyun if (atkbd_probe(atkbd))
1330*4882a593Smuzhiyun goto out;
1331*4882a593Smuzhiyun
1332*4882a593Smuzhiyun if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
1333*4882a593Smuzhiyun goto out;
1334*4882a593Smuzhiyun
1335*4882a593Smuzhiyun /*
1336*4882a593Smuzhiyun * Restore LED state and repeat rate. While input core
1337*4882a593Smuzhiyun * will do this for us at resume time reconnect may happen
1338*4882a593Smuzhiyun * because user requested it via sysfs or simply because
1339*4882a593Smuzhiyun * keyboard was unplugged and plugged in again so we need
1340*4882a593Smuzhiyun * to do it ourselves here.
1341*4882a593Smuzhiyun */
1342*4882a593Smuzhiyun atkbd_set_leds(atkbd);
1343*4882a593Smuzhiyun if (!atkbd->softrepeat)
1344*4882a593Smuzhiyun atkbd_set_repeat_rate(atkbd);
1345*4882a593Smuzhiyun
1346*4882a593Smuzhiyun }
1347*4882a593Smuzhiyun
1348*4882a593Smuzhiyun /*
1349*4882a593Smuzhiyun * Reset our state machine in case reconnect happened in the middle
1350*4882a593Smuzhiyun * of multi-byte scancode.
1351*4882a593Smuzhiyun */
1352*4882a593Smuzhiyun atkbd->xl_bit = 0;
1353*4882a593Smuzhiyun atkbd->emul = 0;
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun atkbd_enable(atkbd);
1356*4882a593Smuzhiyun if (atkbd->write)
1357*4882a593Smuzhiyun atkbd_activate(atkbd);
1358*4882a593Smuzhiyun
1359*4882a593Smuzhiyun retval = 0;
1360*4882a593Smuzhiyun
1361*4882a593Smuzhiyun out:
1362*4882a593Smuzhiyun mutex_unlock(&atkbd->mutex);
1363*4882a593Smuzhiyun return retval;
1364*4882a593Smuzhiyun }
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun static const struct serio_device_id atkbd_serio_ids[] = {
1367*4882a593Smuzhiyun {
1368*4882a593Smuzhiyun .type = SERIO_8042,
1369*4882a593Smuzhiyun .proto = SERIO_ANY,
1370*4882a593Smuzhiyun .id = SERIO_ANY,
1371*4882a593Smuzhiyun .extra = SERIO_ANY,
1372*4882a593Smuzhiyun },
1373*4882a593Smuzhiyun {
1374*4882a593Smuzhiyun .type = SERIO_8042_XL,
1375*4882a593Smuzhiyun .proto = SERIO_ANY,
1376*4882a593Smuzhiyun .id = SERIO_ANY,
1377*4882a593Smuzhiyun .extra = SERIO_ANY,
1378*4882a593Smuzhiyun },
1379*4882a593Smuzhiyun {
1380*4882a593Smuzhiyun .type = SERIO_RS232,
1381*4882a593Smuzhiyun .proto = SERIO_PS2SER,
1382*4882a593Smuzhiyun .id = SERIO_ANY,
1383*4882a593Smuzhiyun .extra = SERIO_ANY,
1384*4882a593Smuzhiyun },
1385*4882a593Smuzhiyun { 0 }
1386*4882a593Smuzhiyun };
1387*4882a593Smuzhiyun
1388*4882a593Smuzhiyun MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);
1389*4882a593Smuzhiyun
1390*4882a593Smuzhiyun static struct serio_driver atkbd_drv = {
1391*4882a593Smuzhiyun .driver = {
1392*4882a593Smuzhiyun .name = "atkbd",
1393*4882a593Smuzhiyun },
1394*4882a593Smuzhiyun .description = DRIVER_DESC,
1395*4882a593Smuzhiyun .id_table = atkbd_serio_ids,
1396*4882a593Smuzhiyun .interrupt = atkbd_interrupt,
1397*4882a593Smuzhiyun .connect = atkbd_connect,
1398*4882a593Smuzhiyun .reconnect = atkbd_reconnect,
1399*4882a593Smuzhiyun .disconnect = atkbd_disconnect,
1400*4882a593Smuzhiyun .cleanup = atkbd_cleanup,
1401*4882a593Smuzhiyun };
1402*4882a593Smuzhiyun
atkbd_attr_show_helper(struct device * dev,char * buf,ssize_t (* handler)(struct atkbd *,char *))1403*4882a593Smuzhiyun static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
1404*4882a593Smuzhiyun ssize_t (*handler)(struct atkbd *, char *))
1405*4882a593Smuzhiyun {
1406*4882a593Smuzhiyun struct serio *serio = to_serio_port(dev);
1407*4882a593Smuzhiyun struct atkbd *atkbd = serio_get_drvdata(serio);
1408*4882a593Smuzhiyun
1409*4882a593Smuzhiyun return handler(atkbd, buf);
1410*4882a593Smuzhiyun }
1411*4882a593Smuzhiyun
atkbd_attr_set_helper(struct device * dev,const char * buf,size_t count,ssize_t (* handler)(struct atkbd *,const char *,size_t))1412*4882a593Smuzhiyun static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
1413*4882a593Smuzhiyun ssize_t (*handler)(struct atkbd *, const char *, size_t))
1414*4882a593Smuzhiyun {
1415*4882a593Smuzhiyun struct serio *serio = to_serio_port(dev);
1416*4882a593Smuzhiyun struct atkbd *atkbd = serio_get_drvdata(serio);
1417*4882a593Smuzhiyun int retval;
1418*4882a593Smuzhiyun
1419*4882a593Smuzhiyun retval = mutex_lock_interruptible(&atkbd->mutex);
1420*4882a593Smuzhiyun if (retval)
1421*4882a593Smuzhiyun return retval;
1422*4882a593Smuzhiyun
1423*4882a593Smuzhiyun atkbd_disable(atkbd);
1424*4882a593Smuzhiyun retval = handler(atkbd, buf, count);
1425*4882a593Smuzhiyun atkbd_enable(atkbd);
1426*4882a593Smuzhiyun
1427*4882a593Smuzhiyun mutex_unlock(&atkbd->mutex);
1428*4882a593Smuzhiyun
1429*4882a593Smuzhiyun return retval;
1430*4882a593Smuzhiyun }
1431*4882a593Smuzhiyun
atkbd_show_extra(struct atkbd * atkbd,char * buf)1432*4882a593Smuzhiyun static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
1433*4882a593Smuzhiyun {
1434*4882a593Smuzhiyun return sprintf(buf, "%d\n", atkbd->extra ? 1 : 0);
1435*4882a593Smuzhiyun }
1436*4882a593Smuzhiyun
atkbd_set_extra(struct atkbd * atkbd,const char * buf,size_t count)1437*4882a593Smuzhiyun static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
1438*4882a593Smuzhiyun {
1439*4882a593Smuzhiyun struct input_dev *old_dev, *new_dev;
1440*4882a593Smuzhiyun unsigned int value;
1441*4882a593Smuzhiyun int err;
1442*4882a593Smuzhiyun bool old_extra;
1443*4882a593Smuzhiyun unsigned char old_set;
1444*4882a593Smuzhiyun
1445*4882a593Smuzhiyun if (!atkbd->write)
1446*4882a593Smuzhiyun return -EIO;
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun err = kstrtouint(buf, 10, &value);
1449*4882a593Smuzhiyun if (err)
1450*4882a593Smuzhiyun return err;
1451*4882a593Smuzhiyun
1452*4882a593Smuzhiyun if (value > 1)
1453*4882a593Smuzhiyun return -EINVAL;
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun if (atkbd->extra != value) {
1456*4882a593Smuzhiyun /*
1457*4882a593Smuzhiyun * Since device's properties will change we need to
1458*4882a593Smuzhiyun * unregister old device. But allocate and register
1459*4882a593Smuzhiyun * new one first to make sure we have it.
1460*4882a593Smuzhiyun */
1461*4882a593Smuzhiyun old_dev = atkbd->dev;
1462*4882a593Smuzhiyun old_extra = atkbd->extra;
1463*4882a593Smuzhiyun old_set = atkbd->set;
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun new_dev = input_allocate_device();
1466*4882a593Smuzhiyun if (!new_dev)
1467*4882a593Smuzhiyun return -ENOMEM;
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun atkbd->dev = new_dev;
1470*4882a593Smuzhiyun atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
1471*4882a593Smuzhiyun atkbd_reset_state(atkbd);
1472*4882a593Smuzhiyun atkbd_activate(atkbd);
1473*4882a593Smuzhiyun atkbd_set_keycode_table(atkbd);
1474*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun err = input_register_device(atkbd->dev);
1477*4882a593Smuzhiyun if (err) {
1478*4882a593Smuzhiyun input_free_device(new_dev);
1479*4882a593Smuzhiyun
1480*4882a593Smuzhiyun atkbd->dev = old_dev;
1481*4882a593Smuzhiyun atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
1482*4882a593Smuzhiyun atkbd_set_keycode_table(atkbd);
1483*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1484*4882a593Smuzhiyun
1485*4882a593Smuzhiyun return err;
1486*4882a593Smuzhiyun }
1487*4882a593Smuzhiyun input_unregister_device(old_dev);
1488*4882a593Smuzhiyun
1489*4882a593Smuzhiyun }
1490*4882a593Smuzhiyun return count;
1491*4882a593Smuzhiyun }
1492*4882a593Smuzhiyun
atkbd_show_force_release(struct atkbd * atkbd,char * buf)1493*4882a593Smuzhiyun static ssize_t atkbd_show_force_release(struct atkbd *atkbd, char *buf)
1494*4882a593Smuzhiyun {
1495*4882a593Smuzhiyun size_t len = scnprintf(buf, PAGE_SIZE - 1, "%*pbl",
1496*4882a593Smuzhiyun ATKBD_KEYMAP_SIZE, atkbd->force_release_mask);
1497*4882a593Smuzhiyun
1498*4882a593Smuzhiyun buf[len++] = '\n';
1499*4882a593Smuzhiyun buf[len] = '\0';
1500*4882a593Smuzhiyun
1501*4882a593Smuzhiyun return len;
1502*4882a593Smuzhiyun }
1503*4882a593Smuzhiyun
atkbd_set_force_release(struct atkbd * atkbd,const char * buf,size_t count)1504*4882a593Smuzhiyun static ssize_t atkbd_set_force_release(struct atkbd *atkbd,
1505*4882a593Smuzhiyun const char *buf, size_t count)
1506*4882a593Smuzhiyun {
1507*4882a593Smuzhiyun /* 64 bytes on stack should be acceptable */
1508*4882a593Smuzhiyun DECLARE_BITMAP(new_mask, ATKBD_KEYMAP_SIZE);
1509*4882a593Smuzhiyun int err;
1510*4882a593Smuzhiyun
1511*4882a593Smuzhiyun err = bitmap_parselist(buf, new_mask, ATKBD_KEYMAP_SIZE);
1512*4882a593Smuzhiyun if (err)
1513*4882a593Smuzhiyun return err;
1514*4882a593Smuzhiyun
1515*4882a593Smuzhiyun memcpy(atkbd->force_release_mask, new_mask, sizeof(atkbd->force_release_mask));
1516*4882a593Smuzhiyun return count;
1517*4882a593Smuzhiyun }
1518*4882a593Smuzhiyun
1519*4882a593Smuzhiyun
atkbd_show_scroll(struct atkbd * atkbd,char * buf)1520*4882a593Smuzhiyun static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
1521*4882a593Smuzhiyun {
1522*4882a593Smuzhiyun return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0);
1523*4882a593Smuzhiyun }
1524*4882a593Smuzhiyun
atkbd_set_scroll(struct atkbd * atkbd,const char * buf,size_t count)1525*4882a593Smuzhiyun static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
1526*4882a593Smuzhiyun {
1527*4882a593Smuzhiyun struct input_dev *old_dev, *new_dev;
1528*4882a593Smuzhiyun unsigned int value;
1529*4882a593Smuzhiyun int err;
1530*4882a593Smuzhiyun bool old_scroll;
1531*4882a593Smuzhiyun
1532*4882a593Smuzhiyun err = kstrtouint(buf, 10, &value);
1533*4882a593Smuzhiyun if (err)
1534*4882a593Smuzhiyun return err;
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun if (value > 1)
1537*4882a593Smuzhiyun return -EINVAL;
1538*4882a593Smuzhiyun
1539*4882a593Smuzhiyun if (atkbd->scroll != value) {
1540*4882a593Smuzhiyun old_dev = atkbd->dev;
1541*4882a593Smuzhiyun old_scroll = atkbd->scroll;
1542*4882a593Smuzhiyun
1543*4882a593Smuzhiyun new_dev = input_allocate_device();
1544*4882a593Smuzhiyun if (!new_dev)
1545*4882a593Smuzhiyun return -ENOMEM;
1546*4882a593Smuzhiyun
1547*4882a593Smuzhiyun atkbd->dev = new_dev;
1548*4882a593Smuzhiyun atkbd->scroll = value;
1549*4882a593Smuzhiyun atkbd_set_keycode_table(atkbd);
1550*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1551*4882a593Smuzhiyun
1552*4882a593Smuzhiyun err = input_register_device(atkbd->dev);
1553*4882a593Smuzhiyun if (err) {
1554*4882a593Smuzhiyun input_free_device(new_dev);
1555*4882a593Smuzhiyun
1556*4882a593Smuzhiyun atkbd->scroll = old_scroll;
1557*4882a593Smuzhiyun atkbd->dev = old_dev;
1558*4882a593Smuzhiyun atkbd_set_keycode_table(atkbd);
1559*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun return err;
1562*4882a593Smuzhiyun }
1563*4882a593Smuzhiyun input_unregister_device(old_dev);
1564*4882a593Smuzhiyun }
1565*4882a593Smuzhiyun return count;
1566*4882a593Smuzhiyun }
1567*4882a593Smuzhiyun
atkbd_show_set(struct atkbd * atkbd,char * buf)1568*4882a593Smuzhiyun static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
1569*4882a593Smuzhiyun {
1570*4882a593Smuzhiyun return sprintf(buf, "%d\n", atkbd->set);
1571*4882a593Smuzhiyun }
1572*4882a593Smuzhiyun
atkbd_set_set(struct atkbd * atkbd,const char * buf,size_t count)1573*4882a593Smuzhiyun static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
1574*4882a593Smuzhiyun {
1575*4882a593Smuzhiyun struct input_dev *old_dev, *new_dev;
1576*4882a593Smuzhiyun unsigned int value;
1577*4882a593Smuzhiyun int err;
1578*4882a593Smuzhiyun unsigned char old_set;
1579*4882a593Smuzhiyun bool old_extra;
1580*4882a593Smuzhiyun
1581*4882a593Smuzhiyun if (!atkbd->write)
1582*4882a593Smuzhiyun return -EIO;
1583*4882a593Smuzhiyun
1584*4882a593Smuzhiyun err = kstrtouint(buf, 10, &value);
1585*4882a593Smuzhiyun if (err)
1586*4882a593Smuzhiyun return err;
1587*4882a593Smuzhiyun
1588*4882a593Smuzhiyun if (value != 2 && value != 3)
1589*4882a593Smuzhiyun return -EINVAL;
1590*4882a593Smuzhiyun
1591*4882a593Smuzhiyun if (atkbd->set != value) {
1592*4882a593Smuzhiyun old_dev = atkbd->dev;
1593*4882a593Smuzhiyun old_extra = atkbd->extra;
1594*4882a593Smuzhiyun old_set = atkbd->set;
1595*4882a593Smuzhiyun
1596*4882a593Smuzhiyun new_dev = input_allocate_device();
1597*4882a593Smuzhiyun if (!new_dev)
1598*4882a593Smuzhiyun return -ENOMEM;
1599*4882a593Smuzhiyun
1600*4882a593Smuzhiyun atkbd->dev = new_dev;
1601*4882a593Smuzhiyun atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
1602*4882a593Smuzhiyun atkbd_reset_state(atkbd);
1603*4882a593Smuzhiyun atkbd_activate(atkbd);
1604*4882a593Smuzhiyun atkbd_set_keycode_table(atkbd);
1605*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1606*4882a593Smuzhiyun
1607*4882a593Smuzhiyun err = input_register_device(atkbd->dev);
1608*4882a593Smuzhiyun if (err) {
1609*4882a593Smuzhiyun input_free_device(new_dev);
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun atkbd->dev = old_dev;
1612*4882a593Smuzhiyun atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
1613*4882a593Smuzhiyun atkbd_set_keycode_table(atkbd);
1614*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1615*4882a593Smuzhiyun
1616*4882a593Smuzhiyun return err;
1617*4882a593Smuzhiyun }
1618*4882a593Smuzhiyun input_unregister_device(old_dev);
1619*4882a593Smuzhiyun }
1620*4882a593Smuzhiyun return count;
1621*4882a593Smuzhiyun }
1622*4882a593Smuzhiyun
atkbd_show_softrepeat(struct atkbd * atkbd,char * buf)1623*4882a593Smuzhiyun static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
1624*4882a593Smuzhiyun {
1625*4882a593Smuzhiyun return sprintf(buf, "%d\n", atkbd->softrepeat ? 1 : 0);
1626*4882a593Smuzhiyun }
1627*4882a593Smuzhiyun
atkbd_set_softrepeat(struct atkbd * atkbd,const char * buf,size_t count)1628*4882a593Smuzhiyun static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
1629*4882a593Smuzhiyun {
1630*4882a593Smuzhiyun struct input_dev *old_dev, *new_dev;
1631*4882a593Smuzhiyun unsigned int value;
1632*4882a593Smuzhiyun int err;
1633*4882a593Smuzhiyun bool old_softrepeat, old_softraw;
1634*4882a593Smuzhiyun
1635*4882a593Smuzhiyun if (!atkbd->write)
1636*4882a593Smuzhiyun return -EIO;
1637*4882a593Smuzhiyun
1638*4882a593Smuzhiyun err = kstrtouint(buf, 10, &value);
1639*4882a593Smuzhiyun if (err)
1640*4882a593Smuzhiyun return err;
1641*4882a593Smuzhiyun
1642*4882a593Smuzhiyun if (value > 1)
1643*4882a593Smuzhiyun return -EINVAL;
1644*4882a593Smuzhiyun
1645*4882a593Smuzhiyun if (atkbd->softrepeat != value) {
1646*4882a593Smuzhiyun old_dev = atkbd->dev;
1647*4882a593Smuzhiyun old_softrepeat = atkbd->softrepeat;
1648*4882a593Smuzhiyun old_softraw = atkbd->softraw;
1649*4882a593Smuzhiyun
1650*4882a593Smuzhiyun new_dev = input_allocate_device();
1651*4882a593Smuzhiyun if (!new_dev)
1652*4882a593Smuzhiyun return -ENOMEM;
1653*4882a593Smuzhiyun
1654*4882a593Smuzhiyun atkbd->dev = new_dev;
1655*4882a593Smuzhiyun atkbd->softrepeat = value;
1656*4882a593Smuzhiyun if (atkbd->softrepeat)
1657*4882a593Smuzhiyun atkbd->softraw = true;
1658*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1659*4882a593Smuzhiyun
1660*4882a593Smuzhiyun err = input_register_device(atkbd->dev);
1661*4882a593Smuzhiyun if (err) {
1662*4882a593Smuzhiyun input_free_device(new_dev);
1663*4882a593Smuzhiyun
1664*4882a593Smuzhiyun atkbd->dev = old_dev;
1665*4882a593Smuzhiyun atkbd->softrepeat = old_softrepeat;
1666*4882a593Smuzhiyun atkbd->softraw = old_softraw;
1667*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1668*4882a593Smuzhiyun
1669*4882a593Smuzhiyun return err;
1670*4882a593Smuzhiyun }
1671*4882a593Smuzhiyun input_unregister_device(old_dev);
1672*4882a593Smuzhiyun }
1673*4882a593Smuzhiyun return count;
1674*4882a593Smuzhiyun }
1675*4882a593Smuzhiyun
1676*4882a593Smuzhiyun
atkbd_show_softraw(struct atkbd * atkbd,char * buf)1677*4882a593Smuzhiyun static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
1678*4882a593Smuzhiyun {
1679*4882a593Smuzhiyun return sprintf(buf, "%d\n", atkbd->softraw ? 1 : 0);
1680*4882a593Smuzhiyun }
1681*4882a593Smuzhiyun
atkbd_set_softraw(struct atkbd * atkbd,const char * buf,size_t count)1682*4882a593Smuzhiyun static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
1683*4882a593Smuzhiyun {
1684*4882a593Smuzhiyun struct input_dev *old_dev, *new_dev;
1685*4882a593Smuzhiyun unsigned int value;
1686*4882a593Smuzhiyun int err;
1687*4882a593Smuzhiyun bool old_softraw;
1688*4882a593Smuzhiyun
1689*4882a593Smuzhiyun err = kstrtouint(buf, 10, &value);
1690*4882a593Smuzhiyun if (err)
1691*4882a593Smuzhiyun return err;
1692*4882a593Smuzhiyun
1693*4882a593Smuzhiyun if (value > 1)
1694*4882a593Smuzhiyun return -EINVAL;
1695*4882a593Smuzhiyun
1696*4882a593Smuzhiyun if (atkbd->softraw != value) {
1697*4882a593Smuzhiyun old_dev = atkbd->dev;
1698*4882a593Smuzhiyun old_softraw = atkbd->softraw;
1699*4882a593Smuzhiyun
1700*4882a593Smuzhiyun new_dev = input_allocate_device();
1701*4882a593Smuzhiyun if (!new_dev)
1702*4882a593Smuzhiyun return -ENOMEM;
1703*4882a593Smuzhiyun
1704*4882a593Smuzhiyun atkbd->dev = new_dev;
1705*4882a593Smuzhiyun atkbd->softraw = value;
1706*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1707*4882a593Smuzhiyun
1708*4882a593Smuzhiyun err = input_register_device(atkbd->dev);
1709*4882a593Smuzhiyun if (err) {
1710*4882a593Smuzhiyun input_free_device(new_dev);
1711*4882a593Smuzhiyun
1712*4882a593Smuzhiyun atkbd->dev = old_dev;
1713*4882a593Smuzhiyun atkbd->softraw = old_softraw;
1714*4882a593Smuzhiyun atkbd_set_device_attrs(atkbd);
1715*4882a593Smuzhiyun
1716*4882a593Smuzhiyun return err;
1717*4882a593Smuzhiyun }
1718*4882a593Smuzhiyun input_unregister_device(old_dev);
1719*4882a593Smuzhiyun }
1720*4882a593Smuzhiyun return count;
1721*4882a593Smuzhiyun }
1722*4882a593Smuzhiyun
atkbd_show_err_count(struct atkbd * atkbd,char * buf)1723*4882a593Smuzhiyun static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf)
1724*4882a593Smuzhiyun {
1725*4882a593Smuzhiyun return sprintf(buf, "%lu\n", atkbd->err_count);
1726*4882a593Smuzhiyun }
1727*4882a593Smuzhiyun
atkbd_setup_forced_release(const struct dmi_system_id * id)1728*4882a593Smuzhiyun static int __init atkbd_setup_forced_release(const struct dmi_system_id *id)
1729*4882a593Smuzhiyun {
1730*4882a593Smuzhiyun atkbd_platform_fixup = atkbd_apply_forced_release_keylist;
1731*4882a593Smuzhiyun atkbd_platform_fixup_data = id->driver_data;
1732*4882a593Smuzhiyun
1733*4882a593Smuzhiyun return 1;
1734*4882a593Smuzhiyun }
1735*4882a593Smuzhiyun
atkbd_setup_scancode_fixup(const struct dmi_system_id * id)1736*4882a593Smuzhiyun static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
1737*4882a593Smuzhiyun {
1738*4882a593Smuzhiyun atkbd_platform_scancode_fixup = id->driver_data;
1739*4882a593Smuzhiyun
1740*4882a593Smuzhiyun return 1;
1741*4882a593Smuzhiyun }
1742*4882a593Smuzhiyun
atkbd_deactivate_fixup(const struct dmi_system_id * id)1743*4882a593Smuzhiyun static int __init atkbd_deactivate_fixup(const struct dmi_system_id *id)
1744*4882a593Smuzhiyun {
1745*4882a593Smuzhiyun atkbd_skip_deactivate = true;
1746*4882a593Smuzhiyun return 1;
1747*4882a593Smuzhiyun }
1748*4882a593Smuzhiyun
1749*4882a593Smuzhiyun /*
1750*4882a593Smuzhiyun * NOTE: do not add any more "force release" quirks to this table. The
1751*4882a593Smuzhiyun * task of adjusting list of keys that should be "released" automatically
1752*4882a593Smuzhiyun * by the driver is now delegated to userspace tools, such as udev, so
1753*4882a593Smuzhiyun * submit such quirks there.
1754*4882a593Smuzhiyun */
1755*4882a593Smuzhiyun static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
1756*4882a593Smuzhiyun {
1757*4882a593Smuzhiyun .matches = {
1758*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
1759*4882a593Smuzhiyun DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
1760*4882a593Smuzhiyun },
1761*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1762*4882a593Smuzhiyun .driver_data = atkbd_dell_laptop_forced_release_keys,
1763*4882a593Smuzhiyun },
1764*4882a593Smuzhiyun {
1765*4882a593Smuzhiyun .matches = {
1766*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
1767*4882a593Smuzhiyun DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
1768*4882a593Smuzhiyun },
1769*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1770*4882a593Smuzhiyun .driver_data = atkbd_dell_laptop_forced_release_keys,
1771*4882a593Smuzhiyun },
1772*4882a593Smuzhiyun {
1773*4882a593Smuzhiyun .matches = {
1774*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1775*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"),
1776*4882a593Smuzhiyun },
1777*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1778*4882a593Smuzhiyun .driver_data = atkbd_hp_forced_release_keys,
1779*4882a593Smuzhiyun },
1780*4882a593Smuzhiyun {
1781*4882a593Smuzhiyun .matches = {
1782*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1783*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"),
1784*4882a593Smuzhiyun },
1785*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1786*4882a593Smuzhiyun .driver_data = atkbd_volume_forced_release_keys,
1787*4882a593Smuzhiyun },
1788*4882a593Smuzhiyun {
1789*4882a593Smuzhiyun .matches = {
1790*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1791*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"),
1792*4882a593Smuzhiyun },
1793*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1794*4882a593Smuzhiyun .driver_data = atkbd_volume_forced_release_keys,
1795*4882a593Smuzhiyun },
1796*4882a593Smuzhiyun {
1797*4882a593Smuzhiyun .matches = {
1798*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1799*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"),
1800*4882a593Smuzhiyun },
1801*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1802*4882a593Smuzhiyun .driver_data = atkbd_volume_forced_release_keys,
1803*4882a593Smuzhiyun },
1804*4882a593Smuzhiyun {
1805*4882a593Smuzhiyun .matches = {
1806*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1807*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"),
1808*4882a593Smuzhiyun },
1809*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1810*4882a593Smuzhiyun .driver_data = atkbd_volume_forced_release_keys,
1811*4882a593Smuzhiyun },
1812*4882a593Smuzhiyun {
1813*4882a593Smuzhiyun /* Inventec Symphony */
1814*4882a593Smuzhiyun .matches = {
1815*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"),
1816*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"),
1817*4882a593Smuzhiyun },
1818*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1819*4882a593Smuzhiyun .driver_data = atkbd_volume_forced_release_keys,
1820*4882a593Smuzhiyun },
1821*4882a593Smuzhiyun {
1822*4882a593Smuzhiyun /* Samsung NC10 */
1823*4882a593Smuzhiyun .matches = {
1824*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
1825*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
1826*4882a593Smuzhiyun },
1827*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1828*4882a593Smuzhiyun .driver_data = atkbd_samsung_forced_release_keys,
1829*4882a593Smuzhiyun },
1830*4882a593Smuzhiyun {
1831*4882a593Smuzhiyun /* Samsung NC20 */
1832*4882a593Smuzhiyun .matches = {
1833*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
1834*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "NC20"),
1835*4882a593Smuzhiyun },
1836*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1837*4882a593Smuzhiyun .driver_data = atkbd_samsung_forced_release_keys,
1838*4882a593Smuzhiyun },
1839*4882a593Smuzhiyun {
1840*4882a593Smuzhiyun /* Samsung SQ45S70S */
1841*4882a593Smuzhiyun .matches = {
1842*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
1843*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
1844*4882a593Smuzhiyun },
1845*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1846*4882a593Smuzhiyun .driver_data = atkbd_samsung_forced_release_keys,
1847*4882a593Smuzhiyun },
1848*4882a593Smuzhiyun {
1849*4882a593Smuzhiyun /* Fujitsu Amilo PA 1510 */
1850*4882a593Smuzhiyun .matches = {
1851*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
1852*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"),
1853*4882a593Smuzhiyun },
1854*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1855*4882a593Smuzhiyun .driver_data = atkbd_volume_forced_release_keys,
1856*4882a593Smuzhiyun },
1857*4882a593Smuzhiyun {
1858*4882a593Smuzhiyun /* Fujitsu Amilo Pi 3525 */
1859*4882a593Smuzhiyun .matches = {
1860*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
1861*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 3525"),
1862*4882a593Smuzhiyun },
1863*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1864*4882a593Smuzhiyun .driver_data = atkbd_amilo_pi3525_forced_release_keys,
1865*4882a593Smuzhiyun },
1866*4882a593Smuzhiyun {
1867*4882a593Smuzhiyun /* Fujitsu Amilo Xi 3650 */
1868*4882a593Smuzhiyun .matches = {
1869*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
1870*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 3650"),
1871*4882a593Smuzhiyun },
1872*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1873*4882a593Smuzhiyun .driver_data = atkbd_amilo_xi3650_forced_release_keys,
1874*4882a593Smuzhiyun },
1875*4882a593Smuzhiyun {
1876*4882a593Smuzhiyun .matches = {
1877*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"),
1878*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "TA12"),
1879*4882a593Smuzhiyun },
1880*4882a593Smuzhiyun .callback = atkbd_setup_forced_release,
1881*4882a593Smuzhiyun .driver_data = atkdb_soltech_ta12_forced_release_keys,
1882*4882a593Smuzhiyun },
1883*4882a593Smuzhiyun {
1884*4882a593Smuzhiyun /* OQO Model 01+ */
1885*4882a593Smuzhiyun .matches = {
1886*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
1887*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
1888*4882a593Smuzhiyun },
1889*4882a593Smuzhiyun .callback = atkbd_setup_scancode_fixup,
1890*4882a593Smuzhiyun .driver_data = atkbd_oqo_01plus_scancode_fixup,
1891*4882a593Smuzhiyun },
1892*4882a593Smuzhiyun {
1893*4882a593Smuzhiyun .matches = {
1894*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
1895*4882a593Smuzhiyun },
1896*4882a593Smuzhiyun .callback = atkbd_deactivate_fixup,
1897*4882a593Smuzhiyun },
1898*4882a593Smuzhiyun { }
1899*4882a593Smuzhiyun };
1900*4882a593Smuzhiyun
atkbd_init(void)1901*4882a593Smuzhiyun static int __init atkbd_init(void)
1902*4882a593Smuzhiyun {
1903*4882a593Smuzhiyun dmi_check_system(atkbd_dmi_quirk_table);
1904*4882a593Smuzhiyun
1905*4882a593Smuzhiyun return serio_register_driver(&atkbd_drv);
1906*4882a593Smuzhiyun }
1907*4882a593Smuzhiyun
atkbd_exit(void)1908*4882a593Smuzhiyun static void __exit atkbd_exit(void)
1909*4882a593Smuzhiyun {
1910*4882a593Smuzhiyun serio_unregister_driver(&atkbd_drv);
1911*4882a593Smuzhiyun }
1912*4882a593Smuzhiyun
1913*4882a593Smuzhiyun module_init(atkbd_init);
1914*4882a593Smuzhiyun module_exit(atkbd_exit);
1915