aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt1
-rw-r--r--drivers/char/keyboard.c111
-rw-r--r--drivers/input/evdev.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c32
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c1
-rw-r--r--drivers/input/keyboard/atkbd.c10
-rw-r--r--drivers/input/keyboard/sunkbd.c2
-rw-r--r--drivers/input/mouse/Makefile2
-rw-r--r--drivers/input/mouse/alps.c2
-rw-r--r--drivers/input/mouse/logips2pp.c13
-rw-r--r--drivers/input/mouse/psmouse-base.c132
-rw-r--r--drivers/input/mouse/psmouse.h52
-rw-r--r--drivers/input/mouse/trackpoint.c304
-rw-r--r--drivers/input/mouse/trackpoint.h147
-rw-r--r--drivers/input/serio/i8042-io.h6
-rw-r--r--drivers/input/serio/i8042-ip22io.h2
-rw-r--r--drivers/input/serio/i8042-jazzio.h2
-rw-r--r--drivers/input/serio/i8042-sparcio.h12
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h72
-rw-r--r--drivers/input/serio/i8042.c199
-rw-r--r--drivers/usb/input/hid-core.c76
-rw-r--r--drivers/usb/input/hid-debug.h34
-rw-r--r--drivers/usb/input/hid-input.c66
-rw-r--r--drivers/usb/input/hid.h9
-rw-r--r--drivers/usb/input/hiddev.c1
-rw-r--r--include/linux/input.h8
26 files changed, 986 insertions, 312 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d2f0c67ba1fb..db2603ceabba 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -549,6 +549,7 @@ running once the system is up.
549 keyboard and can not control its state 549 keyboard and can not control its state
550 (Don't attempt to blink the leds) 550 (Don't attempt to blink the leds)
551 i8042.noaux [HW] Don't check for auxiliary (== mouse) port 551 i8042.noaux [HW] Don't check for auxiliary (== mouse) port
552 i8042.nokbd [HW] Don't check/create keyboard port
552 i8042.nomux [HW] Don't check presence of an active multiplexing 553 i8042.nomux [HW] Don't check presence of an active multiplexing
553 controller 554 controller
554 i8042.nopnp [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX 555 i8042.nopnp [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 1745065d8f78..449d029ad4f4 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -14,7 +14,7 @@
14 * `Sticky' modifier keys, 951006. 14 * `Sticky' modifier keys, 951006.
15 * 15 *
16 * 11-11-96: SAK should now work in the raw mode (Martin Mares) 16 * 11-11-96: SAK should now work in the raw mode (Martin Mares)
17 * 17 *
18 * Modified to provide 'generic' keyboard support by Hamish Macdonald 18 * Modified to provide 'generic' keyboard support by Hamish Macdonald
19 * Merge with the m68k keyboard driver and split-off of the PC low-level 19 * Merge with the m68k keyboard driver and split-off of the PC low-level
20 * parts by Geert Uytterhoeven, May 1997 20 * parts by Geert Uytterhoeven, May 1997
@@ -52,7 +52,7 @@ extern void ctrl_alt_del(void);
52/* 52/*
53 * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on. 53 * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
54 * This seems a good reason to start with NumLock off. On HIL keyboards 54 * This seems a good reason to start with NumLock off. On HIL keyboards
55 * of PARISC machines however there is no NumLock key and everyone expects the keypad 55 * of PARISC machines however there is no NumLock key and everyone expects the keypad
56 * to be used for numbers. 56 * to be used for numbers.
57 */ 57 */
58 58
@@ -76,17 +76,17 @@ void compute_shiftstate(void);
76 k_meta, k_ascii, k_lock, k_lowercase,\ 76 k_meta, k_ascii, k_lock, k_lowercase,\
77 k_slock, k_dead2, k_ignore, k_ignore 77 k_slock, k_dead2, k_ignore, k_ignore
78 78
79typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, 79typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
80 char up_flag, struct pt_regs *regs); 80 char up_flag, struct pt_regs *regs);
81static k_handler_fn K_HANDLERS; 81static k_handler_fn K_HANDLERS;
82static k_handler_fn *k_handler[16] = { K_HANDLERS }; 82static k_handler_fn *k_handler[16] = { K_HANDLERS };
83 83
84#define FN_HANDLERS\ 84#define FN_HANDLERS\
85 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ 85 fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
86 fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\ 86 fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
87 fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\ 87 fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
88 fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\ 88 fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
89 fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num 89 fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
90 90
91typedef void (fn_handler_fn)(struct vc_data *vc, struct pt_regs *regs); 91typedef void (fn_handler_fn)(struct vc_data *vc, struct pt_regs *regs);
92static fn_handler_fn FN_HANDLERS; 92static fn_handler_fn FN_HANDLERS;
@@ -159,13 +159,13 @@ static int sysrq_alt;
159 */ 159 */
160int getkeycode(unsigned int scancode) 160int getkeycode(unsigned int scancode)
161{ 161{
162 struct list_head * node; 162 struct list_head *node;
163 struct input_dev *dev = NULL; 163 struct input_dev *dev = NULL;
164 164
165 list_for_each(node,&kbd_handler.h_list) { 165 list_for_each(node, &kbd_handler.h_list) {
166 struct input_handle * handle = to_handle_h(node); 166 struct input_handle *handle = to_handle_h(node);
167 if (handle->dev->keycodesize) { 167 if (handle->dev->keycodesize) {
168 dev = handle->dev; 168 dev = handle->dev;
169 break; 169 break;
170 } 170 }
171 } 171 }
@@ -181,15 +181,15 @@ int getkeycode(unsigned int scancode)
181 181
182int setkeycode(unsigned int scancode, unsigned int keycode) 182int setkeycode(unsigned int scancode, unsigned int keycode)
183{ 183{
184 struct list_head * node; 184 struct list_head *node;
185 struct input_dev *dev = NULL; 185 struct input_dev *dev = NULL;
186 unsigned int i, oldkey; 186 unsigned int i, oldkey;
187 187
188 list_for_each(node,&kbd_handler.h_list) { 188 list_for_each(node, &kbd_handler.h_list) {
189 struct input_handle *handle = to_handle_h(node); 189 struct input_handle *handle = to_handle_h(node);
190 if (handle->dev->keycodesize) { 190 if (handle->dev->keycodesize) {
191 dev = handle->dev; 191 dev = handle->dev;
192 break; 192 break;
193 } 193 }
194 } 194 }
195 195
@@ -200,7 +200,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
200 return -EINVAL; 200 return -EINVAL;
201 if (keycode < 0 || keycode > KEY_MAX) 201 if (keycode < 0 || keycode > KEY_MAX)
202 return -EINVAL; 202 return -EINVAL;
203 if (keycode >> (dev->keycodesize * 8)) 203 if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
204 return -EINVAL; 204 return -EINVAL;
205 205
206 oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode); 206 oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
@@ -216,11 +216,11 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
216} 216}
217 217
218/* 218/*
219 * Making beeps and bells. 219 * Making beeps and bells.
220 */ 220 */
221static void kd_nosound(unsigned long ignored) 221static void kd_nosound(unsigned long ignored)
222{ 222{
223 struct list_head * node; 223 struct list_head *node;
224 224
225 list_for_each(node,&kbd_handler.h_list) { 225 list_for_each(node,&kbd_handler.h_list) {
226 struct input_handle *handle = to_handle_h(node); 226 struct input_handle *handle = to_handle_h(node);
@@ -237,12 +237,12 @@ static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
237 237
238void kd_mksound(unsigned int hz, unsigned int ticks) 238void kd_mksound(unsigned int hz, unsigned int ticks)
239{ 239{
240 struct list_head * node; 240 struct list_head *node;
241 241
242 del_timer(&kd_mksound_timer); 242 del_timer(&kd_mksound_timer);
243 243
244 if (hz) { 244 if (hz) {
245 list_for_each_prev(node,&kbd_handler.h_list) { 245 list_for_each_prev(node, &kbd_handler.h_list) {
246 struct input_handle *handle = to_handle_h(node); 246 struct input_handle *handle = to_handle_h(node);
247 if (test_bit(EV_SND, handle->dev->evbit)) { 247 if (test_bit(EV_SND, handle->dev->evbit)) {
248 if (test_bit(SND_TONE, handle->dev->sndbit)) { 248 if (test_bit(SND_TONE, handle->dev->sndbit)) {
@@ -337,19 +337,19 @@ static void to_utf8(struct vc_data *vc, ushort c)
337 if (c < 0x80) 337 if (c < 0x80)
338 /* 0******* */ 338 /* 0******* */
339 put_queue(vc, c); 339 put_queue(vc, c);
340 else if (c < 0x800) { 340 else if (c < 0x800) {
341 /* 110***** 10****** */ 341 /* 110***** 10****** */
342 put_queue(vc, 0xc0 | (c >> 6)); 342 put_queue(vc, 0xc0 | (c >> 6));
343 put_queue(vc, 0x80 | (c & 0x3f)); 343 put_queue(vc, 0x80 | (c & 0x3f));
344 } else { 344 } else {
345 /* 1110**** 10****** 10****** */ 345 /* 1110**** 10****** 10****** */
346 put_queue(vc, 0xe0 | (c >> 12)); 346 put_queue(vc, 0xe0 | (c >> 12));
347 put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); 347 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
348 put_queue(vc, 0x80 | (c & 0x3f)); 348 put_queue(vc, 0x80 | (c & 0x3f));
349 } 349 }
350} 350}
351 351
352/* 352/*
353 * Called after returning from RAW mode or when changing consoles - recompute 353 * Called after returning from RAW mode or when changing consoles - recompute
354 * shift_down[] and shift_state from key_down[] maybe called when keymap is 354 * shift_down[] and shift_state from key_down[] maybe called when keymap is
355 * undefined, so that shiftkey release is seen 355 * undefined, so that shiftkey release is seen
@@ -360,7 +360,7 @@ void compute_shiftstate(void)
360 360
361 shift_state = 0; 361 shift_state = 0;
362 memset(shift_down, 0, sizeof(shift_down)); 362 memset(shift_down, 0, sizeof(shift_down));
363 363
364 for (i = 0; i < ARRAY_SIZE(key_down); i++) { 364 for (i = 0; i < ARRAY_SIZE(key_down); i++) {
365 365
366 if (!key_down[i]) 366 if (!key_down[i])
@@ -499,9 +499,9 @@ static void fn_dec_console(struct vc_data *vc, struct pt_regs *regs)
499 if (want_console != -1) 499 if (want_console != -1)
500 cur = want_console; 500 cur = want_console;
501 501
502 for (i = cur-1; i != cur; i--) { 502 for (i = cur - 1; i != cur; i--) {
503 if (i == -1) 503 if (i == -1)
504 i = MAX_NR_CONSOLES-1; 504 i = MAX_NR_CONSOLES - 1;
505 if (vc_cons_allocated(i)) 505 if (vc_cons_allocated(i))
506 break; 506 break;
507 } 507 }
@@ -567,9 +567,9 @@ static void fn_compose(struct vc_data *vc, struct pt_regs *regs)
567 567
568static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs) 568static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs)
569{ 569{
570 if (spawnpid) 570 if (spawnpid)
571 if(kill_proc(spawnpid, spawnsig, 1)) 571 if (kill_proc(spawnpid, spawnsig, 1))
572 spawnpid = 0; 572 spawnpid = 0;
573} 573}
574 574
575static void fn_SAK(struct vc_data *vc, struct pt_regs *regs) 575static void fn_SAK(struct vc_data *vc, struct pt_regs *regs)
@@ -603,8 +603,8 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag, struct
603 return; 603 return;
604 if (value >= ARRAY_SIZE(fn_handler)) 604 if (value >= ARRAY_SIZE(fn_handler))
605 return; 605 return;
606 if ((kbd->kbdmode == VC_RAW || 606 if ((kbd->kbdmode == VC_RAW ||
607 kbd->kbdmode == VC_MEDIUMRAW) && 607 kbd->kbdmode == VC_MEDIUMRAW) &&
608 value != KVAL(K_SAK)) 608 value != KVAL(K_SAK))
609 return; /* SAK is allowed even in raw mode */ 609 return; /* SAK is allowed even in raw mode */
610 fn_handler[value](vc, regs); 610 fn_handler[value](vc, regs);
@@ -894,11 +894,11 @@ static inline unsigned char getleds(void)
894 894
895static void kbd_bh(unsigned long dummy) 895static void kbd_bh(unsigned long dummy)
896{ 896{
897 struct list_head * node; 897 struct list_head *node;
898 unsigned char leds = getleds(); 898 unsigned char leds = getleds();
899 899
900 if (leds != ledstate) { 900 if (leds != ledstate) {
901 list_for_each(node,&kbd_handler.h_list) { 901 list_for_each(node, &kbd_handler.h_list) {
902 struct input_handle * handle = to_handle_h(node); 902 struct input_handle * handle = to_handle_h(node);
903 input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); 903 input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
904 input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); 904 input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
@@ -963,11 +963,11 @@ static int sparc_l1_a_state = 0;
963extern void sun_do_break(void); 963extern void sun_do_break(void);
964#endif 964#endif
965 965
966static int emulate_raw(struct vc_data *vc, unsigned int keycode, 966static int emulate_raw(struct vc_data *vc, unsigned int keycode,
967 unsigned char up_flag) 967 unsigned char up_flag)
968{ 968{
969 if (keycode > 255 || !x86_keycodes[keycode]) 969 if (keycode > 255 || !x86_keycodes[keycode])
970 return -1; 970 return -1;
971 971
972 switch (keycode) { 972 switch (keycode) {
973 case KEY_PAUSE: 973 case KEY_PAUSE:
@@ -981,7 +981,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
981 case KEY_HANJA: 981 case KEY_HANJA:
982 if (!up_flag) put_queue(vc, 0xf2); 982 if (!up_flag) put_queue(vc, 0xf2);
983 return 0; 983 return 0;
984 } 984 }
985 985
986 if (keycode == KEY_SYSRQ && sysrq_alt) { 986 if (keycode == KEY_SYSRQ && sysrq_alt) {
987 put_queue(vc, 0x54 | up_flag); 987 put_queue(vc, 0x54 | up_flag);
@@ -1104,11 +1104,12 @@ static void kbd_keycode(unsigned int keycode, int down,
1104 else 1104 else
1105 clear_bit(keycode, key_down); 1105 clear_bit(keycode, key_down);
1106 1106
1107 if (rep && (!vc_kbd_mode(kbd, VC_REPEAT) || (tty && 1107 if (rep &&
1108 (!L_ECHO(tty) && tty->driver->chars_in_buffer(tty))))) { 1108 (!vc_kbd_mode(kbd, VC_REPEAT) ||
1109 (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
1109 /* 1110 /*
1110 * Don't repeat a key if the input buffers are not empty and the 1111 * Don't repeat a key if the input buffers are not empty and the
1111 * characters get aren't echoed locally. This makes key repeat 1112 * characters get aren't echoed locally. This makes key repeat
1112 * usable with slow applications and under heavy loads. 1113 * usable with slow applications and under heavy loads.
1113 */ 1114 */
1114 return; 1115 return;
@@ -1130,7 +1131,8 @@ static void kbd_keycode(unsigned int keycode, int down,
1130 type = KTYP(keysym); 1131 type = KTYP(keysym);
1131 1132
1132 if (type < 0xf0) { 1133 if (type < 0xf0) {
1133 if (down && !raw_mode) to_utf8(vc, keysym); 1134 if (down && !raw_mode)
1135 to_utf8(vc, keysym);
1134 return; 1136 return;
1135 } 1137 }
1136 1138
@@ -1154,7 +1156,7 @@ static void kbd_keycode(unsigned int keycode, int down,
1154 kbd->slockstate = 0; 1156 kbd->slockstate = 0;
1155} 1157}
1156 1158
1157static void kbd_event(struct input_handle *handle, unsigned int event_type, 1159static void kbd_event(struct input_handle *handle, unsigned int event_type,
1158 unsigned int event_code, int value) 1160 unsigned int event_code, int value)
1159{ 1161{
1160 if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev)) 1162 if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
@@ -1166,15 +1168,13 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
1166 schedule_console_callback(); 1168 schedule_console_callback();
1167} 1169}
1168 1170
1169static char kbd_name[] = "kbd";
1170
1171/* 1171/*
1172 * When a keyboard (or other input device) is found, the kbd_connect 1172 * When a keyboard (or other input device) is found, the kbd_connect
1173 * function is called. The function then looks at the device, and if it 1173 * function is called. The function then looks at the device, and if it
1174 * likes it, it can open it and get events from it. In this (kbd_connect) 1174 * likes it, it can open it and get events from it. In this (kbd_connect)
1175 * function, we should decide which VT to bind that keyboard to initially. 1175 * function, we should decide which VT to bind that keyboard to initially.
1176 */ 1176 */
1177static struct input_handle *kbd_connect(struct input_handler *handler, 1177static struct input_handle *kbd_connect(struct input_handler *handler,
1178 struct input_dev *dev, 1178 struct input_dev *dev,
1179 struct input_device_id *id) 1179 struct input_device_id *id)
1180{ 1180{
@@ -1182,18 +1182,19 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
1182 int i; 1182 int i;
1183 1183
1184 for (i = KEY_RESERVED; i < BTN_MISC; i++) 1184 for (i = KEY_RESERVED; i < BTN_MISC; i++)
1185 if (test_bit(i, dev->keybit)) break; 1185 if (test_bit(i, dev->keybit))
1186 break;
1186 1187
1187 if ((i == BTN_MISC) && !test_bit(EV_SND, dev->evbit)) 1188 if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
1188 return NULL; 1189 return NULL;
1189 1190
1190 if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) 1191 if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
1191 return NULL; 1192 return NULL;
1192 memset(handle, 0, sizeof(struct input_handle)); 1193 memset(handle, 0, sizeof(struct input_handle));
1193 1194
1194 handle->dev = dev; 1195 handle->dev = dev;
1195 handle->handler = handler; 1196 handle->handler = handler;
1196 handle->name = kbd_name; 1197 handle->name = "kbd";
1197 1198
1198 input_open_device(handle); 1199 input_open_device(handle);
1199 kbd_refresh_leds(handle); 1200 kbd_refresh_leds(handle);
@@ -1212,11 +1213,11 @@ static struct input_device_id kbd_ids[] = {
1212 .flags = INPUT_DEVICE_ID_MATCH_EVBIT, 1213 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1213 .evbit = { BIT(EV_KEY) }, 1214 .evbit = { BIT(EV_KEY) },
1214 }, 1215 },
1215 1216
1216 { 1217 {
1217 .flags = INPUT_DEVICE_ID_MATCH_EVBIT, 1218 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1218 .evbit = { BIT(EV_SND) }, 1219 .evbit = { BIT(EV_SND) },
1219 }, 1220 },
1220 1221
1221 { }, /* Terminating entry */ 1222 { }, /* Terminating entry */
1222}; 1223};
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 60b696e9336b..3738d173f9a6 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -322,7 +322,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
322 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL; 322 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
323 if (get_user(v, ip + 1)) return -EFAULT; 323 if (get_user(v, ip + 1)) return -EFAULT;
324 if (v < 0 || v > KEY_MAX) return -EINVAL; 324 if (v < 0 || v > KEY_MAX) return -EINVAL;
325 if (v >> (dev->keycodesize * 8)) return -EINVAL; 325 if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
326 u = SET_INPUT_KEYCODE(dev, t, v); 326 u = SET_INPUT_KEYCODE(dev, t, v);
327 clear_bit(u, dev->keybit); 327 clear_bit(u, dev->keybit);
328 set_bit(v, dev->keybit); 328 set_bit(v, dev->keybit);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 58728ebaaf80..e5a31e55d3e2 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -249,9 +249,6 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
249 249
250int iforce_get_id_packet(struct iforce *iforce, char *packet) 250int iforce_get_id_packet(struct iforce *iforce, char *packet)
251{ 251{
252 DECLARE_WAITQUEUE(wait, current);
253 int timeout = HZ; /* 1 second */
254
255 switch (iforce->bus) { 252 switch (iforce->bus) {
256 253
257 case IFORCE_USB: 254 case IFORCE_USB:
@@ -260,22 +257,13 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
260 iforce->cr.bRequest = packet[0]; 257 iforce->cr.bRequest = packet[0];
261 iforce->ctrl->dev = iforce->usbdev; 258 iforce->ctrl->dev = iforce->usbdev;
262 259
263 set_current_state(TASK_INTERRUPTIBLE); 260 if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC))
264 add_wait_queue(&iforce->wait, &wait);
265
266 if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) {
267 set_current_state(TASK_RUNNING);
268 remove_wait_queue(&iforce->wait, &wait);
269 return -1; 261 return -1;
270 }
271 262
272 while (timeout && iforce->ctrl->status == -EINPROGRESS) 263 wait_event_interruptible_timeout(iforce->wait,
273 timeout = schedule_timeout(timeout); 264 iforce->ctrl->status != -EINPROGRESS, HZ);
274 265
275 set_current_state(TASK_RUNNING); 266 if (iforce->ctrl->status != -EINPROGRESS) {
276 remove_wait_queue(&iforce->wait, &wait);
277
278 if (!timeout) {
279 usb_unlink_urb(iforce->ctrl); 267 usb_unlink_urb(iforce->ctrl);
280 return -1; 268 return -1;
281 } 269 }
@@ -290,16 +278,10 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
290 iforce->expect_packet = FF_CMD_QUERY; 278 iforce->expect_packet = FF_CMD_QUERY;
291 iforce_send_packet(iforce, FF_CMD_QUERY, packet); 279 iforce_send_packet(iforce, FF_CMD_QUERY, packet);
292 280
293 set_current_state(TASK_INTERRUPTIBLE); 281 wait_event_interruptible_timeout(iforce->wait,
294 add_wait_queue(&iforce->wait, &wait); 282 !iforce->expect_packet, HZ);
295
296 while (timeout && iforce->expect_packet)
297 timeout = schedule_timeout(timeout);
298
299 set_current_state(TASK_RUNNING);
300 remove_wait_queue(&iforce->wait, &wait);
301 283
302 if (!timeout) { 284 if (iforce->expect_packet) {
303 iforce->expect_packet = 0; 285 iforce->expect_packet = 0;
304 return -1; 286 return -1;
305 } 287 }
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 6369a24684fe..58600f91eff5 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -95,6 +95,7 @@ static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
95 goto exit; 95 goto exit;
96 } 96 }
97 97
98 wake_up(&iforce->wait);
98 iforce_process_packet(iforce, 99 iforce_process_packet(iforce,
99 (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs); 100 (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
100 101
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 4d4985b59abf..1ad8c2ee7dbf 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -208,6 +208,7 @@ struct atkbd {
208 unsigned char resend; 208 unsigned char resend;
209 unsigned char release; 209 unsigned char release;
210 unsigned char bat_xl; 210 unsigned char bat_xl;
211 unsigned char err_xl;
211 unsigned int last; 212 unsigned int last;
212 unsigned long time; 213 unsigned long time;
213}; 214};
@@ -296,15 +297,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
296 if (atkbd->emul || 297 if (atkbd->emul ||
297 !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 || 298 !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
298 code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA || 299 code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
299 code == ATKBD_RET_ERR || 300 (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
300 (code == ATKBD_RET_BAT && !atkbd->bat_xl))) { 301 (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
301 atkbd->release = code >> 7; 302 atkbd->release = code >> 7;
302 code &= 0x7f; 303 code &= 0x7f;
303 } 304 }
304 305
305 if (!atkbd->emul && 306 if (!atkbd->emul) {
306 (code & 0x7f) == (ATKBD_RET_BAT & 0x7f)) 307 if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
307 atkbd->bat_xl = !atkbd->release; 308 atkbd->bat_xl = !atkbd->release;
309 if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
310 atkbd->err_xl = !atkbd->release;
311 }
308 } 312 }
309 313
310 switch (code) { 314 switch (code) {
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 596964ceb96d..4bae5d89348d 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -44,7 +44,7 @@ MODULE_DESCRIPTION(DRIVER_DESC);
44MODULE_LICENSE("GPL"); 44MODULE_LICENSE("GPL");
45 45
46static unsigned char sunkbd_keycode[128] = { 46static unsigned char sunkbd_keycode[128] = {
47 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64, 0, 47 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64,112,
48 65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3, 48 65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3,
49 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 41, 14,110,113, 98, 55, 49 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 41, 14,110,113, 98, 55,
50 116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 50 116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index c4909b49337d..82b330bbf068 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
15obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o 15obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
16obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o 16obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
17 17
18psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o 18psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 0d68e5e0182a..b20783f9748a 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -170,7 +170,7 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
170 input_report_key(dev, BTN_TOOL_FINGER, z > 0); 170 input_report_key(dev, BTN_TOOL_FINGER, z > 0);
171 171
172 if (priv->i->flags & ALPS_WHEEL) 172 if (priv->i->flags & ALPS_WHEEL)
173 input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); 173 input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
174 174
175 if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { 175 if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
176 input_report_key(dev, BTN_FORWARD, forward); 176 input_report_key(dev, BTN_FORWARD, forward);
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 48d2b20d2642..7df96525222e 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -150,12 +150,12 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscr
150 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); 150 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
151} 151}
152 152
153static ssize_t psmouse_attr_show_smartscroll(struct psmouse *psmouse, char *buf) 153static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf)
154{ 154{
155 return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0); 155 return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0);
156} 156}
157 157
158static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char *buf, size_t count) 158static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count)
159{ 159{
160 unsigned long value; 160 unsigned long value;
161 char *rest; 161 char *rest;
@@ -169,7 +169,8 @@ static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char
169 return count; 169 return count;
170} 170}
171 171
172PSMOUSE_DEFINE_ATTR(smartscroll); 172PSMOUSE_DEFINE_ATTR(smartscroll, S_IWUSR | S_IRUGO, NULL,
173 ps2pp_attr_show_smartscroll, ps2pp_attr_set_smartscroll);
173 174
174/* 175/*
175 * Support 800 dpi resolution _only_ if the user wants it (there are good 176 * Support 800 dpi resolution _only_ if the user wants it (there are good
@@ -194,7 +195,7 @@ static void ps2pp_set_resolution(struct psmouse *psmouse, unsigned int resolutio
194 195
195static void ps2pp_disconnect(struct psmouse *psmouse) 196static void ps2pp_disconnect(struct psmouse *psmouse)
196{ 197{
197 device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll); 198 device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr);
198} 199}
199 200
200static struct ps2pp_info *get_model_info(unsigned char model) 201static struct ps2pp_info *get_model_info(unsigned char model)
@@ -222,6 +223,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
222 { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, 223 { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
223 { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, 224 { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
224 { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, 225 { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
226 { 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
225 { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, 227 { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
226 { 96, 0, 0 }, 228 { 96, 0, 0 },
227 { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL }, 229 { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
@@ -379,7 +381,8 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
379 psmouse->set_resolution = ps2pp_set_resolution; 381 psmouse->set_resolution = ps2pp_set_resolution;
380 psmouse->disconnect = ps2pp_disconnect; 382 psmouse->disconnect = ps2pp_disconnect;
381 383
382 device_create_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll); 384 device_create_file(&psmouse->ps2dev.serio->dev,
385 &psmouse_attr_smartscroll.dattr);
383 } 386 }
384 } 387 }
385 388
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 12bdd3eff923..af24313ff5bb 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -25,6 +25,7 @@
25#include "logips2pp.h" 25#include "logips2pp.h"
26#include "alps.h" 26#include "alps.h"
27#include "lifebook.h" 27#include "lifebook.h"
28#include "trackpoint.h"
28 29
29#define DRIVER_DESC "PS/2 mouse driver" 30#define DRIVER_DESC "PS/2 mouse driver"
30 31
@@ -57,10 +58,30 @@ static unsigned int psmouse_resetafter;
57module_param_named(resetafter, psmouse_resetafter, uint, 0644); 58module_param_named(resetafter, psmouse_resetafter, uint, 0644);
58MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); 59MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
59 60
60PSMOUSE_DEFINE_ATTR(protocol); 61PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
61PSMOUSE_DEFINE_ATTR(rate); 62 NULL,
62PSMOUSE_DEFINE_ATTR(resolution); 63 psmouse_attr_show_protocol, psmouse_attr_set_protocol);
63PSMOUSE_DEFINE_ATTR(resetafter); 64PSMOUSE_DEFINE_ATTR(rate, S_IWUSR | S_IRUGO,
65 (void *) offsetof(struct psmouse, rate),
66 psmouse_show_int_attr, psmouse_attr_set_rate);
67PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
68 (void *) offsetof(struct psmouse, resolution),
69 psmouse_show_int_attr, psmouse_attr_set_resolution);
70PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
71 (void *) offsetof(struct psmouse, resetafter),
72 psmouse_show_int_attr, psmouse_set_int_attr);
73
74static struct attribute *psmouse_attributes[] = {
75 &psmouse_attr_protocol.dattr.attr,
76 &psmouse_attr_rate.dattr.attr,
77 &psmouse_attr_resolution.dattr.attr,
78 &psmouse_attr_resetafter.dattr.attr,
79 NULL
80};
81
82static struct attribute_group psmouse_attribute_group = {
83 .attrs = psmouse_attributes,
84};
64 85
65__obsolete_setup("psmouse_noext"); 86__obsolete_setup("psmouse_noext");
66__obsolete_setup("psmouse_resolution="); 87__obsolete_setup("psmouse_resolution=");
@@ -520,6 +541,12 @@ static int psmouse_extensions(struct psmouse *psmouse,
520 return PSMOUSE_IMPS; 541 return PSMOUSE_IMPS;
521 542
522/* 543/*
544 * Try to initialize the IBM TrackPoint
545 */
546 if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
547 return PSMOUSE_TRACKPOINT;
548
549/*
523 * Okay, all failed, we have a standard mouse here. The number of the buttons 550 * Okay, all failed, we have a standard mouse here. The number of the buttons
524 * is still a question, though. We assume 3. 551 * is still a question, though. We assume 3.
525 */ 552 */
@@ -600,6 +627,12 @@ static struct psmouse_protocol psmouse_protocols[] = {
600 .init = lifebook_init, 627 .init = lifebook_init,
601 }, 628 },
602 { 629 {
630 .type = PSMOUSE_TRACKPOINT,
631 .name = "TPPS/2",
632 .alias = "trackpoint",
633 .detect = trackpoint_detect,
634 },
635 {
603 .type = PSMOUSE_AUTO, 636 .type = PSMOUSE_AUTO,
604 .name = "auto", 637 .name = "auto",
605 .alias = "any", 638 .alias = "any",
@@ -787,10 +820,7 @@ static void psmouse_disconnect(struct serio *serio)
787 820
788 psmouse = serio_get_drvdata(serio); 821 psmouse = serio_get_drvdata(serio);
789 822
790 device_remove_file(&serio->dev, &psmouse_attr_protocol); 823 sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
791 device_remove_file(&serio->dev, &psmouse_attr_rate);
792 device_remove_file(&serio->dev, &psmouse_attr_resolution);
793 device_remove_file(&serio->dev, &psmouse_attr_resetafter);
794 824
795 down(&psmouse_sem); 825 down(&psmouse_sem);
796 826
@@ -927,10 +957,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
927 if (parent && parent->pt_activate) 957 if (parent && parent->pt_activate)
928 parent->pt_activate(parent); 958 parent->pt_activate(parent);
929 959
930 device_create_file(&serio->dev, &psmouse_attr_protocol); 960 sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
931 device_create_file(&serio->dev, &psmouse_attr_rate);
932 device_create_file(&serio->dev, &psmouse_attr_resolution);
933 device_create_file(&serio->dev, &psmouse_attr_resetafter);
934 961
935 psmouse_activate(psmouse); 962 psmouse_activate(psmouse);
936 963
@@ -1027,10 +1054,12 @@ static struct serio_driver psmouse_drv = {
1027 .cleanup = psmouse_cleanup, 1054 .cleanup = psmouse_cleanup,
1028}; 1055};
1029 1056
1030ssize_t psmouse_attr_show_helper(struct device *dev, char *buf, 1057ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *devattr,
1031 ssize_t (*handler)(struct psmouse *, char *)) 1058 char *buf)
1032{ 1059{
1033 struct serio *serio = to_serio_port(dev); 1060 struct serio *serio = to_serio_port(dev);
1061 struct psmouse_attribute *attr = to_psmouse_attr(devattr);
1062 struct psmouse *psmouse;
1034 int retval; 1063 int retval;
1035 1064
1036 retval = serio_pin_driver(serio); 1065 retval = serio_pin_driver(serio);
@@ -1042,19 +1071,21 @@ ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
1042 goto out; 1071 goto out;
1043 } 1072 }
1044 1073
1045 retval = handler(serio_get_drvdata(serio), buf); 1074 psmouse = serio_get_drvdata(serio);
1075
1076 retval = attr->show(psmouse, attr->data, buf);
1046 1077
1047out: 1078out:
1048 serio_unpin_driver(serio); 1079 serio_unpin_driver(serio);
1049 return retval; 1080 return retval;
1050} 1081}
1051 1082
1052ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count, 1083ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr,
1053 ssize_t (*handler)(struct psmouse *, const char *, size_t)) 1084 const char *buf, size_t count)
1054{ 1085{
1055 struct serio *serio = to_serio_port(dev); 1086 struct serio *serio = to_serio_port(dev);
1056 struct psmouse *psmouse = serio_get_drvdata(serio); 1087 struct psmouse_attribute *attr = to_psmouse_attr(devattr);
1057 struct psmouse *parent = NULL; 1088 struct psmouse *psmouse, *parent = NULL;
1058 int retval; 1089 int retval;
1059 1090
1060 retval = serio_pin_driver(serio); 1091 retval = serio_pin_driver(serio);
@@ -1070,6 +1101,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
1070 if (retval) 1101 if (retval)
1071 goto out_unpin; 1102 goto out_unpin;
1072 1103
1104 psmouse = serio_get_drvdata(serio);
1105
1073 if (psmouse->state == PSMOUSE_IGNORE) { 1106 if (psmouse->state == PSMOUSE_IGNORE) {
1074 retval = -ENODEV; 1107 retval = -ENODEV;
1075 goto out_up; 1108 goto out_up;
@@ -1082,7 +1115,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
1082 1115
1083 psmouse_deactivate(psmouse); 1116 psmouse_deactivate(psmouse);
1084 1117
1085 retval = handler(psmouse, buf, count); 1118 retval = attr->set(psmouse, attr->data, buf, count);
1086 1119
1087 if (retval != -ENODEV) 1120 if (retval != -ENODEV)
1088 psmouse_activate(psmouse); 1121 psmouse_activate(psmouse);
@@ -1097,12 +1130,34 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
1097 return retval; 1130 return retval;
1098} 1131}
1099 1132
1100static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf) 1133static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf)
1134{
1135 unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
1136
1137 return sprintf(buf, "%lu\n", *field);
1138}
1139
1140static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
1141{
1142 unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
1143 unsigned long value;
1144 char *rest;
1145
1146 value = simple_strtoul(buf, &rest, 10);
1147 if (*rest)
1148 return -EINVAL;
1149
1150 *field = value;
1151
1152 return count;
1153}
1154
1155static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf)
1101{ 1156{
1102 return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name); 1157 return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);
1103} 1158}
1104 1159
1105static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count) 1160static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count)
1106{ 1161{
1107 struct serio *serio = psmouse->ps2dev.serio; 1162 struct serio *serio = psmouse->ps2dev.serio;
1108 struct psmouse *parent = NULL; 1163 struct psmouse *parent = NULL;
@@ -1166,12 +1221,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu
1166 return count; 1221 return count;
1167} 1222}
1168 1223
1169static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) 1224static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
1170{
1171 return sprintf(buf, "%d\n", psmouse->rate);
1172}
1173
1174static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, size_t count)
1175{ 1225{
1176 unsigned long value; 1226 unsigned long value;
1177 char *rest; 1227 char *rest;
@@ -1184,12 +1234,7 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, s
1184 return count; 1234 return count;
1185} 1235}
1186 1236
1187static ssize_t psmouse_attr_show_resolution(struct psmouse *psmouse, char *buf) 1237static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
1188{
1189 return sprintf(buf, "%d\n", psmouse->resolution);
1190}
1191
1192static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *buf, size_t count)
1193{ 1238{
1194 unsigned long value; 1239 unsigned long value;
1195 char *rest; 1240 char *rest;
@@ -1202,23 +1247,6 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *
1202 return count; 1247 return count;
1203} 1248}
1204 1249
1205static ssize_t psmouse_attr_show_resetafter(struct psmouse *psmouse, char *buf)
1206{
1207 return sprintf(buf, "%d\n", psmouse->resetafter);
1208}
1209
1210static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *buf, size_t count)
1211{
1212 unsigned long value;
1213 char *rest;
1214
1215 value = simple_strtoul(buf, &rest, 10);
1216 if (*rest)
1217 return -EINVAL;
1218
1219 psmouse->resetafter = value;
1220 return count;
1221}
1222 1250
1223static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) 1251static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
1224{ 1252{
@@ -1234,7 +1262,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
1234 1262
1235 *((unsigned int *)kp->arg) = proto->type; 1263 *((unsigned int *)kp->arg) = proto->type;
1236 1264
1237 return 0; \ 1265 return 0;
1238} 1266}
1239 1267
1240static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) 1268static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 86691cf43433..45d2bd774f00 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -78,6 +78,7 @@ enum psmouse_type {
78 PSMOUSE_SYNAPTICS, 78 PSMOUSE_SYNAPTICS,
79 PSMOUSE_ALPS, 79 PSMOUSE_ALPS,
80 PSMOUSE_LIFEBOOK, 80 PSMOUSE_LIFEBOOK,
81 PSMOUSE_TRACKPOINT,
81 PSMOUSE_AUTO /* This one should always be last */ 82 PSMOUSE_AUTO /* This one should always be last */
82}; 83};
83 84
@@ -85,24 +86,37 @@ int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
85int psmouse_reset(struct psmouse *psmouse); 86int psmouse_reset(struct psmouse *psmouse);
86void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); 87void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
87 88
88ssize_t psmouse_attr_show_helper(struct device *dev, char *buf, 89
89 ssize_t (*handler)(struct psmouse *, char *)); 90struct psmouse_attribute {
90ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count, 91 struct device_attribute dattr;
91 ssize_t (*handler)(struct psmouse *, const char *, size_t)); 92 void *data;
92 93 ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf);
93#define PSMOUSE_DEFINE_ATTR(_name) \ 94 ssize_t (*set)(struct psmouse *psmouse, void *data,
94static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *); \ 95 const char *buf, size_t count);
95static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\ 96};
96static ssize_t psmouse_do_show_##_name(struct device *d, struct device_attribute *attr, char *b) \ 97#define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr)
97{ \ 98
98 return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name); \ 99ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *attr,
99} \ 100 char *buf);
100static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)\ 101ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr,
101{ \ 102 const char *buf, size_t count);
102 return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ 103
103} \ 104#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \
104static struct device_attribute psmouse_attr_##_name = \ 105static ssize_t _show(struct psmouse *, void *data, char *); \
105 __ATTR(_name, S_IWUSR | S_IRUGO, \ 106static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \
106 psmouse_do_show_##_name, psmouse_do_set_##_name); 107static struct psmouse_attribute psmouse_attr_##_name = { \
108 .dattr = { \
109 .attr = { \
110 .name = __stringify(_name), \
111 .mode = _mode, \
112 .owner = THIS_MODULE, \
113 }, \
114 .show = psmouse_attr_show_helper, \
115 .store = psmouse_attr_set_helper, \
116 }, \
117 .data = _data, \
118 .show = _show, \
119 .set = _set, \
120}
107 121
108#endif /* _PSMOUSE_H */ 122#endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
new file mode 100644
index 000000000000..b4898d8a68e2
--- /dev/null
+++ b/drivers/input/mouse/trackpoint.c
@@ -0,0 +1,304 @@
1/*
2 * Stephen Evanchik <evanchsa@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published by
6 * the Free Software Foundation.
7 *
8 * Trademarks are the property of their respective owners.
9 */
10
11#include <linux/delay.h>
12#include <linux/serio.h>
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/input.h>
16#include <linux/libps2.h>
17#include <linux/proc_fs.h>
18#include <asm/uaccess.h>
19#include "psmouse.h"
20#include "trackpoint.h"
21
22/*
23 * Device IO: read, write and toggle bit
24 */
25static int trackpoint_read(struct ps2dev *ps2dev, unsigned char loc, unsigned char *results)
26{
27 if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
28 ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc))) {
29 return -1;
30 }
31
32 return 0;
33}
34
35static int trackpoint_write(struct ps2dev *ps2dev, unsigned char loc, unsigned char val)
36{
37 if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
38 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM)) ||
39 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
40 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, val))) {
41 return -1;
42 }
43
44 return 0;
45}
46
47static int trackpoint_toggle_bit(struct ps2dev *ps2dev, unsigned char loc, unsigned char mask)
48{
49 /* Bad things will happen if the loc param isn't in this range */
50 if (loc < 0x20 || loc >= 0x2F)
51 return -1;
52
53 if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
54 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_TOGGLE)) ||
55 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
56 ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, mask))) {
57 return -1;
58 }
59
60 return 0;
61}
62
63
64/*
65 * Trackpoint-specific attributes
66 */
67struct trackpoint_attr_data {
68 size_t field_offset;
69 unsigned char command;
70 unsigned char mask;
71};
72
73static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf)
74{
75 struct trackpoint_data *tp = psmouse->private;
76 struct trackpoint_attr_data *attr = data;
77 unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
78
79 return sprintf(buf, "%u\n", *field);
80}
81
82static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
83 const char *buf, size_t count)
84{
85 struct trackpoint_data *tp = psmouse->private;
86 struct trackpoint_attr_data *attr = data;
87 unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
88 unsigned long value;
89 char *rest;
90
91 value = simple_strtoul(buf, &rest, 10);
92 if (*rest || value > 255)
93 return -EINVAL;
94
95 *field = value;
96 trackpoint_write(&psmouse->ps2dev, attr->command, value);
97
98 return count;
99}
100
101#define TRACKPOINT_INT_ATTR(_name, _command) \
102 static struct trackpoint_attr_data trackpoint_attr_##_name = { \
103 .field_offset = offsetof(struct trackpoint_data, _name), \
104 .command = _command, \
105 }; \
106 PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
107 &trackpoint_attr_##_name, \
108 trackpoint_show_int_attr, trackpoint_set_int_attr)
109
110static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
111 const char *buf, size_t count)
112{
113 struct trackpoint_data *tp = psmouse->private;
114 struct trackpoint_attr_data *attr = data;
115 unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
116 unsigned long value;
117 char *rest;
118
119 value = simple_strtoul(buf, &rest, 10);
120 if (*rest || value > 1)
121 return -EINVAL;
122
123 if (*field != value) {
124 *field = value;
125 trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask);
126 }
127
128 return count;
129}
130
131
132#define TRACKPOINT_BIT_ATTR(_name, _command, _mask) \
133 static struct trackpoint_attr_data trackpoint_attr_##_name = { \
134 .field_offset = offsetof(struct trackpoint_data, _name), \
135 .command = _command, \
136 .mask = _mask, \
137 }; \
138 PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
139 &trackpoint_attr_##_name, \
140 trackpoint_show_int_attr, trackpoint_set_bit_attr)
141
142TRACKPOINT_INT_ATTR(sensitivity, TP_SENS);
143TRACKPOINT_INT_ATTR(speed, TP_SPEED);
144TRACKPOINT_INT_ATTR(inertia, TP_INERTIA);
145TRACKPOINT_INT_ATTR(reach, TP_REACH);
146TRACKPOINT_INT_ATTR(draghys, TP_DRAGHYS);
147TRACKPOINT_INT_ATTR(mindrag, TP_MINDRAG);
148TRACKPOINT_INT_ATTR(thresh, TP_THRESH);
149TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH);
150TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME);
151TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV);
152
153TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON);
154TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
155TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
156
157static struct attribute *trackpoint_attrs[] = {
158 &psmouse_attr_sensitivity.dattr.attr,
159 &psmouse_attr_speed.dattr.attr,
160 &psmouse_attr_inertia.dattr.attr,
161 &psmouse_attr_reach.dattr.attr,
162 &psmouse_attr_draghys.dattr.attr,
163 &psmouse_attr_mindrag.dattr.attr,
164 &psmouse_attr_thresh.dattr.attr,
165 &psmouse_attr_upthresh.dattr.attr,
166 &psmouse_attr_ztime.dattr.attr,
167 &psmouse_attr_jenks.dattr.attr,
168 &psmouse_attr_press_to_select.dattr.attr,
169 &psmouse_attr_skipback.dattr.attr,
170 &psmouse_attr_ext_dev.dattr.attr,
171 NULL
172};
173
174static struct attribute_group trackpoint_attr_group = {
175 .attrs = trackpoint_attrs,
176};
177
178static void trackpoint_disconnect(struct psmouse *psmouse)
179{
180 sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
181
182 kfree(psmouse->private);
183 psmouse->private = NULL;
184}
185
186static int trackpoint_sync(struct psmouse *psmouse)
187{
188 unsigned char toggle;
189 struct trackpoint_data *tp = psmouse->private;
190
191 if (!tp)
192 return -1;
193
194 /* Disable features that may make device unusable with this driver */
195 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
196 if (toggle & TP_MASK_TWOHAND)
197 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, TP_MASK_TWOHAND);
198
199 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, &toggle);
200 if (toggle & TP_MASK_SOURCE_TAG)
201 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, TP_MASK_SOURCE_TAG);
202
203 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_MB, &toggle);
204 if (toggle & TP_MASK_MB)
205 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_MB, TP_MASK_MB);
206
207 /* Push the config to the device */
208 trackpoint_write(&psmouse->ps2dev, TP_SENS, tp->sensitivity);
209 trackpoint_write(&psmouse->ps2dev, TP_INERTIA, tp->inertia);
210 trackpoint_write(&psmouse->ps2dev, TP_SPEED, tp->speed);
211
212 trackpoint_write(&psmouse->ps2dev, TP_REACH, tp->reach);
213 trackpoint_write(&psmouse->ps2dev, TP_DRAGHYS, tp->draghys);
214 trackpoint_write(&psmouse->ps2dev, TP_MINDRAG, tp->mindrag);
215
216 trackpoint_write(&psmouse->ps2dev, TP_THRESH, tp->thresh);
217 trackpoint_write(&psmouse->ps2dev, TP_UP_THRESH, tp->upthresh);
218
219 trackpoint_write(&psmouse->ps2dev, TP_Z_TIME, tp->ztime);
220 trackpoint_write(&psmouse->ps2dev, TP_JENKS_CURV, tp->jenks);
221
222 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_PTSON, &toggle);
223 if (((toggle & TP_MASK_PTSON) == TP_MASK_PTSON) != tp->press_to_select)
224 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_PTSON, TP_MASK_PTSON);
225
226 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, &toggle);
227 if (((toggle & TP_MASK_SKIPBACK) == TP_MASK_SKIPBACK) != tp->skipback)
228 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
229
230 trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, &toggle);
231 if (((toggle & TP_MASK_EXT_DEV) == TP_MASK_EXT_DEV) != tp->ext_dev)
232 trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
233
234 return 0;
235}
236
237static void trackpoint_defaults(struct trackpoint_data *tp)
238{
239 tp->press_to_select = TP_DEF_PTSON;
240 tp->sensitivity = TP_DEF_SENS;
241 tp->speed = TP_DEF_SPEED;
242 tp->reach = TP_DEF_REACH;
243
244 tp->draghys = TP_DEF_DRAGHYS;
245 tp->mindrag = TP_DEF_MINDRAG;
246
247 tp->thresh = TP_DEF_THRESH;
248 tp->upthresh = TP_DEF_UP_THRESH;
249
250 tp->ztime = TP_DEF_Z_TIME;
251 tp->jenks = TP_DEF_JENKS_CURV;
252
253 tp->inertia = TP_DEF_INERTIA;
254 tp->skipback = TP_DEF_SKIPBACK;
255 tp->ext_dev = TP_DEF_EXT_DEV;
256}
257
258int trackpoint_detect(struct psmouse *psmouse, int set_properties)
259{
260 struct trackpoint_data *priv;
261 struct ps2dev *ps2dev = &psmouse->ps2dev;
262 unsigned char firmware_id;
263 unsigned char button_info;
264 unsigned char param[2];
265
266 param[0] = param[1] = 0;
267
268 if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
269 return -1;
270
271 if (param[0] != TP_MAGIC_IDENT)
272 return -1;
273
274 if (!set_properties)
275 return 0;
276
277 firmware_id = param[1];
278
279 if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
280 printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
281 button_info = 0;
282 }
283
284 psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL);
285 if (!priv)
286 return -1;
287
288 psmouse->vendor = "IBM";
289 psmouse->name = "TrackPoint";
290
291 psmouse->reconnect = trackpoint_sync;
292 psmouse->disconnect = trackpoint_disconnect;
293
294 trackpoint_defaults(priv);
295 trackpoint_sync(psmouse);
296
297 sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
298
299 printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
300 firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f);
301
302 return 0;
303}
304
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
new file mode 100644
index 000000000000..9857d8b6ad66
--- /dev/null
+++ b/drivers/input/mouse/trackpoint.h
@@ -0,0 +1,147 @@
1/*
2 * IBM TrackPoint PS/2 mouse driver
3 *
4 * Stephen Evanchik <evanchsa@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#ifndef _TRACKPOINT_H
12#define _TRACKPOINT_H
13
14/*
15 * These constants are from the TrackPoint System
16 * Engineering documentation Version 4 from IBM Watson
17 * research:
18 * http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
19 */
20
21#define TP_COMMAND 0xE2 /* Commands start with this */
22
23#define TP_READ_ID 0xE1 /* Sent for device identification */
24#define TP_MAGIC_IDENT 0x01 /* Sent after a TP_READ_ID followed */
25 /* by the firmware ID */
26
27
28/*
29 * Commands
30 */
31#define TP_RECALIB 0x51 /* Recalibrate */
32#define TP_POWER_DOWN 0x44 /* Can only be undone through HW reset */
33#define TP_EXT_DEV 0x21 /* Determines if external device is connected (RO) */
34#define TP_EXT_BTN 0x4B /* Read extended button status */
35#define TP_POR 0x7F /* Execute Power on Reset */
36#define TP_POR_RESULTS 0x25 /* Read Power on Self test results */
37#define TP_DISABLE_EXT 0x40 /* Disable external pointing device */
38#define TP_ENABLE_EXT 0x41 /* Enable external pointing device */
39
40/*
41 * Mode manipulation
42 */
43#define TP_SET_SOFT_TRANS 0x4E /* Set mode */
44#define TP_CANCEL_SOFT_TRANS 0xB9 /* Cancel mode */
45#define TP_SET_HARD_TRANS 0x45 /* Mode can only be set */
46
47
48/*
49 * Register oriented commands/properties
50 */
51#define TP_WRITE_MEM 0x81
52#define TP_READ_MEM 0x80 /* Not used in this implementation */
53
54/*
55* RAM Locations for properties
56 */
57#define TP_SENS 0x4A /* Sensitivity */
58#define TP_MB 0x4C /* Read Middle Button Status (RO) */
59#define TP_INERTIA 0x4D /* Negative Inertia */
60#define TP_SPEED 0x60 /* Speed of TP Cursor */
61#define TP_REACH 0x57 /* Backup for Z-axis press */
62#define TP_DRAGHYS 0x58 /* Drag Hysteresis */
63 /* (how hard it is to drag */
64 /* with Z-axis pressed) */
65
66#define TP_MINDRAG 0x59 /* Minimum amount of force needed */
67 /* to trigger dragging */
68
69#define TP_THRESH 0x5C /* Minimum value for a Z-axis press */
70#define TP_UP_THRESH 0x5A /* Used to generate a 'click' on Z-axis */
71#define TP_Z_TIME 0x5E /* How sharp of a press */
72#define TP_JENKS_CURV 0x5D /* Minimum curvature for double click */
73
74/*
75 * Toggling Flag bits
76 */
77#define TP_TOGGLE 0x47 /* Toggle command */
78
79#define TP_TOGGLE_MB 0x23 /* Disable/Enable Middle Button */
80#define TP_MASK_MB 0x01
81#define TP_TOGGLE_EXT_DEV 0x23 /* Toggle external device */
82#define TP_MASK_EXT_DEV 0x02
83#define TP_TOGGLE_DRIFT 0x23 /* Drift Correction */
84#define TP_MASK_DRIFT 0x80
85#define TP_TOGGLE_BURST 0x28 /* Burst Mode */
86#define TP_MASK_BURST 0x80
87#define TP_TOGGLE_PTSON 0x2C /* Press to Select */
88#define TP_MASK_PTSON 0x01
89#define TP_TOGGLE_HARD_TRANS 0x2C /* Alternate method to set Hard Transparency */
90#define TP_MASK_HARD_TRANS 0x80
91#define TP_TOGGLE_TWOHAND 0x2D /* Two handed */
92#define TP_MASK_TWOHAND 0x01
93#define TP_TOGGLE_STICKY_TWO 0x2D /* Sticky two handed */
94#define TP_MASK_STICKY_TWO 0x04
95#define TP_TOGGLE_SKIPBACK 0x2D /* Suppress movement after drag release */
96#define TP_MASK_SKIPBACK 0x08
97#define TP_TOGGLE_SOURCE_TAG 0x20 /* Bit 3 of the first packet will be set to
98 to the origin of the packet (external or TP) */
99#define TP_MASK_SOURCE_TAG 0x80
100#define TP_TOGGLE_EXT_TAG 0x22 /* Bit 3 of the first packet coming from the
101 external device will be forced to 1 */
102#define TP_MASK_EXT_TAG 0x04
103
104
105/* Power on Self Test Results */
106#define TP_POR_SUCCESS 0x3B
107
108/*
109 * Default power on values
110 */
111#define TP_DEF_SENS 0x80
112#define TP_DEF_INERTIA 0x06
113#define TP_DEF_SPEED 0x61
114#define TP_DEF_REACH 0x0A
115
116#define TP_DEF_DRAGHYS 0xFF
117#define TP_DEF_MINDRAG 0x14
118
119#define TP_DEF_THRESH 0x08
120#define TP_DEF_UP_THRESH 0xFF
121#define TP_DEF_Z_TIME 0x26
122#define TP_DEF_JENKS_CURV 0x87
123
124/* Toggles */
125#define TP_DEF_MB 0x00
126#define TP_DEF_PTSON 0x00
127#define TP_DEF_SKIPBACK 0x00
128#define TP_DEF_EXT_DEV 0x01
129
130#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd))
131
132struct trackpoint_data
133{
134 unsigned char sensitivity, speed, inertia, reach;
135 unsigned char draghys, mindrag;
136 unsigned char thresh, upthresh;
137 unsigned char ztime, jenks;
138
139 unsigned char press_to_select;
140 unsigned char skipback;
141
142 unsigned char ext_dev;
143};
144
145extern int trackpoint_detect(struct psmouse *psmouse, int set_properties);
146
147#endif /* _TRACKPOINT_H */
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index c9e633d21d90..9a9221644250 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -69,16 +69,16 @@ static inline int i8042_platform_init(void)
69 */ 69 */
70#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64) 70#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64)
71 if (!request_region(I8042_DATA_REG, 16, "i8042")) 71 if (!request_region(I8042_DATA_REG, 16, "i8042"))
72 return -1; 72 return -EBUSY;
73#endif 73#endif
74 74
75 i8042_reset = 1; 75 i8042_reset = 1;
76 76
77#if defined(CONFIG_PPC64) 77#if defined(CONFIG_PPC64)
78 if (check_legacy_ioport(I8042_DATA_REG)) 78 if (check_legacy_ioport(I8042_DATA_REG))
79 return -1; 79 return -EBUSY;
80 if (!request_region(I8042_DATA_REG, 16, "i8042")) 80 if (!request_region(I8042_DATA_REG, 16, "i8042"))
81 return -1; 81 return -EBUSY;
82#endif 82#endif
83 return 0; 83 return 0;
84} 84}
diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h
index 863b9c95fbb8..ee1ad27d6ed0 100644
--- a/drivers/input/serio/i8042-ip22io.h
+++ b/drivers/input/serio/i8042-ip22io.h
@@ -58,7 +58,7 @@ static inline int i8042_platform_init(void)
58#if 0 58#if 0
59 /* XXX sgi_kh is a virtual address */ 59 /* XXX sgi_kh is a virtual address */
60 if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042")) 60 if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042"))
61 return 1; 61 return -EBUSY;
62#endif 62#endif
63 63
64 i8042_reset = 1; 64 i8042_reset = 1;
diff --git a/drivers/input/serio/i8042-jazzio.h b/drivers/input/serio/i8042-jazzio.h
index 5c20ab131488..13fd7108eb28 100644
--- a/drivers/input/serio/i8042-jazzio.h
+++ b/drivers/input/serio/i8042-jazzio.h
@@ -53,7 +53,7 @@ static inline int i8042_platform_init(void)
53#if 0 53#if 0
54 /* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */ 54 /* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */
55 if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042")) 55 if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042"))
56 return 1; 56 return -EBUSY;
57#endif 57#endif
58 58
59 return 0; 59 return 0;
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index da2a19812485..ed9446f6d7e3 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -48,10 +48,10 @@ static inline void i8042_write_command(int val)
48#define OBP_PS2MS_NAME1 "kdmouse" 48#define OBP_PS2MS_NAME1 "kdmouse"
49#define OBP_PS2MS_NAME2 "mouse" 49#define OBP_PS2MS_NAME2 "mouse"
50 50
51static int i8042_platform_init(void) 51static int __init i8042_platform_init(void)
52{ 52{
53#ifndef CONFIG_PCI 53#ifndef CONFIG_PCI
54 return -1; 54 return -ENODEV;
55#else 55#else
56 char prop[128]; 56 char prop[128];
57 int len; 57 int len;
@@ -59,14 +59,14 @@ static int i8042_platform_init(void)
59 len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); 59 len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
60 if (len < 0) { 60 if (len < 0) {
61 printk("i8042: Cannot get name property of root OBP node.\n"); 61 printk("i8042: Cannot get name property of root OBP node.\n");
62 return -1; 62 return -ENODEV;
63 } 63 }
64 if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) { 64 if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
65 /* Hardcoded values for MrCoffee. */ 65 /* Hardcoded values for MrCoffee. */
66 i8042_kbd_irq = i8042_aux_irq = 13 | 0x20; 66 i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
67 kbd_iobase = ioremap(0x71300060, 8); 67 kbd_iobase = ioremap(0x71300060, 8);
68 if (!kbd_iobase) 68 if (!kbd_iobase)
69 return -1; 69 return -ENODEV;
70 } else { 70 } else {
71 struct linux_ebus *ebus; 71 struct linux_ebus *ebus;
72 struct linux_ebus_device *edev; 72 struct linux_ebus_device *edev;
@@ -78,7 +78,7 @@ static int i8042_platform_init(void)
78 goto edev_found; 78 goto edev_found;
79 } 79 }
80 } 80 }
81 return -1; 81 return -ENODEV;
82 82
83 edev_found: 83 edev_found:
84 for_each_edevchild(edev, child) { 84 for_each_edevchild(edev, child) {
@@ -96,7 +96,7 @@ static int i8042_platform_init(void)
96 i8042_aux_irq == -1) { 96 i8042_aux_irq == -1) {
97 printk("i8042: Error, 8042 device lacks both kbd and " 97 printk("i8042: Error, 8042 device lacks both kbd and "
98 "mouse nodes.\n"); 98 "mouse nodes.\n");
99 return -1; 99 return -ENODEV;
100 } 100 }
101 } 101 }
102 102
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 03877c84e6ff..273bb3b08cfa 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -138,6 +138,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
138 }, 138 },
139 }, 139 },
140 { 140 {
141 .ident = "Fujitsu-Siemens Lifebook E4010",
142 .matches = {
143 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
144 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
145 },
146 },
147 {
141 .ident = "Toshiba P10", 148 .ident = "Toshiba P10",
142 .matches = { 149 .matches = {
143 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 150 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -256,9 +263,10 @@ static void i8042_pnp_exit(void)
256 } 263 }
257} 264}
258 265
259static int i8042_pnp_init(void) 266static int __init i8042_pnp_init(void)
260{ 267{
261 int result_kbd, result_aux; 268 int result_kbd = 0, result_aux = 0;
269 char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
262 270
263 if (i8042_nopnp) { 271 if (i8042_nopnp) {
264 printk(KERN_INFO "i8042: PNP detection disabled\n"); 272 printk(KERN_INFO "i8042: PNP detection disabled\n");
@@ -267,6 +275,7 @@ static int i8042_pnp_init(void)
267 275
268 if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0) 276 if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
269 i8042_pnp_kbd_registered = 1; 277 i8042_pnp_kbd_registered = 1;
278
270 if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0) 279 if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
271 i8042_pnp_aux_registered = 1; 280 i8042_pnp_aux_registered = 1;
272 281
@@ -280,6 +289,27 @@ static int i8042_pnp_init(void)
280#endif 289#endif
281 } 290 }
282 291
292 if (result_kbd > 0)
293 snprintf(kbd_irq_str, sizeof(kbd_irq_str),
294 "%d", i8042_pnp_kbd_irq);
295 if (result_aux > 0)
296 snprintf(aux_irq_str, sizeof(aux_irq_str),
297 "%d", i8042_pnp_aux_irq);
298
299 printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
300 i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "",
301 i8042_pnp_aux_name,
302 i8042_pnp_data_reg, i8042_pnp_command_reg,
303 kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "",
304 aux_irq_str);
305
306#if defined(__ia64__)
307 if (result_kbd <= 0)
308 i8042_nokbd = 1;
309 if (result_aux <= 0)
310 i8042_noaux = 1;
311#endif
312
283 if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && 313 if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
284 i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) { 314 i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) {
285 printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n", 315 printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
@@ -294,53 +324,47 @@ static int i8042_pnp_init(void)
294 i8042_pnp_command_reg = i8042_command_reg; 324 i8042_pnp_command_reg = i8042_command_reg;
295 } 325 }
296 326
297 if (!i8042_pnp_kbd_irq) { 327 if (!i8042_nokbd && !i8042_pnp_kbd_irq) {
298 printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq); 328 printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %d\n", i8042_kbd_irq);
299 i8042_pnp_kbd_irq = i8042_kbd_irq; 329 i8042_pnp_kbd_irq = i8042_kbd_irq;
300 } 330 }
301 331
302 if (!i8042_pnp_aux_irq) { 332 if (!i8042_noaux && !i8042_pnp_aux_irq) {
303 printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq); 333 printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %d\n", i8042_aux_irq);
304 i8042_pnp_aux_irq = i8042_aux_irq; 334 i8042_pnp_aux_irq = i8042_aux_irq;
305 } 335 }
306 336
307#if defined(__ia64__)
308 if (result_aux <= 0)
309 i8042_noaux = 1;
310#endif
311
312 i8042_data_reg = i8042_pnp_data_reg; 337 i8042_data_reg = i8042_pnp_data_reg;
313 i8042_command_reg = i8042_pnp_command_reg; 338 i8042_command_reg = i8042_pnp_command_reg;
314 i8042_kbd_irq = i8042_pnp_kbd_irq; 339 i8042_kbd_irq = i8042_pnp_kbd_irq;
315 i8042_aux_irq = i8042_pnp_aux_irq; 340 i8042_aux_irq = i8042_pnp_aux_irq;
316 341
317 printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n",
318 i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name,
319 i8042_data_reg, i8042_command_reg, i8042_kbd_irq,
320 (result_aux > 0) ? "," : "", i8042_aux_irq);
321
322 return 0; 342 return 0;
323} 343}
324 344
345#else
346static inline int i8042_pnp_init(void) { return 0; }
347static inline void i8042_pnp_exit(void) { }
325#endif 348#endif
326 349
327static inline int i8042_platform_init(void) 350static int __init i8042_platform_init(void)
328{ 351{
352 int retval;
353
329/* 354/*
330 * On ix86 platforms touching the i8042 data register region can do really 355 * On ix86 platforms touching the i8042 data register region can do really
331 * bad things. Because of this the region is always reserved on ix86 boxes. 356 * bad things. Because of this the region is always reserved on ix86 boxes.
332 * 357 *
333 * if (!request_region(I8042_DATA_REG, 16, "i8042")) 358 * if (!request_region(I8042_DATA_REG, 16, "i8042"))
334 * return -1; 359 * return -EBUSY;
335 */ 360 */
336 361
337 i8042_kbd_irq = I8042_MAP_IRQ(1); 362 i8042_kbd_irq = I8042_MAP_IRQ(1);
338 i8042_aux_irq = I8042_MAP_IRQ(12); 363 i8042_aux_irq = I8042_MAP_IRQ(12);
339 364
340#ifdef CONFIG_PNP 365 retval = i8042_pnp_init();
341 if (i8042_pnp_init()) 366 if (retval)
342 return -1; 367 return retval;
343#endif
344 368
345#if defined(__ia64__) 369#if defined(__ia64__)
346 i8042_reset = 1; 370 i8042_reset = 1;
@@ -354,14 +378,12 @@ static inline int i8042_platform_init(void)
354 i8042_nomux = 1; 378 i8042_nomux = 1;
355#endif 379#endif
356 380
357 return 0; 381 return retval;
358} 382}
359 383
360static inline void i8042_platform_exit(void) 384static inline void i8042_platform_exit(void)
361{ 385{
362#ifdef CONFIG_PNP
363 i8042_pnp_exit(); 386 i8042_pnp_exit();
364#endif
365} 387}
366 388
367#endif /* _I8042_X86IA64IO_H */ 389#endif /* _I8042_X86IA64IO_H */
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 708a1d3beab9..40d451ce07ff 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -27,6 +27,10 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
27MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); 27MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
28MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
29 29
30static unsigned int i8042_nokbd;
31module_param_named(nokbd, i8042_nokbd, bool, 0);
32MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port.");
33
30static unsigned int i8042_noaux; 34static unsigned int i8042_noaux;
31module_param_named(noaux, i8042_noaux, bool, 0); 35module_param_named(noaux, i8042_noaux, bool, 0);
32MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); 36MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port.");
@@ -338,10 +342,10 @@ static int i8042_open(struct serio *serio)
338 342
339 return 0; 343 return 0;
340 344
341activate_fail: 345 activate_fail:
342 free_irq(port->irq, i8042_request_irq_cookie); 346 free_irq(port->irq, i8042_request_irq_cookie);
343 347
344irq_fail: 348 irq_fail:
345 serio_unregister_port_delayed(serio); 349 serio_unregister_port_delayed(serio);
346 350
347 return -1; 351 return -1;
@@ -485,7 +489,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
485 serio_interrupt(port->serio, data, dfl, regs); 489 serio_interrupt(port->serio, data, dfl, regs);
486 490
487 ret = 1; 491 ret = 1;
488out: 492 out:
489 return IRQ_RETVAL(ret); 493 return IRQ_RETVAL(ret);
490} 494}
491 495
@@ -552,7 +556,7 @@ static int i8042_enable_mux_ports(void)
552 * Enable all muxed ports. 556 * Enable all muxed ports.
553 */ 557 */
554 558
555 for (i = 0; i < 4; i++) { 559 for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
556 i8042_command(&param, I8042_CMD_MUX_PFX + i); 560 i8042_command(&param, I8042_CMD_MUX_PFX + i);
557 i8042_command(&param, I8042_CMD_AUX_ENABLE); 561 i8042_command(&param, I8042_CMD_AUX_ENABLE);
558 } 562 }
@@ -682,7 +686,7 @@ static int __init i8042_port_register(struct i8042_port *port)
682 kfree(port->serio); 686 kfree(port->serio);
683 port->serio = NULL; 687 port->serio = NULL;
684 i8042_ctr |= port->disable; 688 i8042_ctr |= port->disable;
685 return -1; 689 return -EIO;
686 } 690 }
687 691
688 printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", 692 printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
@@ -977,85 +981,88 @@ static struct device_driver i8042_driver = {
977 .shutdown = i8042_shutdown, 981 .shutdown = i8042_shutdown,
978}; 982};
979 983
980static void __init i8042_create_kbd_port(void) 984static int __init i8042_create_kbd_port(void)
981{ 985{
982 struct serio *serio; 986 struct serio *serio;
983 struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; 987 struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
984 988
985 serio = kmalloc(sizeof(struct serio), GFP_KERNEL); 989 serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
986 if (serio) { 990 if (!serio)
987 memset(serio, 0, sizeof(struct serio)); 991 return -ENOMEM;
988 serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; 992
989 serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; 993 serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
990 serio->open = i8042_open; 994 serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
991 serio->close = i8042_close; 995 serio->open = i8042_open;
992 serio->start = i8042_start; 996 serio->close = i8042_close;
993 serio->stop = i8042_stop; 997 serio->start = i8042_start;
994 serio->port_data = port; 998 serio->stop = i8042_stop;
995 serio->dev.parent = &i8042_platform_device->dev; 999 serio->port_data = port;
996 strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); 1000 serio->dev.parent = &i8042_platform_device->dev;
997 strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); 1001 strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
998 1002 strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
999 port->serio = serio; 1003
1000 i8042_port_register(port); 1004 port->serio = serio;
1001 } 1005
1006 return i8042_port_register(port);
1002} 1007}
1003 1008
1004static void __init i8042_create_aux_port(void) 1009static int __init i8042_create_aux_port(void)
1005{ 1010{
1006 struct serio *serio; 1011 struct serio *serio;
1007 struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; 1012 struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
1008 1013
1009 serio = kmalloc(sizeof(struct serio), GFP_KERNEL); 1014 serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
1010 if (serio) { 1015 if (!serio)
1011 memset(serio, 0, sizeof(struct serio)); 1016 return -ENOMEM;
1012 serio->id.type = SERIO_8042; 1017
1013 serio->write = i8042_aux_write; 1018 serio->id.type = SERIO_8042;
1014 serio->open = i8042_open; 1019 serio->write = i8042_aux_write;
1015 serio->close = i8042_close; 1020 serio->open = i8042_open;
1016 serio->start = i8042_start; 1021 serio->close = i8042_close;
1017 serio->stop = i8042_stop; 1022 serio->start = i8042_start;
1018 serio->port_data = port; 1023 serio->stop = i8042_stop;
1019 serio->dev.parent = &i8042_platform_device->dev; 1024 serio->port_data = port;
1020 strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); 1025 serio->dev.parent = &i8042_platform_device->dev;
1021 strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); 1026 strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
1022 1027 strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
1023 port->serio = serio; 1028
1024 i8042_port_register(port); 1029 port->serio = serio;
1025 } 1030
1031 return i8042_port_register(port);
1026} 1032}
1027 1033
1028static void __init i8042_create_mux_port(int index) 1034static int __init i8042_create_mux_port(int index)
1029{ 1035{
1030 struct serio *serio; 1036 struct serio *serio;
1031 struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; 1037 struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
1032 1038
1033 serio = kmalloc(sizeof(struct serio), GFP_KERNEL); 1039 serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
1034 if (serio) { 1040 if (!serio)
1035 memset(serio, 0, sizeof(struct serio)); 1041 return -ENOMEM;
1036 serio->id.type = SERIO_8042; 1042
1037 serio->write = i8042_aux_write; 1043 serio->id.type = SERIO_8042;
1038 serio->open = i8042_open; 1044 serio->write = i8042_aux_write;
1039 serio->close = i8042_close; 1045 serio->open = i8042_open;
1040 serio->start = i8042_start; 1046 serio->close = i8042_close;
1041 serio->stop = i8042_stop; 1047 serio->start = i8042_start;
1042 serio->port_data = port; 1048 serio->stop = i8042_stop;
1043 serio->dev.parent = &i8042_platform_device->dev; 1049 serio->port_data = port;
1044 snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); 1050 serio->dev.parent = &i8042_platform_device->dev;
1045 snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); 1051 snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
1046 1052 snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
1047 *port = i8042_ports[I8042_AUX_PORT_NO]; 1053
1048 port->exists = 0; 1054 *port = i8042_ports[I8042_AUX_PORT_NO];
1049 snprintf(port->name, sizeof(port->name), "AUX%d", index); 1055 port->exists = 0;
1050 port->mux = index; 1056 snprintf(port->name, sizeof(port->name), "AUX%d", index);
1051 port->serio = serio; 1057 port->mux = index;
1052 i8042_port_register(port); 1058 port->serio = serio;
1053 } 1059
1060 return i8042_port_register(port);
1054} 1061}
1055 1062
1056static int __init i8042_init(void) 1063static int __init i8042_init(void)
1057{ 1064{
1058 int i; 1065 int i, have_ports = 0;
1059 int err; 1066 int err;
1060 1067
1061 dbg_init(); 1068 dbg_init();
@@ -1063,43 +1070,73 @@ static int __init i8042_init(void)
1063 init_timer(&i8042_timer); 1070 init_timer(&i8042_timer);
1064 i8042_timer.function = i8042_timer_func; 1071 i8042_timer.function = i8042_timer_func;
1065 1072
1066 if (i8042_platform_init()) 1073 err = i8042_platform_init();
1067 return -EBUSY; 1074 if (err)
1075 return err;
1068 1076
1069 i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; 1077 i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
1070 i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; 1078 i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
1071 1079
1072 if (i8042_controller_init()) { 1080 if (i8042_controller_init()) {
1073 i8042_platform_exit(); 1081 err = -ENODEV;
1074 return -ENODEV; 1082 goto err_platform_exit;
1075 } 1083 }
1076 1084
1077 err = driver_register(&i8042_driver); 1085 err = driver_register(&i8042_driver);
1078 if (err) { 1086 if (err)
1079 i8042_platform_exit(); 1087 goto err_controller_cleanup;
1080 return err;
1081 }
1082 1088
1083 i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); 1089 i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
1084 if (IS_ERR(i8042_platform_device)) { 1090 if (IS_ERR(i8042_platform_device)) {
1085 driver_unregister(&i8042_driver); 1091 err = PTR_ERR(i8042_platform_device);
1086 i8042_platform_exit(); 1092 goto err_unregister_driver;
1087 return PTR_ERR(i8042_platform_device);
1088 } 1093 }
1089 1094
1090 if (!i8042_noaux && !i8042_check_aux()) { 1095 if (!i8042_noaux && !i8042_check_aux()) {
1091 if (!i8042_nomux && !i8042_check_mux()) 1096 if (!i8042_nomux && !i8042_check_mux()) {
1092 for (i = 0; i < I8042_NUM_MUX_PORTS; i++) 1097 for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
1093 i8042_create_mux_port(i); 1098 err = i8042_create_mux_port(i);
1094 else 1099 if (err)
1095 i8042_create_aux_port(); 1100 goto err_unregister_ports;
1101 }
1102 } else {
1103 err = i8042_create_aux_port();
1104 if (err)
1105 goto err_unregister_ports;
1106 }
1107 have_ports = 1;
1096 } 1108 }
1097 1109
1098 i8042_create_kbd_port(); 1110 if (!i8042_nokbd) {
1111 err = i8042_create_kbd_port();
1112 if (err)
1113 goto err_unregister_ports;
1114 have_ports = 1;
1115 }
1116
1117 if (!have_ports) {
1118 err = -ENODEV;
1119 goto err_unregister_device;
1120 }
1099 1121
1100 mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); 1122 mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
1101 1123
1102 return 0; 1124 return 0;
1125
1126 err_unregister_ports:
1127 for (i = 0; i < I8042_NUM_PORTS; i++)
1128 if (i8042_ports[i].serio)
1129 serio_unregister_port(i8042_ports[i].serio);
1130 err_unregister_device:
1131 platform_device_unregister(i8042_platform_device);
1132 err_unregister_driver:
1133 driver_unregister(&i8042_driver);
1134 err_controller_cleanup:
1135 i8042_controller_cleanup();
1136 err_platform_exit:
1137 i8042_platform_exit();
1138
1139 return err;
1103} 1140}
1104 1141
1105static void __exit i8042_exit(void) 1142static void __exit i8042_exit(void)
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 1ab95d24c5e2..e108e0a36b74 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -2,7 +2,8 @@
2 * USB HID support for Linux 2 * USB HID support for Linux
3 * 3 *
4 * Copyright (c) 1999 Andreas Gal 4 * Copyright (c) 1999 Andreas Gal
5 * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz> 5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
6 */ 7 */
7 8
8/* 9/*
@@ -38,7 +39,7 @@
38 * Version Information 39 * Version Information
39 */ 40 */
40 41
41#define DRIVER_VERSION "v2.01" 42#define DRIVER_VERSION "v2.6"
42#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" 43#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
43#define DRIVER_DESC "USB HID core driver" 44#define DRIVER_DESC "USB HID core driver"
44#define DRIVER_LICENSE "GPL" 45#define DRIVER_LICENSE "GPL"
@@ -1058,8 +1059,8 @@ static int hid_submit_ctrl(struct hid_device *hid)
1058 if (maxpacket > 0) { 1059 if (maxpacket > 0) {
1059 padlen = (len + maxpacket - 1) / maxpacket; 1060 padlen = (len + maxpacket - 1) / maxpacket;
1060 padlen *= maxpacket; 1061 padlen *= maxpacket;
1061 if (padlen > HID_BUFFER_SIZE) 1062 if (padlen > hid->bufsize)
1062 padlen = HID_BUFFER_SIZE; 1063 padlen = hid->bufsize;
1063 } else 1064 } else
1064 padlen = 0; 1065 padlen = 0;
1065 hid->urbctrl->transfer_buffer_length = padlen; 1066 hid->urbctrl->transfer_buffer_length = padlen;
@@ -1096,6 +1097,7 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
1096 1097
1097 switch (urb->status) { 1098 switch (urb->status) {
1098 case 0: /* success */ 1099 case 0: /* success */
1100 break;
1099 case -ESHUTDOWN: /* unplug */ 1101 case -ESHUTDOWN: /* unplug */
1100 case -EILSEQ: /* unplug timeout on uhci */ 1102 case -EILSEQ: /* unplug timeout on uhci */
1101 unplug = 1; 1103 unplug = 1;
@@ -1143,6 +1145,7 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
1143 case 0: /* success */ 1145 case 0: /* success */
1144 if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 1146 if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
1145 hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs); 1147 hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
1148 break;
1146 case -ESHUTDOWN: /* unplug */ 1149 case -ESHUTDOWN: /* unplug */
1147 case -EILSEQ: /* unplug timectrl on uhci */ 1150 case -EILSEQ: /* unplug timectrl on uhci */
1148 unplug = 1; 1151 unplug = 1;
@@ -1284,13 +1287,8 @@ void hid_init_reports(struct hid_device *hid)
1284 struct hid_report *report; 1287 struct hid_report *report;
1285 int err, ret; 1288 int err, ret;
1286 1289
1287 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) { 1290 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
1288 int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
1289 if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE;
1290 if (size > hid->urbin->transfer_buffer_length)
1291 hid->urbin->transfer_buffer_length = size;
1292 hid_submit_report(hid, report, USB_DIR_IN); 1291 hid_submit_report(hid, report, USB_DIR_IN);
1293 }
1294 1292
1295 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) 1293 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
1296 hid_submit_report(hid, report, USB_DIR_IN); 1294 hid_submit_report(hid, report, USB_DIR_IN);
@@ -1372,12 +1370,14 @@ void hid_init_reports(struct hid_device *hid)
1372#define USB_VENDOR_ID_A4TECH 0x09da 1370#define USB_VENDOR_ID_A4TECH 0x09da
1373#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 1371#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
1374 1372
1375#define USB_VENDOR_ID_AASHIMA 0x06D6 1373#define USB_VENDOR_ID_AASHIMA 0x06d6
1376#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 1374#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025
1375#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026
1377 1376
1378#define USB_VENDOR_ID_CYPRESS 0x04b4 1377#define USB_VENDOR_ID_CYPRESS 0x04b4
1379#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 1378#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
1380#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 1379#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
1380#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417
1381 1381
1382#define USB_VENDOR_ID_BERKSHIRE 0x0c98 1382#define USB_VENDOR_ID_BERKSHIRE 0x0c98
1383#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 1383#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
@@ -1432,7 +1432,7 @@ void hid_init_reports(struct hid_device *hid)
1432#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 1432#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
1433 1433
1434#define USB_VENDOR_ID_LD 0x0f11 1434#define USB_VENDOR_ID_LD 0x0f11
1435#define USB_DEVICE_ID_CASSY 0x1000 1435#define USB_DEVICE_ID_CASSY 0x1000
1436#define USB_DEVICE_ID_POCKETCASSY 0x1010 1436#define USB_DEVICE_ID_POCKETCASSY 0x1010
1437#define USB_DEVICE_ID_MOBILECASSY 0x1020 1437#define USB_DEVICE_ID_MOBILECASSY 0x1020
1438#define USB_DEVICE_ID_JWM 0x1080 1438#define USB_DEVICE_ID_JWM 0x1080
@@ -1445,7 +1445,8 @@ void hid_init_reports(struct hid_device *hid)
1445#define USB_DEVICE_ID_POWERCONTROL 0x2030 1445#define USB_DEVICE_ID_POWERCONTROL 0x2030
1446 1446
1447#define USB_VENDOR_ID_APPLE 0x05ac 1447#define USB_VENDOR_ID_APPLE 0x05ac
1448#define USB_DEVICE_ID_APPLE_BLUETOOTH 0x1000 1448#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
1449#define USB_DEVICE_ID_APPLE_BLUETOOTH 0x1000
1449 1450
1450/* 1451/*
1451 * Alphabetically sorted blacklist by quirk type. 1452 * Alphabetically sorted blacklist by quirk type.
@@ -1471,6 +1472,7 @@ static struct hid_blacklist {
1471 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE }, 1472 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
1472 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE }, 1473 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
1473 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, 1474 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
1475 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
1474 { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE }, 1476 { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
1475 { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE }, 1477 { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
1476 { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, 1478 { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
@@ -1551,10 +1553,12 @@ static struct hid_blacklist {
1551 { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET}, 1553 { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
1552 { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, 1554 { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
1553 1555
1556 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
1554 { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, 1557 { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
1555 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, 1558 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
1556 1559
1557 { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, 1560 { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
1561 { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
1558 { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, 1562 { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
1559 { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, 1563 { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
1560 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, 1564 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -1567,15 +1571,32 @@ static struct hid_blacklist {
1567 { 0, 0 } 1571 { 0, 0 }
1568}; 1572};
1569 1573
1574/*
1575 * Traverse the supplied list of reports and find the longest
1576 */
1577static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
1578{
1579 struct hid_report *report;
1580 int size;
1581
1582 list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
1583 size = ((report->size - 1) >> 3) + 1;
1584 if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
1585 size++;
1586 if (*max < size)
1587 *max = size;
1588 }
1589}
1590
1570static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) 1591static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
1571{ 1592{
1572 if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma))) 1593 if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma)))
1573 return -1; 1594 return -1;
1574 if (!(hid->outbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->outbuf_dma))) 1595 if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma)))
1575 return -1; 1596 return -1;
1576 if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma))) 1597 if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma)))
1577 return -1; 1598 return -1;
1578 if (!(hid->ctrlbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->ctrlbuf_dma))) 1599 if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
1579 return -1; 1600 return -1;
1580 1601
1581 return 0; 1602 return 0;
@@ -1584,13 +1605,13 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
1584static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) 1605static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
1585{ 1606{
1586 if (hid->inbuf) 1607 if (hid->inbuf)
1587 usb_buffer_free(dev, HID_BUFFER_SIZE, hid->inbuf, hid->inbuf_dma); 1608 usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
1588 if (hid->outbuf) 1609 if (hid->outbuf)
1589 usb_buffer_free(dev, HID_BUFFER_SIZE, hid->outbuf, hid->outbuf_dma); 1610 usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
1590 if (hid->cr) 1611 if (hid->cr)
1591 usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma); 1612 usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
1592 if (hid->ctrlbuf) 1613 if (hid->ctrlbuf)
1593 usb_buffer_free(dev, HID_BUFFER_SIZE, hid->ctrlbuf, hid->ctrlbuf_dma); 1614 usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
1594} 1615}
1595 1616
1596static struct hid_device *usb_hid_configure(struct usb_interface *intf) 1617static struct hid_device *usb_hid_configure(struct usb_interface *intf)
@@ -1601,7 +1622,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
1601 struct hid_device *hid; 1622 struct hid_device *hid;
1602 unsigned quirks = 0, rsize = 0; 1623 unsigned quirks = 0, rsize = 0;
1603 char *buf, *rdesc; 1624 char *buf, *rdesc;
1604 int n; 1625 int n, insize = 0;
1605 1626
1606 for (n = 0; hid_blacklist[n].idVendor; n++) 1627 for (n = 0; hid_blacklist[n].idVendor; n++)
1607 if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && 1628 if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
@@ -1655,6 +1676,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
1655 kfree(rdesc); 1676 kfree(rdesc);
1656 hid->quirks = quirks; 1677 hid->quirks = quirks;
1657 1678
1679 hid->bufsize = HID_MIN_BUFFER_SIZE;
1680 hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
1681 hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
1682 hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
1683
1684 if (hid->bufsize > HID_MAX_BUFFER_SIZE)
1685 hid->bufsize = HID_MAX_BUFFER_SIZE;
1686
1687 hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
1688
1689 if (insize > HID_MAX_BUFFER_SIZE)
1690 insize = HID_MAX_BUFFER_SIZE;
1691
1658 if (hid_alloc_buffers(dev, hid)) { 1692 if (hid_alloc_buffers(dev, hid)) {
1659 hid_free_buffers(dev, hid); 1693 hid_free_buffers(dev, hid);
1660 goto fail; 1694 goto fail;
@@ -1685,7 +1719,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
1685 if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL))) 1719 if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
1686 goto fail; 1720 goto fail;
1687 pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 1721 pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
1688 usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0, 1722 usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
1689 hid_irq_in, hid, interval); 1723 hid_irq_in, hid, interval);
1690 hid->urbin->transfer_dma = hid->inbuf_dma; 1724 hid->urbin->transfer_dma = hid->inbuf_dma;
1691 hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1725 hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
index 52437e5e2e78..ceebab99eff2 100644
--- a/drivers/usb/input/hid-debug.h
+++ b/drivers/usb/input/hid-debug.h
@@ -85,6 +85,23 @@ static const struct hid_usage_entry hid_usage_table[] = {
85 {0, 0x91, "D-PadDown"}, 85 {0, 0x91, "D-PadDown"},
86 {0, 0x92, "D-PadRight"}, 86 {0, 0x92, "D-PadRight"},
87 {0, 0x93, "D-PadLeft"}, 87 {0, 0x93, "D-PadLeft"},
88 { 2, 0, "Simulation" },
89 {0, 0xb0, "Aileron"},
90 {0, 0xb1, "AileronTrim"},
91 {0, 0xb2, "Anti-Torque"},
92 {0, 0xb3, "Autopilot"},
93 {0, 0xb4, "Chaff"},
94 {0, 0xb5, "Collective"},
95 {0, 0xb6, "DiveBrake"},
96 {0, 0xb7, "ElectronicCountermeasures"},
97 {0, 0xb8, "Elevator"},
98 {0, 0xb9, "ElevatorTrim"},
99 {0, 0xba, "Rudder"},
100 {0, 0xbb, "Throttle"},
101 {0, 0xbc, "FlightCommunications"},
102 {0, 0xbd, "FlareRelease"},
103 {0, 0xbe, "LandingGear"},
104 {0, 0xbf, "ToeBrake"},
88 { 7, 0, "Keyboard" }, 105 { 7, 0, "Keyboard" },
89 { 8, 0, "LED" }, 106 { 8, 0, "LED" },
90 {0, 0x01, "NumLock"}, 107 {0, 0x01, "NumLock"},
@@ -92,6 +109,7 @@ static const struct hid_usage_entry hid_usage_table[] = {
92 {0, 0x03, "ScrollLock"}, 109 {0, 0x03, "ScrollLock"},
93 {0, 0x04, "Compose"}, 110 {0, 0x04, "Compose"},
94 {0, 0x05, "Kana"}, 111 {0, 0x05, "Kana"},
112 {0, 0x4b, "GenericIndicator"},
95 { 9, 0, "Button" }, 113 { 9, 0, "Button" },
96 { 10, 0, "Ordinal" }, 114 { 10, 0, "Ordinal" },
97 { 12, 0, "Consumer" }, 115 { 12, 0, "Consumer" },
@@ -574,7 +592,8 @@ static char *keys[KEY_MAX + 1] = {
574 [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move", 592 [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move",
575 [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp", 593 [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp",
576 [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis", 594 [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis",
577 [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_F13] = "F13", 595 [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New",
596 [KEY_REDO] = "Redo", [KEY_F13] = "F13",
578 [KEY_F14] = "F14", [KEY_F15] = "F15", 597 [KEY_F14] = "F14", [KEY_F15] = "F15",
579 [KEY_F16] = "F16", [KEY_F17] = "F17", 598 [KEY_F16] = "F16", [KEY_F17] = "F17",
580 [KEY_F18] = "F18", [KEY_F19] = "F19", 599 [KEY_F18] = "F18", [KEY_F19] = "F19",
@@ -584,15 +603,15 @@ static char *keys[KEY_MAX + 1] = {
584 [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", 603 [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3",
585 [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", 604 [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend",
586 [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", 605 [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play",
587 [KEY_FASTFORWARD] = "Fast Forward", [KEY_BASSBOOST] = "Bass Boost", 606 [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost",
588 [KEY_PRINT] = "Print", [KEY_HP] = "HP", 607 [KEY_PRINT] = "Print", [KEY_HP] = "HP",
589 [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound", 608 [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound",
590 [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email", 609 [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email",
591 [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search", 610 [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search",
592 [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance", 611 [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance",
593 [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop", 612 [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop",
594 [KEY_ALTERASE] = "Alternate Erase", [KEY_CANCEL] = "Cancel", 613 [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel",
595 [KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] = "Brightness up", 614 [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
596 [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", 615 [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown",
597 [BTN_0] = "Btn0", [BTN_1] = "Btn1", 616 [BTN_0] = "Btn0", [BTN_1] = "Btn1",
598 [BTN_2] = "Btn2", [BTN_3] = "Btn3", 617 [BTN_2] = "Btn2", [BTN_3] = "Btn3",
@@ -622,8 +641,8 @@ static char *keys[KEY_MAX + 1] = {
622 [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger", 641 [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger",
623 [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", 642 [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens",
624 [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", 643 [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
625 [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap", 644 [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
626 [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn", 645 [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
627 [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", 646 [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
628 [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", 647 [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto",
629 [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", 648 [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2",
@@ -659,6 +678,9 @@ static char *keys[KEY_MAX + 1] = {
659 [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL", 678 [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL",
660 [KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine", 679 [KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine",
661 [KEY_DEL_LINE] = "DeleteLine", 680 [KEY_DEL_LINE] = "DeleteLine",
681 [KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
682 [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
683 [KEY_DOCUMENTS] = "Documents",
662}; 684};
663 685
664static char *relatives[REL_MAX + 1] = { 686static char *relatives[REL_MAX + 1] = {
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 63a4db721f7e..0b6452248a39 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -78,8 +78,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
78{ 78{
79 struct input_dev *input = &hidinput->input; 79 struct input_dev *input = &hidinput->input;
80 struct hid_device *device = hidinput->input.private; 80 struct hid_device *device = hidinput->input.private;
81 int max, code; 81 int max = 0, code;
82 unsigned long *bit; 82 unsigned long *bit = NULL;
83 83
84 field->hidinput = hidinput; 84 field->hidinput = hidinput;
85 85
@@ -131,6 +131,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
131 map_key(code); 131 map_key(code);
132 break; 132 break;
133 133
134
135 case HID_UP_SIMULATION:
136
137 switch (usage->hid & 0xffff) {
138 case 0xba: map_abs(ABS_RUDDER); break;
139 case 0xbb: map_abs(ABS_THROTTLE); break;
140 }
141 break;
142
134 case HID_UP_GENDESK: 143 case HID_UP_GENDESK:
135 144
136 if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */ 145 if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
@@ -238,8 +247,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
238 case 0x000: goto ignore; 247 case 0x000: goto ignore;
239 case 0x034: map_key_clear(KEY_SLEEP); break; 248 case 0x034: map_key_clear(KEY_SLEEP); break;
240 case 0x036: map_key_clear(BTN_MISC); break; 249 case 0x036: map_key_clear(BTN_MISC); break;
250 case 0x045: map_key_clear(KEY_RADIO); break;
241 case 0x08a: map_key_clear(KEY_WWW); break; 251 case 0x08a: map_key_clear(KEY_WWW); break;
252 case 0x08d: map_key_clear(KEY_PROGRAM); break;
242 case 0x095: map_key_clear(KEY_HELP); break; 253 case 0x095: map_key_clear(KEY_HELP); break;
254 case 0x09c: map_key_clear(KEY_CHANNELUP); break;
255 case 0x09d: map_key_clear(KEY_CHANNELDOWN); break;
243 case 0x0b0: map_key_clear(KEY_PLAY); break; 256 case 0x0b0: map_key_clear(KEY_PLAY); break;
244 case 0x0b1: map_key_clear(KEY_PAUSE); break; 257 case 0x0b1: map_key_clear(KEY_PAUSE); break;
245 case 0x0b2: map_key_clear(KEY_RECORD); break; 258 case 0x0b2: map_key_clear(KEY_RECORD); break;
@@ -259,6 +272,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
259 case 0x18a: map_key_clear(KEY_MAIL); break; 272 case 0x18a: map_key_clear(KEY_MAIL); break;
260 case 0x192: map_key_clear(KEY_CALC); break; 273 case 0x192: map_key_clear(KEY_CALC); break;
261 case 0x194: map_key_clear(KEY_FILE); break; 274 case 0x194: map_key_clear(KEY_FILE); break;
275 case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
276 case 0x201: map_key_clear(KEY_NEW); break;
277 case 0x207: map_key_clear(KEY_SAVE); break;
278 case 0x208: map_key_clear(KEY_PRINT); break;
279 case 0x209: map_key_clear(KEY_PROPS); break;
262 case 0x21a: map_key_clear(KEY_UNDO); break; 280 case 0x21a: map_key_clear(KEY_UNDO); break;
263 case 0x21b: map_key_clear(KEY_COPY); break; 281 case 0x21b: map_key_clear(KEY_COPY); break;
264 case 0x21c: map_key_clear(KEY_CUT); break; 282 case 0x21c: map_key_clear(KEY_CUT); break;
@@ -271,7 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
271 case 0x227: map_key_clear(KEY_REFRESH); break; 289 case 0x227: map_key_clear(KEY_REFRESH); break;
272 case 0x22a: map_key_clear(KEY_BOOKMARKS); break; 290 case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
273 case 0x238: map_rel(REL_HWHEEL); break; 291 case 0x238: map_rel(REL_HWHEEL); break;
274 default: goto unknown; 292 case 0x279: map_key_clear(KEY_REDO); break;
293 case 0x289: map_key_clear(KEY_REPLY); break;
294 case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
295 case 0x28c: map_key_clear(KEY_SEND); break;
296 default: goto ignore;
275 } 297 }
276 break; 298 break;
277 299
@@ -296,9 +318,42 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
296 break; 318 break;
297 319
298 case HID_UP_MSVENDOR: 320 case HID_UP_MSVENDOR:
299
300 goto ignore; 321 goto ignore;
301 322
323 case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
324
325 set_bit(EV_REP, input->evbit);
326 switch(usage->hid & HID_USAGE) {
327 case 0x003: map_key_clear(KEY_FN); break;
328 default: goto ignore;
329 }
330 break;
331
332 case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
333
334 set_bit(EV_REP, input->evbit);
335 switch(usage->hid & HID_USAGE) {
336 case 0x004: map_key_clear(KEY_AGAIN); break;
337 case 0x00d: map_key_clear(KEY_HOME); break;
338 case 0x024: map_key_clear(KEY_SHUFFLE); break;
339 case 0x025: map_key_clear(KEY_TV); break;
340 case 0x026: map_key_clear(KEY_MENU); break;
341 case 0x031: map_key_clear(KEY_AUDIO); break;
342 case 0x032: map_key_clear(KEY_SUBTITLE); break;
343 case 0x033: map_key_clear(KEY_LAST); break;
344 case 0x047: map_key_clear(KEY_MP3); break;
345 case 0x048: map_key_clear(KEY_DVD); break;
346 case 0x049: map_key_clear(KEY_MEDIA); break;
347 case 0x04a: map_key_clear(KEY_VIDEO); break;
348 case 0x04b: map_key_clear(KEY_ANGLE); break;
349 case 0x04c: map_key_clear(KEY_LANGUAGE); break;
350 case 0x04d: map_key_clear(KEY_SUBTITLE); break;
351 case 0x051: map_key_clear(KEY_RED); break;
352 case 0x052: map_key_clear(KEY_CLOSE); break;
353 default: goto ignore;
354 }
355 break;
356
302 case HID_UP_PID: 357 case HID_UP_PID:
303 358
304 set_bit(EV_FF, input->evbit); 359 set_bit(EV_FF, input->evbit);
@@ -349,6 +404,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
349 if (usage->code > max) 404 if (usage->code > max)
350 goto ignore; 405 goto ignore;
351 406
407 if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032)))
408 map_rel(REL_HWHEEL);
409
352 if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && 410 if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
353 (usage->type == EV_REL) && (usage->code == REL_WHEEL)) 411 (usage->type == EV_REL) && (usage->code == REL_WHEEL))
354 set_bit(REL_HWHEEL, bit); 412 set_bit(REL_HWHEEL, bit);
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index c1b6b69bc4a4..ec2412c42f1e 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -173,6 +173,7 @@ struct hid_item {
173 173
174#define HID_UP_UNDEFINED 0x00000000 174#define HID_UP_UNDEFINED 0x00000000
175#define HID_UP_GENDESK 0x00010000 175#define HID_UP_GENDESK 0x00010000
176#define HID_UP_SIMULATION 0x00020000
176#define HID_UP_KEYBOARD 0x00070000 177#define HID_UP_KEYBOARD 0x00070000
177#define HID_UP_LED 0x00080000 178#define HID_UP_LED 0x00080000
178#define HID_UP_BUTTON 0x00090000 179#define HID_UP_BUTTON 0x00090000
@@ -182,6 +183,8 @@ struct hid_item {
182#define HID_UP_PID 0x000f0000 183#define HID_UP_PID 0x000f0000
183#define HID_UP_HPVENDOR 0xff7f0000 184#define HID_UP_HPVENDOR 0xff7f0000
184#define HID_UP_MSVENDOR 0xff000000 185#define HID_UP_MSVENDOR 0xff000000
186#define HID_UP_CUSTOM 0x00ff0000
187#define HID_UP_LOGIVENDOR 0xffbc0000
185 188
186#define HID_USAGE 0x0000ffff 189#define HID_USAGE 0x0000ffff
187 190
@@ -242,6 +245,7 @@ struct hid_item {
242#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 245#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080
243#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 246#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100
244#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 247#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200
248#define HID_QUIRK_2WHEEL_POWERMOUSE 0x400
245 249
246/* 250/*
247 * This is the global environment of the parser. This information is 251 * This is the global environment of the parser. This information is
@@ -348,7 +352,8 @@ struct hid_report_enum {
348 352
349#define HID_REPORT_TYPES 3 353#define HID_REPORT_TYPES 3
350 354
351#define HID_BUFFER_SIZE 64 /* use 64 for compatibility with all possible packetlen */ 355#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */
356#define HID_MAX_BUFFER_SIZE 4096 /* 4kb */
352#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ 357#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */
353#define HID_OUTPUT_FIFO_SIZE 64 358#define HID_OUTPUT_FIFO_SIZE 64
354 359
@@ -386,6 +391,8 @@ struct hid_device { /* device report descriptor */
386 391
387 unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ 392 unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
388 393
394 unsigned int bufsize; /* URB buffer size */
395
389 struct urb *urbin; /* Input URB */ 396 struct urb *urbin; /* Input URB */
390 char *inbuf; /* Input buffer */ 397 char *inbuf; /* Input buffer */
391 dma_addr_t inbuf_dma; /* Input buffer dma */ 398 dma_addr_t inbuf_dma; /* Input buffer dma */
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 4c13331b5f41..d32427818af7 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -507,6 +507,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
507 return -EINVAL; 507 return -EINVAL;
508 508
509 hid_submit_report(hid, report, USB_DIR_OUT); 509 hid_submit_report(hid, report, USB_DIR_OUT);
510 hid_wait_io(hid);
510 511
511 return 0; 512 return 0;
512 513
diff --git a/include/linux/input.h b/include/linux/input.h
index 4767e5429534..e8c296ff6257 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -289,6 +289,8 @@ struct input_absinfo {
289#define KEY_SCROLLDOWN 178 289#define KEY_SCROLLDOWN 178
290#define KEY_KPLEFTPAREN 179 290#define KEY_KPLEFTPAREN 179
291#define KEY_KPRIGHTPAREN 180 291#define KEY_KPRIGHTPAREN 180
292#define KEY_NEW 181
293#define KEY_REDO 182
292 294
293#define KEY_F13 183 295#define KEY_F13 183
294#define KEY_F14 184 296#define KEY_F14 184
@@ -335,6 +337,12 @@ struct input_absinfo {
335#define KEY_KBDILLUMDOWN 229 337#define KEY_KBDILLUMDOWN 229
336#define KEY_KBDILLUMUP 230 338#define KEY_KBDILLUMUP 230
337 339
340#define KEY_SEND 231
341#define KEY_REPLY 232
342#define KEY_FORWARDMAIL 233
343#define KEY_SAVE 234
344#define KEY_DOCUMENTS 235
345
338#define KEY_UNKNOWN 240 346#define KEY_UNKNOWN 240
339 347
340#define BTN_MISC 0x100 348#define BTN_MISC 0x100