diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-14 12:49:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-14 12:49:16 -0500 |
commit | e7de369050534025b33aab1033358bf47a577e4d (patch) | |
tree | fed44f469923690b98f9de2c87e6d1de76f71dc9 | |
parent | 87530db5ec7d519c7ba334e414307c5130ae2da8 (diff) | |
parent | eab9edd27f7ceaad6b57085817d63287bda15190 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/dtor/input
-rw-r--r-- | drivers/input/mouse/alps.c | 38 | ||||
-rw-r--r-- | drivers/input/mouse/logips2pp.c | 2 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 316 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse.h | 9 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 7 | ||||
-rw-r--r-- | drivers/usb/input/Kconfig | 10 | ||||
-rw-r--r-- | drivers/usb/input/hid-core.c | 30 | ||||
-rw-r--r-- | drivers/usb/input/hid-input.c | 179 | ||||
-rw-r--r-- | drivers/usb/input/hid.h | 30 | ||||
-rw-r--r-- | drivers/usb/input/pid.c | 2 | ||||
-rw-r--r-- | drivers/usb/input/wacom.c | 14 |
12 files changed, 551 insertions, 88 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 24474335dfd1..2141501e9f2e 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -348,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) | |||
348 | return 0; | 348 | return 0; |
349 | } | 349 | } |
350 | 350 | ||
351 | /* | ||
352 | * alps_poll() - poll the touchpad for current motion packet. | ||
353 | * Used in resync. | ||
354 | */ | ||
355 | static int alps_poll(struct psmouse *psmouse) | ||
356 | { | ||
357 | struct alps_data *priv = psmouse->private; | ||
358 | unsigned char buf[6]; | ||
359 | int poll_failed; | ||
360 | |||
361 | if (priv->i->flags & ALPS_PASS) | ||
362 | alps_passthrough_mode(psmouse, 1); | ||
363 | |||
364 | poll_failed = ps2_command(&psmouse->ps2dev, buf, | ||
365 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; | ||
366 | |||
367 | if (priv->i->flags & ALPS_PASS) | ||
368 | alps_passthrough_mode(psmouse, 0); | ||
369 | |||
370 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) | ||
371 | return -1; | ||
372 | |||
373 | if ((psmouse->badbyte & 0xc8) == 0x08) { | ||
374 | /* | ||
375 | * Poll the track stick ... | ||
376 | */ | ||
377 | if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8))) | ||
378 | return -1; | ||
379 | } | ||
380 | |||
381 | memcpy(psmouse->packet, buf, sizeof(buf)); | ||
382 | return 0; | ||
383 | } | ||
384 | |||
351 | static int alps_reconnect(struct psmouse *psmouse) | 385 | static int alps_reconnect(struct psmouse *psmouse) |
352 | { | 386 | { |
353 | struct alps_data *priv = psmouse->private; | 387 | struct alps_data *priv = psmouse->private; |
@@ -451,10 +485,14 @@ int alps_init(struct psmouse *psmouse) | |||
451 | input_register_device(priv->dev2); | 485 | input_register_device(priv->dev2); |
452 | 486 | ||
453 | psmouse->protocol_handler = alps_process_byte; | 487 | psmouse->protocol_handler = alps_process_byte; |
488 | psmouse->poll = alps_poll; | ||
454 | psmouse->disconnect = alps_disconnect; | 489 | psmouse->disconnect = alps_disconnect; |
455 | psmouse->reconnect = alps_reconnect; | 490 | psmouse->reconnect = alps_reconnect; |
456 | psmouse->pktsize = 6; | 491 | psmouse->pktsize = 6; |
457 | 492 | ||
493 | /* We are having trouble resyncing ALPS touchpads so disable it for now */ | ||
494 | psmouse->resync_time = 0; | ||
495 | |||
458 | return 0; | 496 | return 0; |
459 | 497 | ||
460 | init_fail: | 498 | init_fail: |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 025a71de5404..c88520d3d13c 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha | |||
117 | if (psmouse_sliced_command(psmouse, command)) | 117 | if (psmouse_sliced_command(psmouse, command)) |
118 | return -1; | 118 | return -1; |
119 | 119 | ||
120 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL)) | 120 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300)) |
121 | return -1; | 121 | return -1; |
122 | 122 | ||
123 | return 0; | 123 | return 0; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 4d5ecc04c5b6..7665fd9ce559 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1; | |||
54 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); | 54 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); |
55 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); | 55 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); |
56 | 56 | ||
57 | static unsigned int psmouse_resetafter; | 57 | static unsigned int psmouse_resetafter = 5; |
58 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); | 58 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); |
59 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); | 59 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); |
60 | 60 | ||
61 | static unsigned int psmouse_resync_time = 5; | ||
62 | module_param_named(resync_time, psmouse_resync_time, uint, 0644); | ||
63 | MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never)."); | ||
64 | |||
61 | PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, | 65 | PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, |
62 | NULL, | 66 | NULL, |
63 | psmouse_attr_show_protocol, psmouse_attr_set_protocol); | 67 | psmouse_attr_show_protocol, psmouse_attr_set_protocol); |
@@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO, | |||
70 | PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, | 74 | PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, |
71 | (void *) offsetof(struct psmouse, resetafter), | 75 | (void *) offsetof(struct psmouse, resetafter), |
72 | psmouse_show_int_attr, psmouse_set_int_attr); | 76 | psmouse_show_int_attr, psmouse_set_int_attr); |
77 | PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO, | ||
78 | (void *) offsetof(struct psmouse, resync_time), | ||
79 | psmouse_show_int_attr, psmouse_set_int_attr); | ||
73 | 80 | ||
74 | static struct attribute *psmouse_attributes[] = { | 81 | static struct attribute *psmouse_attributes[] = { |
75 | &psmouse_attr_protocol.dattr.attr, | 82 | &psmouse_attr_protocol.dattr.attr, |
76 | &psmouse_attr_rate.dattr.attr, | 83 | &psmouse_attr_rate.dattr.attr, |
77 | &psmouse_attr_resolution.dattr.attr, | 84 | &psmouse_attr_resolution.dattr.attr, |
78 | &psmouse_attr_resetafter.dattr.attr, | 85 | &psmouse_attr_resetafter.dattr.attr, |
86 | &psmouse_attr_resync_time.dattr.attr, | ||
79 | NULL | 87 | NULL |
80 | }; | 88 | }; |
81 | 89 | ||
@@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate="); | |||
98 | */ | 106 | */ |
99 | static DECLARE_MUTEX(psmouse_sem); | 107 | static DECLARE_MUTEX(psmouse_sem); |
100 | 108 | ||
109 | static struct workqueue_struct *kpsmoused_wq; | ||
110 | |||
101 | struct psmouse_protocol { | 111 | struct psmouse_protocol { |
102 | enum psmouse_type type; | 112 | enum psmouse_type type; |
103 | char *name; | 113 | char *name; |
@@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg | |||
178 | } | 188 | } |
179 | 189 | ||
180 | /* | 190 | /* |
181 | * psmouse_interrupt() handles incoming characters, either gathering them into | 191 | * __psmouse_set_state() sets new psmouse state and resets all flags. |
182 | * packets or passing them to the command routine as command output. | 192 | */ |
193 | |||
194 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
195 | { | ||
196 | psmouse->state = new_state; | ||
197 | psmouse->pktcnt = psmouse->out_of_sync = 0; | ||
198 | psmouse->ps2dev.flags = 0; | ||
199 | psmouse->last = jiffies; | ||
200 | } | ||
201 | |||
202 | |||
203 | /* | ||
204 | * psmouse_set_state() sets new psmouse state and resets all flags and | ||
205 | * counters while holding serio lock so fighting with interrupt handler | ||
206 | * is not a concern. | ||
207 | */ | ||
208 | |||
209 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
210 | { | ||
211 | serio_pause_rx(psmouse->ps2dev.serio); | ||
212 | __psmouse_set_state(psmouse, new_state); | ||
213 | serio_continue_rx(psmouse->ps2dev.serio); | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * psmouse_handle_byte() processes one byte of the input data stream | ||
218 | * by calling corresponding protocol handler. | ||
219 | */ | ||
220 | |||
221 | static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs) | ||
222 | { | ||
223 | psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs); | ||
224 | |||
225 | switch (rc) { | ||
226 | case PSMOUSE_BAD_DATA: | ||
227 | if (psmouse->state == PSMOUSE_ACTIVATED) { | ||
228 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | ||
229 | psmouse->name, psmouse->phys, psmouse->pktcnt); | ||
230 | if (++psmouse->out_of_sync == psmouse->resetafter) { | ||
231 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
232 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | ||
233 | serio_reconnect(psmouse->ps2dev.serio); | ||
234 | return -1; | ||
235 | } | ||
236 | } | ||
237 | psmouse->pktcnt = 0; | ||
238 | break; | ||
239 | |||
240 | case PSMOUSE_FULL_PACKET: | ||
241 | psmouse->pktcnt = 0; | ||
242 | if (psmouse->out_of_sync) { | ||
243 | psmouse->out_of_sync = 0; | ||
244 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
245 | psmouse->name, psmouse->phys); | ||
246 | } | ||
247 | break; | ||
248 | |||
249 | case PSMOUSE_GOOD_DATA: | ||
250 | break; | ||
251 | } | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * psmouse_interrupt() handles incoming characters, either passing them | ||
257 | * for normal processing or gathering them as command response. | ||
183 | */ | 258 | */ |
184 | 259 | ||
185 | static irqreturn_t psmouse_interrupt(struct serio *serio, | 260 | static irqreturn_t psmouse_interrupt(struct serio *serio, |
186 | unsigned char data, unsigned int flags, struct pt_regs *regs) | 261 | unsigned char data, unsigned int flags, struct pt_regs *regs) |
187 | { | 262 | { |
188 | struct psmouse *psmouse = serio_get_drvdata(serio); | 263 | struct psmouse *psmouse = serio_get_drvdata(serio); |
189 | psmouse_ret_t rc; | ||
190 | 264 | ||
191 | if (psmouse->state == PSMOUSE_IGNORE) | 265 | if (psmouse->state == PSMOUSE_IGNORE) |
192 | goto out; | 266 | goto out; |
@@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
208 | if (ps2_handle_response(&psmouse->ps2dev, data)) | 282 | if (ps2_handle_response(&psmouse->ps2dev, data)) |
209 | goto out; | 283 | goto out; |
210 | 284 | ||
211 | if (psmouse->state == PSMOUSE_INITIALIZING) | 285 | if (psmouse->state <= PSMOUSE_RESYNCING) |
212 | goto out; | 286 | goto out; |
213 | 287 | ||
214 | if (psmouse->state == PSMOUSE_ACTIVATED && | 288 | if (psmouse->state == PSMOUSE_ACTIVATED && |
215 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { | 289 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { |
216 | printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", | 290 | printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", |
217 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 291 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
218 | psmouse->pktcnt = 0; | 292 | psmouse->badbyte = psmouse->packet[0]; |
293 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
294 | queue_work(kpsmoused_wq, &psmouse->resync_work); | ||
295 | goto out; | ||
219 | } | 296 | } |
220 | 297 | ||
221 | psmouse->last = jiffies; | ||
222 | psmouse->packet[psmouse->pktcnt++] = data; | 298 | psmouse->packet[psmouse->pktcnt++] = data; |
223 | 299 | /* | |
224 | if (psmouse->packet[0] == PSMOUSE_RET_BAT) { | 300 | * Check if this is a new device announcement (0xAA 0x00) |
301 | */ | ||
302 | if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { | ||
225 | if (psmouse->pktcnt == 1) | 303 | if (psmouse->pktcnt == 1) |
226 | goto out; | 304 | goto out; |
227 | 305 | ||
228 | if (psmouse->pktcnt == 2) { | 306 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { |
229 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { | 307 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
230 | psmouse->state = PSMOUSE_IGNORE; | 308 | serio_reconnect(serio); |
231 | serio_reconnect(serio); | 309 | goto out; |
232 | goto out; | ||
233 | } | ||
234 | if (psmouse->type == PSMOUSE_SYNAPTICS) { | ||
235 | /* neither 0xAA nor 0x00 are valid first bytes | ||
236 | * for a packet in absolute mode | ||
237 | */ | ||
238 | psmouse->pktcnt = 0; | ||
239 | goto out; | ||
240 | } | ||
241 | } | 310 | } |
242 | } | 311 | /* |
243 | 312 | * Not a new device, try processing first byte normally | |
244 | rc = psmouse->protocol_handler(psmouse, regs); | 313 | */ |
314 | psmouse->pktcnt = 1; | ||
315 | if (psmouse_handle_byte(psmouse, regs)) | ||
316 | goto out; | ||
245 | 317 | ||
246 | switch (rc) { | 318 | psmouse->packet[psmouse->pktcnt++] = data; |
247 | case PSMOUSE_BAD_DATA: | 319 | } |
248 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | ||
249 | psmouse->name, psmouse->phys, psmouse->pktcnt); | ||
250 | psmouse->pktcnt = 0; | ||
251 | 320 | ||
252 | if (++psmouse->out_of_sync == psmouse->resetafter) { | 321 | /* |
253 | psmouse->state = PSMOUSE_IGNORE; | 322 | * See if we need to force resync because mouse was idle for too long |
254 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 323 | */ |
255 | serio_reconnect(psmouse->ps2dev.serio); | 324 | if (psmouse->state == PSMOUSE_ACTIVATED && |
256 | } | 325 | psmouse->pktcnt == 1 && psmouse->resync_time && |
257 | break; | 326 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { |
327 | psmouse->badbyte = psmouse->packet[0]; | ||
328 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
329 | queue_work(kpsmoused_wq, &psmouse->resync_work); | ||
330 | goto out; | ||
331 | } | ||
258 | 332 | ||
259 | case PSMOUSE_FULL_PACKET: | 333 | psmouse->last = jiffies; |
260 | psmouse->pktcnt = 0; | 334 | psmouse_handle_byte(psmouse, regs); |
261 | if (psmouse->out_of_sync) { | ||
262 | psmouse->out_of_sync = 0; | ||
263 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
264 | psmouse->name, psmouse->phys); | ||
265 | } | ||
266 | break; | ||
267 | 335 | ||
268 | case PSMOUSE_GOOD_DATA: | 336 | out: |
269 | break; | ||
270 | } | ||
271 | out: | ||
272 | return IRQ_HANDLED; | 337 | return IRQ_HANDLED; |
273 | } | 338 | } |
274 | 339 | ||
@@ -752,21 +817,6 @@ static void psmouse_initialize(struct psmouse *psmouse) | |||
752 | } | 817 | } |
753 | 818 | ||
754 | /* | 819 | /* |
755 | * psmouse_set_state() sets new psmouse state and resets all flags and | ||
756 | * counters while holding serio lock so fighting with interrupt handler | ||
757 | * is not a concern. | ||
758 | */ | ||
759 | |||
760 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
761 | { | ||
762 | serio_pause_rx(psmouse->ps2dev.serio); | ||
763 | psmouse->state = new_state; | ||
764 | psmouse->pktcnt = psmouse->out_of_sync = 0; | ||
765 | psmouse->ps2dev.flags = 0; | ||
766 | serio_continue_rx(psmouse->ps2dev.serio); | ||
767 | } | ||
768 | |||
769 | /* | ||
770 | * psmouse_activate() enables the mouse so that we get motion reports from it. | 820 | * psmouse_activate() enables the mouse so that we get motion reports from it. |
771 | */ | 821 | */ |
772 | 822 | ||
@@ -794,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse) | |||
794 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 844 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
795 | } | 845 | } |
796 | 846 | ||
847 | /* | ||
848 | * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it. | ||
849 | */ | ||
850 | |||
851 | static int psmouse_poll(struct psmouse *psmouse) | ||
852 | { | ||
853 | return ps2_command(&psmouse->ps2dev, psmouse->packet, | ||
854 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); | ||
855 | } | ||
856 | |||
857 | |||
858 | /* | ||
859 | * psmouse_resync() attempts to re-validate current protocol. | ||
860 | */ | ||
861 | |||
862 | static void psmouse_resync(void *p) | ||
863 | { | ||
864 | struct psmouse *psmouse = p, *parent = NULL; | ||
865 | struct serio *serio = psmouse->ps2dev.serio; | ||
866 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | ||
867 | int failed = 0, enabled = 0; | ||
868 | int i; | ||
869 | |||
870 | down(&psmouse_sem); | ||
871 | |||
872 | if (psmouse->state != PSMOUSE_RESYNCING) | ||
873 | goto out; | ||
874 | |||
875 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | ||
876 | parent = serio_get_drvdata(serio->parent); | ||
877 | psmouse_deactivate(parent); | ||
878 | } | ||
879 | |||
880 | /* | ||
881 | * Some mice don't ACK commands sent while they are in the middle of | ||
882 | * transmitting motion packet. To avoid delay we use ps2_sendbyte() | ||
883 | * instead of ps2_command() which would wait for 200ms for an ACK | ||
884 | * that may never come. | ||
885 | * As an additional quirk ALPS touchpads may not only forget to ACK | ||
886 | * disable command but will stop reporting taps, so if we see that | ||
887 | * mouse at least once ACKs disable we will do full reconnect if ACK | ||
888 | * is missing. | ||
889 | */ | ||
890 | psmouse->num_resyncs++; | ||
891 | |||
892 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { | ||
893 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) | ||
894 | failed = 1; | ||
895 | } else | ||
896 | psmouse->acks_disable_command = 1; | ||
897 | |||
898 | /* | ||
899 | * Poll the mouse. If it was reset the packet will be shorter than | ||
900 | * psmouse->pktsize and ps2_command will fail. We do not expect and | ||
901 | * do not handle scenario when mouse "upgrades" its protocol while | ||
902 | * disconnected since it would require additional delay. If we ever | ||
903 | * see a mouse that does it we'll adjust the code. | ||
904 | */ | ||
905 | if (!failed) { | ||
906 | if (psmouse->poll(psmouse)) | ||
907 | failed = 1; | ||
908 | else { | ||
909 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
910 | for (i = 0; i < psmouse->pktsize; i++) { | ||
911 | psmouse->pktcnt++; | ||
912 | rc = psmouse->protocol_handler(psmouse, NULL); | ||
913 | if (rc != PSMOUSE_GOOD_DATA) | ||
914 | break; | ||
915 | } | ||
916 | if (rc != PSMOUSE_FULL_PACKET) | ||
917 | failed = 1; | ||
918 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
919 | } | ||
920 | } | ||
921 | /* | ||
922 | * Now try to enable mouse. We try to do that even if poll failed and also | ||
923 | * repeat our attempts 5 times, otherwise we may be left out with disabled | ||
924 | * mouse. | ||
925 | */ | ||
926 | for (i = 0; i < 5; i++) { | ||
927 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { | ||
928 | enabled = 1; | ||
929 | break; | ||
930 | } | ||
931 | msleep(200); | ||
932 | } | ||
933 | |||
934 | if (!enabled) { | ||
935 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", | ||
936 | psmouse->ps2dev.serio->phys); | ||
937 | failed = 1; | ||
938 | } | ||
939 | |||
940 | if (failed) { | ||
941 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
942 | printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n"); | ||
943 | serio_reconnect(serio); | ||
944 | } else | ||
945 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
946 | |||
947 | if (parent) | ||
948 | psmouse_activate(parent); | ||
949 | out: | ||
950 | up(&psmouse_sem); | ||
951 | } | ||
797 | 952 | ||
798 | /* | 953 | /* |
799 | * psmouse_cleanup() resets the mouse into power-on state. | 954 | * psmouse_cleanup() resets the mouse into power-on state. |
@@ -822,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio) | |||
822 | 977 | ||
823 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 978 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
824 | 979 | ||
980 | /* make sure we don't have a resync in progress */ | ||
981 | up(&psmouse_sem); | ||
982 | flush_workqueue(kpsmoused_wq); | ||
983 | down(&psmouse_sem); | ||
984 | |||
825 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 985 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
826 | parent = serio_get_drvdata(serio->parent); | 986 | parent = serio_get_drvdata(serio->parent); |
827 | psmouse_deactivate(parent); | 987 | psmouse_deactivate(parent); |
@@ -859,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto | |||
859 | 1019 | ||
860 | psmouse->set_rate = psmouse_set_rate; | 1020 | psmouse->set_rate = psmouse_set_rate; |
861 | psmouse->set_resolution = psmouse_set_resolution; | 1021 | psmouse->set_resolution = psmouse_set_resolution; |
1022 | psmouse->poll = psmouse_poll; | ||
862 | psmouse->protocol_handler = psmouse_process_byte; | 1023 | psmouse->protocol_handler = psmouse_process_byte; |
863 | psmouse->pktsize = 3; | 1024 | psmouse->pktsize = 3; |
864 | 1025 | ||
@@ -874,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto | |||
874 | else | 1035 | else |
875 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 1036 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); |
876 | 1037 | ||
1038 | /* | ||
1039 | * If mouse's packet size is 3 there is no point in polling the | ||
1040 | * device in hopes to detect protocol reset - we won't get less | ||
1041 | * than 3 bytes response anyhow. | ||
1042 | */ | ||
1043 | if (psmouse->pktsize == 3) | ||
1044 | psmouse->resync_time = 0; | ||
1045 | |||
1046 | /* | ||
1047 | * Some smart KVMs fake response to POLL command returning just | ||
1048 | * 3 bytes and messing up our resync logic, so if initial poll | ||
1049 | * fails we won't try polling the device anymore. Hopefully | ||
1050 | * such KVM will maintain initially selected protocol. | ||
1051 | */ | ||
1052 | if (psmouse->resync_time && psmouse->poll(psmouse)) | ||
1053 | psmouse->resync_time = 0; | ||
1054 | |||
877 | sprintf(psmouse->devname, "%s %s %s", | 1055 | sprintf(psmouse->devname, "%s %s %s", |
878 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | 1056 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); |
879 | 1057 | ||
@@ -914,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
914 | goto out; | 1092 | goto out; |
915 | 1093 | ||
916 | ps2_init(&psmouse->ps2dev, serio); | 1094 | ps2_init(&psmouse->ps2dev, serio); |
1095 | INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); | ||
917 | psmouse->dev = input_dev; | 1096 | psmouse->dev = input_dev; |
918 | sprintf(psmouse->phys, "%s/input0", serio->phys); | 1097 | sprintf(psmouse->phys, "%s/input0", serio->phys); |
919 | 1098 | ||
@@ -934,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
934 | psmouse->rate = psmouse_rate; | 1113 | psmouse->rate = psmouse_rate; |
935 | psmouse->resolution = psmouse_resolution; | 1114 | psmouse->resolution = psmouse_resolution; |
936 | psmouse->resetafter = psmouse_resetafter; | 1115 | psmouse->resetafter = psmouse_resetafter; |
1116 | psmouse->resync_time = parent ? 0 : psmouse_resync_time; | ||
937 | psmouse->smartscroll = psmouse_smartscroll; | 1117 | psmouse->smartscroll = psmouse_smartscroll; |
938 | 1118 | ||
939 | psmouse_switch_protocol(psmouse, NULL); | 1119 | psmouse_switch_protocol(psmouse, NULL); |
@@ -1278,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | |||
1278 | 1458 | ||
1279 | static int __init psmouse_init(void) | 1459 | static int __init psmouse_init(void) |
1280 | { | 1460 | { |
1461 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); | ||
1462 | if (!kpsmoused_wq) { | ||
1463 | printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); | ||
1464 | return -ENOMEM; | ||
1465 | } | ||
1466 | |||
1281 | serio_register_driver(&psmouse_drv); | 1467 | serio_register_driver(&psmouse_drv); |
1468 | |||
1282 | return 0; | 1469 | return 0; |
1283 | } | 1470 | } |
1284 | 1471 | ||
1285 | static void __exit psmouse_exit(void) | 1472 | static void __exit psmouse_exit(void) |
1286 | { | 1473 | { |
1287 | serio_unregister_driver(&psmouse_drv); | 1474 | serio_unregister_driver(&psmouse_drv); |
1475 | destroy_workqueue(kpsmoused_wq); | ||
1288 | } | 1476 | } |
1289 | 1477 | ||
1290 | module_init(psmouse_init); | 1478 | module_init(psmouse_init); |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 7c4192bd1279..4d9107fba6a1 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #define PSMOUSE_CMD_GETINFO 0x03e9 | 7 | #define PSMOUSE_CMD_GETINFO 0x03e9 |
8 | #define PSMOUSE_CMD_SETSTREAM 0x00ea | 8 | #define PSMOUSE_CMD_SETSTREAM 0x00ea |
9 | #define PSMOUSE_CMD_SETPOLL 0x00f0 | 9 | #define PSMOUSE_CMD_SETPOLL 0x00f0 |
10 | #define PSMOUSE_CMD_POLL 0x03eb | 10 | #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ |
11 | #define PSMOUSE_CMD_GETID 0x02f2 | 11 | #define PSMOUSE_CMD_GETID 0x02f2 |
12 | #define PSMOUSE_CMD_SETRATE 0x10f3 | 12 | #define PSMOUSE_CMD_SETRATE 0x10f3 |
13 | #define PSMOUSE_CMD_ENABLE 0x00f4 | 13 | #define PSMOUSE_CMD_ENABLE 0x00f4 |
@@ -23,6 +23,7 @@ | |||
23 | enum psmouse_state { | 23 | enum psmouse_state { |
24 | PSMOUSE_IGNORE, | 24 | PSMOUSE_IGNORE, |
25 | PSMOUSE_INITIALIZING, | 25 | PSMOUSE_INITIALIZING, |
26 | PSMOUSE_RESYNCING, | ||
26 | PSMOUSE_CMD_MODE, | 27 | PSMOUSE_CMD_MODE, |
27 | PSMOUSE_ACTIVATED, | 28 | PSMOUSE_ACTIVATED, |
28 | }; | 29 | }; |
@@ -38,15 +39,19 @@ struct psmouse { | |||
38 | void *private; | 39 | void *private; |
39 | struct input_dev *dev; | 40 | struct input_dev *dev; |
40 | struct ps2dev ps2dev; | 41 | struct ps2dev ps2dev; |
42 | struct work_struct resync_work; | ||
41 | char *vendor; | 43 | char *vendor; |
42 | char *name; | 44 | char *name; |
43 | unsigned char packet[8]; | 45 | unsigned char packet[8]; |
46 | unsigned char badbyte; | ||
44 | unsigned char pktcnt; | 47 | unsigned char pktcnt; |
45 | unsigned char pktsize; | 48 | unsigned char pktsize; |
46 | unsigned char type; | 49 | unsigned char type; |
50 | unsigned char acks_disable_command; | ||
47 | unsigned int model; | 51 | unsigned int model; |
48 | unsigned long last; | 52 | unsigned long last; |
49 | unsigned long out_of_sync; | 53 | unsigned long out_of_sync; |
54 | unsigned long num_resyncs; | ||
50 | enum psmouse_state state; | 55 | enum psmouse_state state; |
51 | char devname[64]; | 56 | char devname[64]; |
52 | char phys[32]; | 57 | char phys[32]; |
@@ -54,6 +59,7 @@ struct psmouse { | |||
54 | unsigned int rate; | 59 | unsigned int rate; |
55 | unsigned int resolution; | 60 | unsigned int resolution; |
56 | unsigned int resetafter; | 61 | unsigned int resetafter; |
62 | unsigned int resync_time; | ||
57 | unsigned int smartscroll; /* Logitech only */ | 63 | unsigned int smartscroll; /* Logitech only */ |
58 | 64 | ||
59 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); | 65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); |
@@ -62,6 +68,7 @@ struct psmouse { | |||
62 | 68 | ||
63 | int (*reconnect)(struct psmouse *psmouse); | 69 | int (*reconnect)(struct psmouse *psmouse); |
64 | void (*disconnect)(struct psmouse *psmouse); | 70 | void (*disconnect)(struct psmouse *psmouse); |
71 | int (*poll)(struct psmouse *psmouse); | ||
65 | 72 | ||
66 | void (*pt_activate)(struct psmouse *psmouse); | 73 | void (*pt_activate)(struct psmouse *psmouse); |
67 | void (*pt_deactivate)(struct psmouse *psmouse); | 74 | void (*pt_deactivate)(struct psmouse *psmouse); |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 97cdfd6acaca..2051bec2c394 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
652 | psmouse->disconnect = synaptics_disconnect; | 652 | psmouse->disconnect = synaptics_disconnect; |
653 | psmouse->reconnect = synaptics_reconnect; | 653 | psmouse->reconnect = synaptics_reconnect; |
654 | psmouse->pktsize = 6; | 654 | psmouse->pktsize = 6; |
655 | /* Synaptics can usually stay in sync without extra help */ | ||
656 | psmouse->resync_time = 0; | ||
655 | 657 | ||
656 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) | 658 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) |
657 | synaptics_pt_create(psmouse); | 659 | synaptics_pt_create(psmouse); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2d2f9fb3aded..a4c6f3522723 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -173,6 +173,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
173 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), | 173 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), |
174 | }, | 174 | }, |
175 | }, | 175 | }, |
176 | { | ||
177 | .ident = "Sony Vaio FS-115b", | ||
178 | .matches = { | ||
179 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
180 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), | ||
181 | }, | ||
182 | }, | ||
176 | { } | 183 | { } |
177 | }; | 184 | }; |
178 | 185 | ||
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 509dd0a04c54..5246b35301de 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
@@ -37,6 +37,16 @@ config USB_HIDINPUT | |||
37 | 37 | ||
38 | If unsure, say Y. | 38 | If unsure, say Y. |
39 | 39 | ||
40 | config USB_HIDINPUT_POWERBOOK | ||
41 | bool "Enable support for iBook/PowerBook special keys" | ||
42 | default n | ||
43 | depends on USB_HIDINPUT | ||
44 | help | ||
45 | Say Y here if you want support for the special keys (Fn, Numlock) on | ||
46 | Apple iBooks and PowerBooks. | ||
47 | |||
48 | If unsure, say N. | ||
49 | |||
40 | config HID_FF | 50 | config HID_FF |
41 | bool "Force feedback support (EXPERIMENTAL)" | 51 | bool "Force feedback support (EXPERIMENTAL)" |
42 | depends on USB_HIDINPUT && EXPERIMENTAL | 52 | depends on USB_HIDINPUT && EXPERIMENTAL |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 5f52979af1c7..a91e72c41415 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid) | |||
1450 | #define USB_VENDOR_ID_APPLE 0x05ac | 1450 | #define USB_VENDOR_ID_APPLE 0x05ac |
1451 | #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 | 1451 | #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 |
1452 | 1452 | ||
1453 | #define USB_VENDOR_ID_CHERRY 0x046a | ||
1454 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | ||
1455 | |||
1453 | /* | 1456 | /* |
1454 | * Alphabetically sorted blacklist by quirk type. | 1457 | * Alphabetically sorted blacklist by quirk type. |
1455 | */ | 1458 | */ |
@@ -1580,6 +1583,16 @@ static const struct hid_blacklist { | |||
1580 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, | 1583 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, |
1581 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, | 1584 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, |
1582 | 1585 | ||
1586 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, | ||
1587 | |||
1588 | { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1589 | { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1590 | { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1591 | { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1592 | { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1593 | { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1594 | { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1595 | |||
1583 | { 0, 0 } | 1596 | { 0, 0 } |
1584 | }; | 1597 | }; |
1585 | 1598 | ||
@@ -1626,6 +1639,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | |||
1626 | usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); | 1639 | usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); |
1627 | } | 1640 | } |
1628 | 1641 | ||
1642 | /* | ||
1643 | * Cherry Cymotion keyboard have an invalid HID report descriptor, | ||
1644 | * that needs fixing before we can parse it. | ||
1645 | */ | ||
1646 | |||
1647 | static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) | ||
1648 | { | ||
1649 | if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | ||
1650 | info("Fixing up Cherry Cymotion report descriptor"); | ||
1651 | rdesc[11] = rdesc[16] = 0xff; | ||
1652 | rdesc[12] = rdesc[17] = 0x03; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1629 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | 1656 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) |
1630 | { | 1657 | { |
1631 | struct usb_host_interface *interface = intf->cur_altsetting; | 1658 | struct usb_host_interface *interface = intf->cur_altsetting; |
@@ -1673,6 +1700,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1673 | return NULL; | 1700 | return NULL; |
1674 | } | 1701 | } |
1675 | 1702 | ||
1703 | if ((quirks & HID_QUIRK_CYMOTION)) | ||
1704 | hid_fixup_cymotion_descriptor(rdesc, rsize); | ||
1705 | |||
1676 | #ifdef DEBUG_DATA | 1706 | #ifdef DEBUG_DATA |
1677 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | 1707 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); |
1678 | for (n = 0; n < rsize; n++) | 1708 | for (n = 0; n < rsize; n++) |
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 192a03b28971..cb0d80f49252 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c | |||
@@ -73,6 +73,160 @@ static const struct { | |||
73 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) | 73 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) |
74 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) | 74 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) |
75 | 75 | ||
76 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | ||
77 | |||
78 | struct hidinput_key_translation { | ||
79 | u16 from; | ||
80 | u16 to; | ||
81 | u8 flags; | ||
82 | }; | ||
83 | |||
84 | #define POWERBOOK_FLAG_FKEY 0x01 | ||
85 | |||
86 | static struct hidinput_key_translation powerbook_fn_keys[] = { | ||
87 | { KEY_BACKSPACE, KEY_DELETE }, | ||
88 | { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY }, | ||
89 | { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY }, | ||
90 | { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY }, | ||
91 | { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY }, | ||
92 | { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY }, | ||
93 | { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY }, | ||
94 | { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY }, | ||
95 | { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY }, | ||
96 | { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY }, | ||
97 | { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY }, | ||
98 | { KEY_UP, KEY_PAGEUP }, | ||
99 | { KEY_DOWN, KEY_PAGEDOWN }, | ||
100 | { KEY_LEFT, KEY_HOME }, | ||
101 | { KEY_RIGHT, KEY_END }, | ||
102 | { } | ||
103 | }; | ||
104 | |||
105 | static struct hidinput_key_translation powerbook_numlock_keys[] = { | ||
106 | { KEY_J, KEY_KP1 }, | ||
107 | { KEY_K, KEY_KP2 }, | ||
108 | { KEY_L, KEY_KP3 }, | ||
109 | { KEY_U, KEY_KP4 }, | ||
110 | { KEY_I, KEY_KP5 }, | ||
111 | { KEY_O, KEY_KP6 }, | ||
112 | { KEY_7, KEY_KP7 }, | ||
113 | { KEY_8, KEY_KP8 }, | ||
114 | { KEY_9, KEY_KP9 }, | ||
115 | { KEY_M, KEY_KP0 }, | ||
116 | { KEY_DOT, KEY_KPDOT }, | ||
117 | { KEY_SLASH, KEY_KPPLUS }, | ||
118 | { KEY_SEMICOLON, KEY_KPMINUS }, | ||
119 | { KEY_P, KEY_KPASTERISK }, | ||
120 | { KEY_MINUS, KEY_KPEQUAL }, | ||
121 | { KEY_0, KEY_KPSLASH }, | ||
122 | { KEY_F6, KEY_NUMLOCK }, | ||
123 | { KEY_KPENTER, KEY_KPENTER }, | ||
124 | { KEY_BACKSPACE, KEY_BACKSPACE }, | ||
125 | { } | ||
126 | }; | ||
127 | |||
128 | static int usbhid_pb_fnmode = 1; | ||
129 | module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644); | ||
130 | MODULE_PARM_DESC(pb_fnmode, | ||
131 | "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)"); | ||
132 | |||
133 | static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from) | ||
134 | { | ||
135 | struct hidinput_key_translation *trans; | ||
136 | |||
137 | /* Look for the translation */ | ||
138 | for (trans = table; trans->from; trans++) | ||
139 | if (trans->from == from) | ||
140 | return trans; | ||
141 | |||
142 | return NULL; | ||
143 | } | ||
144 | |||
145 | static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, | ||
146 | struct hid_usage *usage, __s32 value) | ||
147 | { | ||
148 | struct hidinput_key_translation *trans; | ||
149 | |||
150 | if (usage->code == KEY_FN) { | ||
151 | if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON; | ||
152 | else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON; | ||
153 | |||
154 | input_event(input, usage->type, usage->code, value); | ||
155 | |||
156 | return 1; | ||
157 | } | ||
158 | |||
159 | if (usbhid_pb_fnmode) { | ||
160 | int do_translate; | ||
161 | |||
162 | trans = find_translation(powerbook_fn_keys, usage->code); | ||
163 | if (trans) { | ||
164 | if (test_bit(usage->code, hid->pb_pressed_fn)) | ||
165 | do_translate = 1; | ||
166 | else if (trans->flags & POWERBOOK_FLAG_FKEY) | ||
167 | do_translate = | ||
168 | (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) || | ||
169 | (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)); | ||
170 | else | ||
171 | do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON); | ||
172 | |||
173 | if (do_translate) { | ||
174 | if (value) | ||
175 | set_bit(usage->code, hid->pb_pressed_fn); | ||
176 | else | ||
177 | clear_bit(usage->code, hid->pb_pressed_fn); | ||
178 | |||
179 | input_event(input, usage->type, trans->to, value); | ||
180 | |||
181 | return 1; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | if (test_bit(usage->code, hid->pb_pressed_numlock) || | ||
186 | test_bit(LED_NUML, input->led)) { | ||
187 | trans = find_translation(powerbook_numlock_keys, usage->code); | ||
188 | |||
189 | if (trans) { | ||
190 | if (value) | ||
191 | set_bit(usage->code, hid->pb_pressed_numlock); | ||
192 | else | ||
193 | clear_bit(usage->code, hid->pb_pressed_numlock); | ||
194 | |||
195 | input_event(input, usage->type, trans->to, value); | ||
196 | } | ||
197 | |||
198 | return 1; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static void hidinput_pb_setup(struct input_dev *input) | ||
206 | { | ||
207 | struct hidinput_key_translation *trans; | ||
208 | |||
209 | set_bit(KEY_NUMLOCK, input->keybit); | ||
210 | |||
211 | /* Enable all needed keys */ | ||
212 | for (trans = powerbook_fn_keys; trans->from; trans++) | ||
213 | set_bit(trans->to, input->keybit); | ||
214 | |||
215 | for (trans = powerbook_numlock_keys; trans->from; trans++) | ||
216 | set_bit(trans->to, input->keybit); | ||
217 | } | ||
218 | #else | ||
219 | static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, | ||
220 | struct hid_usage *usage, __s32 value) | ||
221 | { | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static inline void hidinput_pb_setup(struct input_dev *input) | ||
226 | { | ||
227 | } | ||
228 | #endif | ||
229 | |||
76 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 230 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
77 | struct hid_usage *usage) | 231 | struct hid_usage *usage) |
78 | { | 232 | { |
@@ -135,8 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
135 | case HID_UP_SIMULATION: | 289 | case HID_UP_SIMULATION: |
136 | 290 | ||
137 | switch (usage->hid & 0xffff) { | 291 | switch (usage->hid & 0xffff) { |
138 | case 0xba: map_abs(ABS_RUDDER); break; | 292 | case 0xba: map_abs(ABS_RUDDER); break; |
139 | case 0xbb: map_abs(ABS_THROTTLE); break; | 293 | case 0xbb: map_abs(ABS_THROTTLE); break; |
294 | case 0xc4: map_abs(ABS_GAS); break; | ||
295 | case 0xc5: map_abs(ABS_BRAKE); break; | ||
296 | case 0xc8: map_abs(ABS_WHEEL); break; | ||
140 | default: goto ignore; | 297 | default: goto ignore; |
141 | } | 298 | } |
142 | break; | 299 | break; |
@@ -289,11 +446,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
289 | case 0x226: map_key_clear(KEY_STOP); break; | 446 | case 0x226: map_key_clear(KEY_STOP); break; |
290 | case 0x227: map_key_clear(KEY_REFRESH); break; | 447 | case 0x227: map_key_clear(KEY_REFRESH); break; |
291 | case 0x22a: map_key_clear(KEY_BOOKMARKS); break; | 448 | case 0x22a: map_key_clear(KEY_BOOKMARKS); break; |
449 | case 0x233: map_key_clear(KEY_SCROLLUP); break; | ||
450 | case 0x234: map_key_clear(KEY_SCROLLDOWN); break; | ||
292 | case 0x238: map_rel(REL_HWHEEL); break; | 451 | case 0x238: map_rel(REL_HWHEEL); break; |
293 | case 0x279: map_key_clear(KEY_REDO); break; | 452 | case 0x279: map_key_clear(KEY_REDO); break; |
294 | case 0x289: map_key_clear(KEY_REPLY); break; | 453 | case 0x289: map_key_clear(KEY_REPLY); break; |
295 | case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; | 454 | case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; |
296 | case 0x28c: map_key_clear(KEY_SEND); break; | 455 | case 0x28c: map_key_clear(KEY_SEND); break; |
456 | |||
457 | /* Reported on a Cherry Cymotion keyboard */ | ||
458 | case 0x301: map_key_clear(KEY_PROG1); break; | ||
459 | case 0x302: map_key_clear(KEY_PROG2); break; | ||
460 | case 0x303: map_key_clear(KEY_PROG3); break; | ||
461 | |||
297 | default: goto ignore; | 462 | default: goto ignore; |
298 | } | 463 | } |
299 | break; | 464 | break; |
@@ -325,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
325 | 490 | ||
326 | set_bit(EV_REP, input->evbit); | 491 | set_bit(EV_REP, input->evbit); |
327 | switch(usage->hid & HID_USAGE) { | 492 | switch(usage->hid & HID_USAGE) { |
328 | case 0x003: map_key_clear(KEY_FN); break; | 493 | case 0x003: |
494 | /* The fn key on Apple PowerBooks */ | ||
495 | map_key_clear(KEY_FN); | ||
496 | hidinput_pb_setup(input); | ||
497 | break; | ||
498 | |||
329 | default: goto ignore; | 499 | default: goto ignore; |
330 | } | 500 | } |
331 | break; | 501 | break; |
@@ -482,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
482 | return; | 652 | return; |
483 | } | 653 | } |
484 | 654 | ||
655 | if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value)) | ||
656 | return; | ||
657 | |||
485 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 658 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
486 | int hat_dir = usage->hat_dir; | 659 | int hat_dir = usage->hat_dir; |
487 | if (!hat_dir) | 660 | if (!hat_dir) |
@@ -524,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
524 | return; | 697 | return; |
525 | } | 698 | } |
526 | 699 | ||
527 | if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ | 700 | if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ |
528 | return; | 701 | return; |
529 | 702 | ||
530 | input_event(input, usage->type, usage->code, value); | 703 | input_event(input, usage->type, usage->code, value); |
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index ee48a2276104..8b0d4346ce9c 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
@@ -235,17 +235,20 @@ struct hid_item { | |||
235 | * HID device quirks. | 235 | * HID device quirks. |
236 | */ | 236 | */ |
237 | 237 | ||
238 | #define HID_QUIRK_INVERT 0x001 | 238 | #define HID_QUIRK_INVERT 0x00000001 |
239 | #define HID_QUIRK_NOTOUCH 0x002 | 239 | #define HID_QUIRK_NOTOUCH 0x00000002 |
240 | #define HID_QUIRK_IGNORE 0x004 | 240 | #define HID_QUIRK_IGNORE 0x00000004 |
241 | #define HID_QUIRK_NOGET 0x008 | 241 | #define HID_QUIRK_NOGET 0x00000008 |
242 | #define HID_QUIRK_HIDDEV 0x010 | 242 | #define HID_QUIRK_HIDDEV 0x00000010 |
243 | #define HID_QUIRK_BADPAD 0x020 | 243 | #define HID_QUIRK_BADPAD 0x00000020 |
244 | #define HID_QUIRK_MULTI_INPUT 0x040 | 244 | #define HID_QUIRK_MULTI_INPUT 0x00000040 |
245 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 | 245 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 |
246 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 | 246 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 |
247 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 | 247 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 |
248 | #define HID_QUIRK_2WHEEL_POWERMOUSE 0x400 | 248 | #define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400 |
249 | #define HID_QUIRK_CYMOTION 0x00000800 | ||
250 | #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 | ||
251 | #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 | ||
249 | 252 | ||
250 | /* | 253 | /* |
251 | * This is the global environment of the parser. This information is | 254 | * This is the global environment of the parser. This information is |
@@ -431,6 +434,11 @@ struct hid_device { /* device report descriptor */ | |||
431 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ | 434 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ |
432 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, | 435 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, |
433 | unsigned int type, unsigned int code, int value); | 436 | unsigned int type, unsigned int code, int value); |
437 | |||
438 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | ||
439 | unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; | ||
440 | unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; | ||
441 | #endif | ||
434 | }; | 442 | }; |
435 | 443 | ||
436 | #define HID_GLOBAL_STACK_SIZE 4 | 444 | #define HID_GLOBAL_STACK_SIZE 4 |
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index 19e015d171aa..d9d9f656b8c9 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c | |||
@@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev, | |||
259 | int hid_pid_init(struct hid_device *hid) | 259 | int hid_pid_init(struct hid_device *hid) |
260 | { | 260 | { |
261 | struct hid_ff_pid *private; | 261 | struct hid_ff_pid *private; |
262 | struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); | 262 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); |
263 | struct input_dev *input_dev = hidinput->input; | 263 | struct input_dev *input_dev = hidinput->input; |
264 | 264 | ||
265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); | 265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); |
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index 48df4cfd5a42..d3e15df9e815 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c | |||
@@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE); | |||
95 | enum { | 95 | enum { |
96 | PENPARTNER = 0, | 96 | PENPARTNER = 0, |
97 | GRAPHIRE, | 97 | GRAPHIRE, |
98 | G4, | 98 | WACOM_G4, |
99 | PL, | 99 | PL, |
100 | INTUOS, | 100 | INTUOS, |
101 | INTUOS3, | 101 | INTUOS3, |
@@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
373 | 373 | ||
374 | case 2: /* Mouse with wheel */ | 374 | case 2: /* Mouse with wheel */ |
375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); | 375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); |
376 | if (wacom->features->type == G4) { | 376 | if (wacom->features->type == WACOM_G4) { |
377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); | 377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); |
378 | input_report_rel(dev, REL_WHEEL, rw); | 378 | input_report_rel(dev, REL_WHEEL, rw); |
379 | } else | 379 | } else |
@@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
385 | id = CURSOR_DEVICE_ID; | 385 | id = CURSOR_DEVICE_ID; |
386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | 386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); |
387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | 387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); |
388 | if (wacom->features->type == G4) | 388 | if (wacom->features->type == WACOM_G4) |
389 | input_report_abs(dev, ABS_DISTANCE, data[6]); | 389 | input_report_abs(dev, ABS_DISTANCE, data[6]); |
390 | else | 390 | else |
391 | input_report_abs(dev, ABS_DISTANCE, data[7]); | 391 | input_report_abs(dev, ABS_DISTANCE, data[7]); |
@@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
410 | input_sync(dev); | 410 | input_sync(dev); |
411 | 411 | ||
412 | /* send pad data */ | 412 | /* send pad data */ |
413 | if (wacom->features->type == G4) { | 413 | if (wacom->features->type == WACOM_G4) { |
414 | /* fist time sending pad data */ | 414 | /* fist time sending pad data */ |
415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { | 415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { |
416 | wacom->id[1] = 0; | 416 | wacom->id[1] = 0; |
@@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = { | |||
713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
715 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 715 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
716 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq }, | 716 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq }, |
717 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq }, | 717 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq }, |
718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, | 719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, |
720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
@@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); | 859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); |
860 | 860 | ||
861 | switch (wacom->features->type) { | 861 | switch (wacom->features->type) { |
862 | case G4: | 862 | case WACOM_G4: |
863 | input_dev->evbit[0] |= BIT(EV_MSC); | 863 | input_dev->evbit[0] |= BIT(EV_MSC); |
864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | 864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); |
865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | 865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); |