Commit e7de369050534025b33aab1033358bf47a577e4d
Exists in
master
and in
4 other branches
Merge master.kernel.org:/pub/scm/linux/kernel/git/dtor/input
Showing 12 changed files Side-by-side Diff
- drivers/input/mouse/alps.c
- drivers/input/mouse/logips2pp.c
- drivers/input/mouse/psmouse-base.c
- drivers/input/mouse/psmouse.h
- drivers/input/mouse/synaptics.c
- drivers/input/serio/i8042-x86ia64io.h
- drivers/usb/input/Kconfig
- drivers/usb/input/hid-core.c
- drivers/usb/input/hid-input.c
- drivers/usb/input/hid.h
- drivers/usb/input/pid.c
- drivers/usb/input/wacom.c
drivers/input/mouse/alps.c
| ... | ... | @@ -348,6 +348,40 @@ |
| 348 | 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 | 385 | static int alps_reconnect(struct psmouse *psmouse) |
| 352 | 386 | { |
| 353 | 387 | struct alps_data *priv = psmouse->private; |
| 354 | 388 | |
| ... | ... | @@ -451,9 +485,13 @@ |
| 451 | 485 | input_register_device(priv->dev2); |
| 452 | 486 | |
| 453 | 487 | psmouse->protocol_handler = alps_process_byte; |
| 488 | + psmouse->poll = alps_poll; | |
| 454 | 489 | psmouse->disconnect = alps_disconnect; |
| 455 | 490 | psmouse->reconnect = alps_reconnect; |
| 456 | 491 | psmouse->pktsize = 6; |
| 492 | + | |
| 493 | + /* We are having trouble resyncing ALPS touchpads so disable it for now */ | |
| 494 | + psmouse->resync_time = 0; | |
| 457 | 495 | |
| 458 | 496 | return 0; |
| 459 | 497 |
drivers/input/mouse/logips2pp.c
drivers/input/mouse/psmouse-base.c
| ... | ... | @@ -54,10 +54,14 @@ |
| 54 | 54 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); |
| 55 | 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 | 58 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); |
| 59 | 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 | 65 | PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, |
| 62 | 66 | NULL, |
| 63 | 67 | psmouse_attr_show_protocol, psmouse_attr_set_protocol); |
| 64 | 68 | |
| ... | ... | @@ -70,12 +74,16 @@ |
| 70 | 74 | PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, |
| 71 | 75 | (void *) offsetof(struct psmouse, resetafter), |
| 72 | 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 | 81 | static struct attribute *psmouse_attributes[] = { |
| 75 | 82 | &psmouse_attr_protocol.dattr.attr, |
| 76 | 83 | &psmouse_attr_rate.dattr.attr, |
| 77 | 84 | &psmouse_attr_resolution.dattr.attr, |
| 78 | 85 | &psmouse_attr_resetafter.dattr.attr, |
| 86 | + &psmouse_attr_resync_time.dattr.attr, | |
| 79 | 87 | NULL |
| 80 | 88 | }; |
| 81 | 89 | |
| ... | ... | @@ -98,6 +106,8 @@ |
| 98 | 106 | */ |
| 99 | 107 | static DECLARE_MUTEX(psmouse_sem); |
| 100 | 108 | |
| 109 | +static struct workqueue_struct *kpsmoused_wq; | |
| 110 | + | |
| 101 | 111 | struct psmouse_protocol { |
| 102 | 112 | enum psmouse_type type; |
| 103 | 113 | char *name; |
| 104 | 114 | |
| 105 | 115 | |
| ... | ... | @@ -178,15 +188,79 @@ |
| 178 | 188 | } |
| 179 | 189 | |
| 180 | 190 | /* |
| 181 | - * psmouse_interrupt() handles incoming characters, either gathering them into | |
| 182 | - * packets or passing them to the command routine as command output. | |
| 191 | + * __psmouse_set_state() sets new psmouse state and resets all flags. | |
| 183 | 192 | */ |
| 184 | 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. | |
| 258 | + */ | |
| 259 | + | |
| 185 | 260 | static irqreturn_t psmouse_interrupt(struct serio *serio, |
| 186 | 261 | unsigned char data, unsigned int flags, struct pt_regs *regs) |
| 187 | 262 | { |
| 188 | 263 | struct psmouse *psmouse = serio_get_drvdata(serio); |
| 189 | - psmouse_ret_t rc; | |
| 190 | 264 | |
| 191 | 265 | if (psmouse->state == PSMOUSE_IGNORE) |
| 192 | 266 | goto out; |
| 193 | 267 | |
| 194 | 268 | |
| 195 | 269 | |
| 196 | 270 | |
| 197 | 271 | |
| 198 | 272 | |
| 199 | 273 | |
| 200 | 274 | |
| 201 | 275 | |
| ... | ... | @@ -208,67 +282,58 @@ |
| 208 | 282 | if (ps2_handle_response(&psmouse->ps2dev, data)) |
| 209 | 283 | goto out; |
| 210 | 284 | |
| 211 | - if (psmouse->state == PSMOUSE_INITIALIZING) | |
| 285 | + if (psmouse->state <= PSMOUSE_RESYNCING) | |
| 212 | 286 | goto out; |
| 213 | 287 | |
| 214 | 288 | if (psmouse->state == PSMOUSE_ACTIVATED && |
| 215 | 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 | 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 | 298 | psmouse->packet[psmouse->pktcnt++] = data; |
| 223 | - | |
| 224 | - if (psmouse->packet[0] == PSMOUSE_RET_BAT) { | |
| 299 | +/* | |
| 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 | 303 | if (psmouse->pktcnt == 1) |
| 226 | 304 | goto out; |
| 227 | 305 | |
| 228 | - if (psmouse->pktcnt == 2) { | |
| 229 | - if (psmouse->packet[1] == PSMOUSE_RET_ID) { | |
| 230 | - psmouse->state = PSMOUSE_IGNORE; | |
| 231 | - serio_reconnect(serio); | |
| 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 | - } | |
| 306 | + if (psmouse->packet[1] == PSMOUSE_RET_ID) { | |
| 307 | + __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | |
| 308 | + serio_reconnect(serio); | |
| 309 | + goto out; | |
| 241 | 310 | } |
| 311 | +/* | |
| 312 | + * Not a new device, try processing first byte normally | |
| 313 | + */ | |
| 314 | + psmouse->pktcnt = 1; | |
| 315 | + if (psmouse_handle_byte(psmouse, regs)) | |
| 316 | + goto out; | |
| 317 | + | |
| 318 | + psmouse->packet[psmouse->pktcnt++] = data; | |
| 242 | 319 | } |
| 243 | 320 | |
| 244 | - rc = psmouse->protocol_handler(psmouse, regs); | |
| 321 | +/* | |
| 322 | + * See if we need to force resync because mouse was idle for too long | |
| 323 | + */ | |
| 324 | + if (psmouse->state == PSMOUSE_ACTIVATED && | |
| 325 | + psmouse->pktcnt == 1 && psmouse->resync_time && | |
| 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 | + } | |
| 245 | 332 | |
| 246 | - switch (rc) { | |
| 247 | - case PSMOUSE_BAD_DATA: | |
| 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; | |
| 333 | + psmouse->last = jiffies; | |
| 334 | + psmouse_handle_byte(psmouse, regs); | |
| 251 | 335 | |
| 252 | - if (++psmouse->out_of_sync == psmouse->resetafter) { | |
| 253 | - psmouse->state = PSMOUSE_IGNORE; | |
| 254 | - printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | |
| 255 | - serio_reconnect(psmouse->ps2dev.serio); | |
| 256 | - } | |
| 257 | - break; | |
| 258 | - | |
| 259 | - case PSMOUSE_FULL_PACKET: | |
| 260 | - psmouse->pktcnt = 0; | |
| 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 | - | |
| 268 | - case PSMOUSE_GOOD_DATA: | |
| 269 | - break; | |
| 270 | - } | |
| 271 | -out: | |
| 336 | + out: | |
| 272 | 337 | return IRQ_HANDLED; |
| 273 | 338 | } |
| 274 | 339 | |
| ... | ... | @@ -752,21 +817,6 @@ |
| 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 | 820 | * psmouse_activate() enables the mouse so that we get motion reports from it. |
| 771 | 821 | */ |
| 772 | 822 | |
| 773 | 823 | |
| 774 | 824 | |
| ... | ... | @@ -794,8 +844,113 @@ |
| 794 | 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 | + */ | |
| 797 | 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 | + | |
| 798 | 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 | +} | |
| 952 | + | |
| 953 | +/* | |
| 799 | 954 | * psmouse_cleanup() resets the mouse into power-on state. |
| 800 | 955 | */ |
| 801 | 956 | |
| ... | ... | @@ -822,6 +977,11 @@ |
| 822 | 977 | |
| 823 | 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 | 985 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
| 826 | 986 | parent = serio_get_drvdata(serio->parent); |
| 827 | 987 | psmouse_deactivate(parent); |
| ... | ... | @@ -859,6 +1019,7 @@ |
| 859 | 1019 | |
| 860 | 1020 | psmouse->set_rate = psmouse_set_rate; |
| 861 | 1021 | psmouse->set_resolution = psmouse_set_resolution; |
| 1022 | + psmouse->poll = psmouse_poll; | |
| 862 | 1023 | psmouse->protocol_handler = psmouse_process_byte; |
| 863 | 1024 | psmouse->pktsize = 3; |
| 864 | 1025 | |
| ... | ... | @@ -874,6 +1035,23 @@ |
| 874 | 1035 | else |
| 875 | 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 | 1055 | sprintf(psmouse->devname, "%s %s %s", |
| 878 | 1056 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); |
| 879 | 1057 | |
| ... | ... | @@ -914,6 +1092,7 @@ |
| 914 | 1092 | goto out; |
| 915 | 1093 | |
| 916 | 1094 | ps2_init(&psmouse->ps2dev, serio); |
| 1095 | + INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); | |
| 917 | 1096 | psmouse->dev = input_dev; |
| 918 | 1097 | sprintf(psmouse->phys, "%s/input0", serio->phys); |
| 919 | 1098 | |
| ... | ... | @@ -934,6 +1113,7 @@ |
| 934 | 1113 | psmouse->rate = psmouse_rate; |
| 935 | 1114 | psmouse->resolution = psmouse_resolution; |
| 936 | 1115 | psmouse->resetafter = psmouse_resetafter; |
| 1116 | + psmouse->resync_time = parent ? 0 : psmouse_resync_time; | |
| 937 | 1117 | psmouse->smartscroll = psmouse_smartscroll; |
| 938 | 1118 | |
| 939 | 1119 | psmouse_switch_protocol(psmouse, NULL); |
| 940 | 1120 | |
| 941 | 1121 | |
| ... | ... | @@ -1278,13 +1458,21 @@ |
| 1278 | 1458 | |
| 1279 | 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 | 1467 | serio_register_driver(&psmouse_drv); |
| 1468 | + | |
| 1282 | 1469 | return 0; |
| 1283 | 1470 | } |
| 1284 | 1471 | |
| 1285 | 1472 | static void __exit psmouse_exit(void) |
| 1286 | 1473 | { |
| 1287 | 1474 | serio_unregister_driver(&psmouse_drv); |
| 1475 | + destroy_workqueue(kpsmoused_wq); | |
| 1288 | 1476 | } |
| 1289 | 1477 | |
| 1290 | 1478 | module_init(psmouse_init); |
drivers/input/mouse/psmouse.h
| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | #define PSMOUSE_CMD_GETINFO 0x03e9 |
| 8 | 8 | #define PSMOUSE_CMD_SETSTREAM 0x00ea |
| 9 | 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 | 11 | #define PSMOUSE_CMD_GETID 0x02f2 |
| 12 | 12 | #define PSMOUSE_CMD_SETRATE 0x10f3 |
| 13 | 13 | #define PSMOUSE_CMD_ENABLE 0x00f4 |
| ... | ... | @@ -23,6 +23,7 @@ |
| 23 | 23 | enum psmouse_state { |
| 24 | 24 | PSMOUSE_IGNORE, |
| 25 | 25 | PSMOUSE_INITIALIZING, |
| 26 | + PSMOUSE_RESYNCING, | |
| 26 | 27 | PSMOUSE_CMD_MODE, |
| 27 | 28 | PSMOUSE_ACTIVATED, |
| 28 | 29 | }; |
| 29 | 30 | |
| 30 | 31 | |
| 31 | 32 | |
| ... | ... | @@ -38,15 +39,19 @@ |
| 38 | 39 | void *private; |
| 39 | 40 | struct input_dev *dev; |
| 40 | 41 | struct ps2dev ps2dev; |
| 42 | + struct work_struct resync_work; | |
| 41 | 43 | char *vendor; |
| 42 | 44 | char *name; |
| 43 | 45 | unsigned char packet[8]; |
| 46 | + unsigned char badbyte; | |
| 44 | 47 | unsigned char pktcnt; |
| 45 | 48 | unsigned char pktsize; |
| 46 | 49 | unsigned char type; |
| 50 | + unsigned char acks_disable_command; | |
| 47 | 51 | unsigned int model; |
| 48 | 52 | unsigned long last; |
| 49 | 53 | unsigned long out_of_sync; |
| 54 | + unsigned long num_resyncs; | |
| 50 | 55 | enum psmouse_state state; |
| 51 | 56 | char devname[64]; |
| 52 | 57 | char phys[32]; |
| ... | ... | @@ -54,6 +59,7 @@ |
| 54 | 59 | unsigned int rate; |
| 55 | 60 | unsigned int resolution; |
| 56 | 61 | unsigned int resetafter; |
| 62 | + unsigned int resync_time; | |
| 57 | 63 | unsigned int smartscroll; /* Logitech only */ |
| 58 | 64 | |
| 59 | 65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); |
| ... | ... | @@ -62,6 +68,7 @@ |
| 62 | 68 | |
| 63 | 69 | int (*reconnect)(struct psmouse *psmouse); |
| 64 | 70 | void (*disconnect)(struct psmouse *psmouse); |
| 71 | + int (*poll)(struct psmouse *psmouse); | |
| 65 | 72 | |
| 66 | 73 | void (*pt_activate)(struct psmouse *psmouse); |
| 67 | 74 | void (*pt_deactivate)(struct psmouse *psmouse); |
drivers/input/mouse/synaptics.c
| ... | ... | @@ -652,6 +652,8 @@ |
| 652 | 652 | psmouse->disconnect = synaptics_disconnect; |
| 653 | 653 | psmouse->reconnect = synaptics_reconnect; |
| 654 | 654 | psmouse->pktsize = 6; |
| 655 | + /* Synaptics can usually stay in sync without extra help */ | |
| 656 | + psmouse->resync_time = 0; | |
| 655 | 657 | |
| 656 | 658 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) |
| 657 | 659 | synaptics_pt_create(psmouse); |
drivers/input/serio/i8042-x86ia64io.h
| ... | ... | @@ -173,6 +173,13 @@ |
| 173 | 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 |
drivers/usb/input/Kconfig
| ... | ... | @@ -37,6 +37,16 @@ |
| 37 | 37 | |
| 38 | 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 | 50 | config HID_FF |
| 41 | 51 | bool "Force feedback support (EXPERIMENTAL)" |
| 42 | 52 | depends on USB_HIDINPUT && EXPERIMENTAL |
drivers/usb/input/hid-core.c
| ... | ... | @@ -1450,6 +1450,9 @@ |
| 1450 | 1450 | #define USB_VENDOR_ID_APPLE 0x05ac |
| 1451 | 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 | 1457 | * Alphabetically sorted blacklist by quirk type. |
| 1455 | 1458 | */ |
| ... | ... | @@ -1580,6 +1583,16 @@ |
| 1580 | 1583 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, |
| 1581 | 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 | 1596 | { 0, 0 } |
| 1584 | 1597 | }; |
| 1585 | 1598 | |
| ... | ... | @@ -1626,6 +1639,20 @@ |
| 1626 | 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 | 1656 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) |
| 1630 | 1657 | { |
| 1631 | 1658 | struct usb_host_interface *interface = intf->cur_altsetting; |
| ... | ... | @@ -1672,6 +1699,9 @@ |
| 1672 | 1699 | kfree(rdesc); |
| 1673 | 1700 | return NULL; |
| 1674 | 1701 | } |
| 1702 | + | |
| 1703 | + if ((quirks & HID_QUIRK_CYMOTION)) | |
| 1704 | + hid_fixup_cymotion_descriptor(rdesc, rsize); | |
| 1675 | 1705 | |
| 1676 | 1706 | #ifdef DEBUG_DATA |
| 1677 | 1707 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); |
drivers/usb/input/hid-input.c
| ... | ... | @@ -73,6 +73,160 @@ |
| 73 | 73 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) |
| 74 | 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 | 230 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
| 77 | 231 | struct hid_usage *usage) |
| 78 | 232 | { |
| 79 | 233 | |
| ... | ... | @@ -135,8 +289,11 @@ |
| 135 | 289 | case HID_UP_SIMULATION: |
| 136 | 290 | |
| 137 | 291 | switch (usage->hid & 0xffff) { |
| 138 | - case 0xba: map_abs(ABS_RUDDER); break; | |
| 292 | + case 0xba: map_abs(ABS_RUDDER); break; | |
| 139 | 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 | 297 | default: goto ignore; |
| 141 | 298 | } |
| 142 | 299 | break; |
| 143 | 300 | |
| ... | ... | @@ -289,11 +446,19 @@ |
| 289 | 446 | case 0x226: map_key_clear(KEY_STOP); break; |
| 290 | 447 | case 0x227: map_key_clear(KEY_REFRESH); break; |
| 291 | 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 | 451 | case 0x238: map_rel(REL_HWHEEL); break; |
| 293 | 452 | case 0x279: map_key_clear(KEY_REDO); break; |
| 294 | 453 | case 0x289: map_key_clear(KEY_REPLY); break; |
| 295 | 454 | case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; |
| 296 | 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 | 462 | default: goto ignore; |
| 298 | 463 | } |
| 299 | 464 | break; |
| ... | ... | @@ -325,7 +490,12 @@ |
| 325 | 490 | |
| 326 | 491 | set_bit(EV_REP, input->evbit); |
| 327 | 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 | 499 | default: goto ignore; |
| 330 | 500 | } |
| 331 | 501 | break; |
| ... | ... | @@ -482,6 +652,9 @@ |
| 482 | 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 | 658 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
| 486 | 659 | int hat_dir = usage->hat_dir; |
| 487 | 660 | if (!hat_dir) |
| ... | ... | @@ -524,7 +697,7 @@ |
| 524 | 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 | 701 | return; |
| 529 | 702 | |
| 530 | 703 | input_event(input, usage->type, usage->code, value); |
drivers/usb/input/hid.h
| ... | ... | @@ -235,17 +235,20 @@ |
| 235 | 235 | * HID device quirks. |
| 236 | 236 | */ |
| 237 | 237 | |
| 238 | -#define HID_QUIRK_INVERT 0x001 | |
| 239 | -#define HID_QUIRK_NOTOUCH 0x002 | |
| 240 | -#define HID_QUIRK_IGNORE 0x004 | |
| 241 | -#define HID_QUIRK_NOGET 0x008 | |
| 242 | -#define HID_QUIRK_HIDDEV 0x010 | |
| 243 | -#define HID_QUIRK_BADPAD 0x020 | |
| 244 | -#define HID_QUIRK_MULTI_INPUT 0x040 | |
| 245 | -#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 | |
| 246 | -#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 | |
| 247 | -#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 | |
| 248 | -#define HID_QUIRK_2WHEEL_POWERMOUSE 0x400 | |
| 238 | +#define HID_QUIRK_INVERT 0x00000001 | |
| 239 | +#define HID_QUIRK_NOTOUCH 0x00000002 | |
| 240 | +#define HID_QUIRK_IGNORE 0x00000004 | |
| 241 | +#define HID_QUIRK_NOGET 0x00000008 | |
| 242 | +#define HID_QUIRK_HIDDEV 0x00000010 | |
| 243 | +#define HID_QUIRK_BADPAD 0x00000020 | |
| 244 | +#define HID_QUIRK_MULTI_INPUT 0x00000040 | |
| 245 | +#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 | |
| 246 | +#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 | |
| 247 | +#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 | |
| 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 | 254 | * This is the global environment of the parser. This information is |
| ... | ... | @@ -431,6 +434,11 @@ |
| 431 | 434 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ |
| 432 | 435 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, |
| 433 | 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 | 444 | #define HID_GLOBAL_STACK_SIZE 4 |
drivers/usb/input/pid.c
| ... | ... | @@ -259,7 +259,7 @@ |
| 259 | 259 | int hid_pid_init(struct hid_device *hid) |
| 260 | 260 | { |
| 261 | 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 | 263 | struct input_dev *input_dev = hidinput->input; |
| 264 | 264 | |
| 265 | 265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); |
drivers/usb/input/wacom.c
| ... | ... | @@ -95,7 +95,7 @@ |
| 95 | 95 | enum { |
| 96 | 96 | PENPARTNER = 0, |
| 97 | 97 | GRAPHIRE, |
| 98 | - G4, | |
| 98 | + WACOM_G4, | |
| 99 | 99 | PL, |
| 100 | 100 | INTUOS, |
| 101 | 101 | INTUOS3, |
| ... | ... | @@ -373,7 +373,7 @@ |
| 373 | 373 | |
| 374 | 374 | case 2: /* Mouse with wheel */ |
| 375 | 375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); |
| 376 | - if (wacom->features->type == G4) { | |
| 376 | + if (wacom->features->type == WACOM_G4) { | |
| 377 | 377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); |
| 378 | 378 | input_report_rel(dev, REL_WHEEL, rw); |
| 379 | 379 | } else |
| ... | ... | @@ -385,7 +385,7 @@ |
| 385 | 385 | id = CURSOR_DEVICE_ID; |
| 386 | 386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); |
| 387 | 387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); |
| 388 | - if (wacom->features->type == G4) | |
| 388 | + if (wacom->features->type == WACOM_G4) | |
| 389 | 389 | input_report_abs(dev, ABS_DISTANCE, data[6]); |
| 390 | 390 | else |
| 391 | 391 | input_report_abs(dev, ABS_DISTANCE, data[7]); |
| ... | ... | @@ -410,7 +410,7 @@ |
| 410 | 410 | input_sync(dev); |
| 411 | 411 | |
| 412 | 412 | /* send pad data */ |
| 413 | - if (wacom->features->type == G4) { | |
| 413 | + if (wacom->features->type == WACOM_G4) { | |
| 414 | 414 | /* fist time sending pad data */ |
| 415 | 415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { |
| 416 | 416 | wacom->id[1] = 0; |
| ... | ... | @@ -713,8 +713,8 @@ |
| 713 | 713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
| 714 | 714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
| 715 | 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 }, | |
| 717 | - { "Wacom Graphire4 6x8", 8, 16704, 12064, 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, WACOM_G4, wacom_graphire_irq }, | |
| 718 | 718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
| 719 | 719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, |
| 720 | 720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
| ... | ... | @@ -859,7 +859,7 @@ |
| 859 | 859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); |
| 860 | 860 | |
| 861 | 861 | switch (wacom->features->type) { |
| 862 | - case G4: | |
| 862 | + case WACOM_G4: | |
| 863 | 863 | input_dev->evbit[0] |= BIT(EV_MSC); |
| 864 | 864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); |
| 865 | 865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); |