···348 return 0;349}350351+/*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+385static int alps_reconnect(struct psmouse *psmouse)386{387 struct alps_data *priv = psmouse->private;···451 input_register_device(priv->dev2);452453 psmouse->protocol_handler = alps_process_byte;454+ psmouse->poll = alps_poll;455 psmouse->disconnect = alps_disconnect;456 psmouse->reconnect = alps_reconnect;457 psmouse->pktsize = 6;458+459+ /* We are having trouble resyncing ALPS touchpads so disable it for now */460+ psmouse->resync_time = 0;461462 return 0;463
+1-1
drivers/input/mouse/logips2pp.c
···117 if (psmouse_sliced_command(psmouse, command))118 return -1;119120- if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL))121 return -1;122123 return 0;
···117 if (psmouse_sliced_command(psmouse, command))118 return -1;119120+ if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300))121 return -1;122123 return 0;
+253-65
drivers/input/mouse/psmouse-base.c
···54module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);55MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");5657-static unsigned int psmouse_resetafter;58module_param_named(resetafter, psmouse_resetafter, uint, 0644);59MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");00006061PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,62 NULL,···74PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,75 (void *) offsetof(struct psmouse, resetafter),76 psmouse_show_int_attr, psmouse_set_int_attr);0007778static struct attribute *psmouse_attributes[] = {79 &psmouse_attr_protocol.dattr.attr,80 &psmouse_attr_rate.dattr.attr,81 &psmouse_attr_resolution.dattr.attr,82 &psmouse_attr_resetafter.dattr.attr,083 NULL84};85···105 * is taken in "slow" paths it is not worth it.106 */107static DECLARE_MUTEX(psmouse_sem);00108109struct psmouse_protocol {110 enum psmouse_type type;···188}189190/*191- * psmouse_interrupt() handles incoming characters, either gathering them into192- * packets or passing them to the command routine as command output.00000000000000000000000000000000000000000000000000000000000000000193 */194195static irqreturn_t psmouse_interrupt(struct serio *serio,196 unsigned char data, unsigned int flags, struct pt_regs *regs)197{198 struct psmouse *psmouse = serio_get_drvdata(serio);199- psmouse_ret_t rc;200201 if (psmouse->state == PSMOUSE_IGNORE)202 goto out;···282 if (ps2_handle_response(&psmouse->ps2dev, data))283 goto out;284285- if (psmouse->state == PSMOUSE_INITIALIZING)286 goto out;287288 if (psmouse->state == PSMOUSE_ACTIVATED &&289 psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {290- printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",291 psmouse->name, psmouse->phys, psmouse->pktcnt);292- psmouse->pktcnt = 0;000293 }294295- psmouse->last = jiffies;296 psmouse->packet[psmouse->pktcnt++] = data;297-298- if (psmouse->packet[0] == PSMOUSE_RET_BAT) {00299 if (psmouse->pktcnt == 1)300 goto out;301302- if (psmouse->pktcnt == 2) {303- if (psmouse->packet[1] == PSMOUSE_RET_ID) {304- psmouse->state = PSMOUSE_IGNORE;305- serio_reconnect(serio);306- goto out;307- }308- if (psmouse->type == PSMOUSE_SYNAPTICS) {309- /* neither 0xAA nor 0x00 are valid first bytes310- * for a packet in absolute mode311- */312- psmouse->pktcnt = 0;313- goto out;314- }315 }00000000316 }317318- rc = psmouse->protocol_handler(psmouse, regs);319-320- switch (rc) {321- case PSMOUSE_BAD_DATA:322- printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",323- psmouse->name, psmouse->phys, psmouse->pktcnt);324- psmouse->pktcnt = 0;325-326- if (++psmouse->out_of_sync == psmouse->resetafter) {327- psmouse->state = PSMOUSE_IGNORE;328- printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");329- serio_reconnect(psmouse->ps2dev.serio);330- }331- break;332-333- case PSMOUSE_FULL_PACKET:334- psmouse->pktcnt = 0;335- if (psmouse->out_of_sync) {336- psmouse->out_of_sync = 0;337- printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",338- psmouse->name, psmouse->phys);339- }340- break;341-342- case PSMOUSE_GOOD_DATA:343- break;344 }345-out:0000346 return IRQ_HANDLED;347}348···817}818819/*820- * psmouse_set_state() sets new psmouse state and resets all flags and821- * counters while holding serio lock so fighting with interrupt handler822- * is not a concern.823- */824-825-static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)826-{827- serio_pause_rx(psmouse->ps2dev.serio);828- psmouse->state = new_state;829- psmouse->pktcnt = psmouse->out_of_sync = 0;830- psmouse->ps2dev.flags = 0;831- serio_continue_rx(psmouse->ps2dev.serio);832-}833-834-/*835 * psmouse_activate() enables the mouse so that we get motion reports from it.836 */837···844 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);845}846000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000847848/*849 * psmouse_cleanup() resets the mouse into power-on state.···976 down(&psmouse_sem);977978 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);00000979980 if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {981 parent = serio_get_drvdata(serio->parent);···10191020 psmouse->set_rate = psmouse_set_rate;1021 psmouse->set_resolution = psmouse_set_resolution;01022 psmouse->protocol_handler = psmouse_process_byte;1023 psmouse->pktsize = 3;1024···1034 }1035 else1036 psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);0000000000000000010371038 sprintf(psmouse->devname, "%s %s %s",1039 psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);···1092 goto out;10931094 ps2_init(&psmouse->ps2dev, serio);01095 psmouse->dev = input_dev;1096 sprintf(psmouse->phys, "%s/input0", serio->phys);1097···1113 psmouse->rate = psmouse_rate;1114 psmouse->resolution = psmouse_resolution;1115 psmouse->resetafter = psmouse_resetafter;01116 psmouse->smartscroll = psmouse_smartscroll;11171118 psmouse_switch_protocol(psmouse, NULL);···14581459static int __init psmouse_init(void)1460{0000001461 serio_register_driver(&psmouse_drv);01462 return 0;1463}14641465static void __exit psmouse_exit(void)1466{1467 serio_unregister_driver(&psmouse_drv);01468}14691470module_init(psmouse_init);
···54module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);55MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");5657+static unsigned int psmouse_resetafter = 5;58module_param_named(resetafter, psmouse_resetafter, uint, 0644);59MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");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).");6465PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,66 NULL,···70PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,71 (void *) offsetof(struct psmouse, resetafter),72 psmouse_show_int_attr, psmouse_set_int_attr);73+PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO,74+ (void *) offsetof(struct psmouse, resync_time),75+ psmouse_show_int_attr, psmouse_set_int_attr);7677static struct attribute *psmouse_attributes[] = {78 &psmouse_attr_protocol.dattr.attr,79 &psmouse_attr_rate.dattr.attr,80 &psmouse_attr_resolution.dattr.attr,81 &psmouse_attr_resetafter.dattr.attr,82+ &psmouse_attr_resync_time.dattr.attr,83 NULL84};85···97 * is taken in "slow" paths it is not worth it.98 */99static DECLARE_MUTEX(psmouse_sem);100+101+static struct workqueue_struct *kpsmoused_wq;102103struct psmouse_protocol {104 enum psmouse_type type;···178}179180/*181+ * __psmouse_set_state() sets new psmouse state and resets all flags.182+ */183+184+static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)185+{186+ psmouse->state = new_state;187+ psmouse->pktcnt = psmouse->out_of_sync = 0;188+ psmouse->ps2dev.flags = 0;189+ psmouse->last = jiffies;190+}191+192+193+/*194+ * psmouse_set_state() sets new psmouse state and resets all flags and195+ * counters while holding serio lock so fighting with interrupt handler196+ * is not a concern.197+ */198+199+static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)200+{201+ serio_pause_rx(psmouse->ps2dev.serio);202+ __psmouse_set_state(psmouse, new_state);203+ serio_continue_rx(psmouse->ps2dev.serio);204+}205+206+/*207+ * psmouse_handle_byte() processes one byte of the input data stream208+ * by calling corresponding protocol handler.209+ */210+211+static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs)212+{213+ psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs);214+215+ switch (rc) {216+ case PSMOUSE_BAD_DATA:217+ if (psmouse->state == PSMOUSE_ACTIVATED) {218+ printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",219+ psmouse->name, psmouse->phys, psmouse->pktcnt);220+ if (++psmouse->out_of_sync == psmouse->resetafter) {221+ __psmouse_set_state(psmouse, PSMOUSE_IGNORE);222+ printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");223+ serio_reconnect(psmouse->ps2dev.serio);224+ return -1;225+ }226+ }227+ psmouse->pktcnt = 0;228+ break;229+230+ case PSMOUSE_FULL_PACKET:231+ psmouse->pktcnt = 0;232+ if (psmouse->out_of_sync) {233+ psmouse->out_of_sync = 0;234+ printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",235+ psmouse->name, psmouse->phys);236+ }237+ break;238+239+ case PSMOUSE_GOOD_DATA:240+ break;241+ }242+ return 0;243+}244+245+/*246+ * psmouse_interrupt() handles incoming characters, either passing them247+ * for normal processing or gathering them as command response.248 */249250static irqreturn_t psmouse_interrupt(struct serio *serio,251 unsigned char data, unsigned int flags, struct pt_regs *regs)252{253 struct psmouse *psmouse = serio_get_drvdata(serio);0254255 if (psmouse->state == PSMOUSE_IGNORE)256 goto out;···208 if (ps2_handle_response(&psmouse->ps2dev, data))209 goto out;210211+ if (psmouse->state <= PSMOUSE_RESYNCING)212 goto out;213214 if (psmouse->state == PSMOUSE_ACTIVATED &&215 psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {216+ printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",217 psmouse->name, psmouse->phys, psmouse->pktcnt);218+ psmouse->badbyte = psmouse->packet[0];219+ __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);220+ queue_work(kpsmoused_wq, &psmouse->resync_work);221+ goto out;222 }2230224 psmouse->packet[psmouse->pktcnt++] = data;225+/*226+ * Check if this is a new device announcement (0xAA 0x00)227+ */228+ if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {229 if (psmouse->pktcnt == 1)230 goto out;231232+ if (psmouse->packet[1] == PSMOUSE_RET_ID) {233+ __psmouse_set_state(psmouse, PSMOUSE_IGNORE);234+ serio_reconnect(serio);235+ goto out;000000000236 }237+/*238+ * Not a new device, try processing first byte normally239+ */240+ psmouse->pktcnt = 1;241+ if (psmouse_handle_byte(psmouse, regs))242+ goto out;243+244+ psmouse->packet[psmouse->pktcnt++] = data;245 }246247+/*248+ * See if we need to force resync because mouse was idle for too long249+ */250+ if (psmouse->state == PSMOUSE_ACTIVATED &&251+ psmouse->pktcnt == 1 && psmouse->resync_time &&252+ time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {253+ psmouse->badbyte = psmouse->packet[0];254+ __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);255+ queue_work(kpsmoused_wq, &psmouse->resync_work);256+ goto out;0000000000000000257 }258+259+ psmouse->last = jiffies;260+ psmouse_handle_byte(psmouse, regs);261+262+ out:263 return IRQ_HANDLED;264}265···752}753754/*000000000000000755 * psmouse_activate() enables the mouse so that we get motion reports from it.756 */757···794 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);795}796797+/*798+ * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it.799+ */800+801+static int psmouse_poll(struct psmouse *psmouse)802+{803+ return ps2_command(&psmouse->ps2dev, psmouse->packet,804+ PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));805+}806+807+808+/*809+ * psmouse_resync() attempts to re-validate current protocol.810+ */811+812+static void psmouse_resync(void *p)813+{814+ struct psmouse *psmouse = p, *parent = NULL;815+ struct serio *serio = psmouse->ps2dev.serio;816+ psmouse_ret_t rc = PSMOUSE_GOOD_DATA;817+ int failed = 0, enabled = 0;818+ int i;819+820+ down(&psmouse_sem);821+822+ if (psmouse->state != PSMOUSE_RESYNCING)823+ goto out;824+825+ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {826+ parent = serio_get_drvdata(serio->parent);827+ psmouse_deactivate(parent);828+ }829+830+/*831+ * Some mice don't ACK commands sent while they are in the middle of832+ * transmitting motion packet. To avoid delay we use ps2_sendbyte()833+ * instead of ps2_command() which would wait for 200ms for an ACK834+ * that may never come.835+ * As an additional quirk ALPS touchpads may not only forget to ACK836+ * disable command but will stop reporting taps, so if we see that837+ * mouse at least once ACKs disable we will do full reconnect if ACK838+ * is missing.839+ */840+ psmouse->num_resyncs++;841+842+ if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) {843+ if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command)844+ failed = 1;845+ } else846+ psmouse->acks_disable_command = 1;847+848+/*849+ * Poll the mouse. If it was reset the packet will be shorter than850+ * psmouse->pktsize and ps2_command will fail. We do not expect and851+ * do not handle scenario when mouse "upgrades" its protocol while852+ * disconnected since it would require additional delay. If we ever853+ * see a mouse that does it we'll adjust the code.854+ */855+ if (!failed) {856+ if (psmouse->poll(psmouse))857+ failed = 1;858+ else {859+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);860+ for (i = 0; i < psmouse->pktsize; i++) {861+ psmouse->pktcnt++;862+ rc = psmouse->protocol_handler(psmouse, NULL);863+ if (rc != PSMOUSE_GOOD_DATA)864+ break;865+ }866+ if (rc != PSMOUSE_FULL_PACKET)867+ failed = 1;868+ psmouse_set_state(psmouse, PSMOUSE_RESYNCING);869+ }870+ }871+/*872+ * Now try to enable mouse. We try to do that even if poll failed and also873+ * repeat our attempts 5 times, otherwise we may be left out with disabled874+ * mouse.875+ */876+ for (i = 0; i < 5; i++) {877+ if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {878+ enabled = 1;879+ break;880+ }881+ msleep(200);882+ }883+884+ if (!enabled) {885+ printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",886+ psmouse->ps2dev.serio->phys);887+ failed = 1;888+ }889+890+ if (failed) {891+ psmouse_set_state(psmouse, PSMOUSE_IGNORE);892+ printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n");893+ serio_reconnect(serio);894+ } else895+ psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);896+897+ if (parent)898+ psmouse_activate(parent);899+ out:900+ up(&psmouse_sem);901+}902903/*904 * psmouse_cleanup() resets the mouse into power-on state.···821 down(&psmouse_sem);822823 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);824+825+ /* make sure we don't have a resync in progress */826+ up(&psmouse_sem);827+ flush_workqueue(kpsmoused_wq);828+ down(&psmouse_sem);829830 if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {831 parent = serio_get_drvdata(serio->parent);···859860 psmouse->set_rate = psmouse_set_rate;861 psmouse->set_resolution = psmouse_set_resolution;862+ psmouse->poll = psmouse_poll;863 psmouse->protocol_handler = psmouse_process_byte;864 psmouse->pktsize = 3;865···873 }874 else875 psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);876+877+ /*878+ * If mouse's packet size is 3 there is no point in polling the879+ * device in hopes to detect protocol reset - we won't get less880+ * than 3 bytes response anyhow.881+ */882+ if (psmouse->pktsize == 3)883+ psmouse->resync_time = 0;884+885+ /*886+ * Some smart KVMs fake response to POLL command returning just887+ * 3 bytes and messing up our resync logic, so if initial poll888+ * fails we won't try polling the device anymore. Hopefully889+ * such KVM will maintain initially selected protocol.890+ */891+ if (psmouse->resync_time && psmouse->poll(psmouse))892+ psmouse->resync_time = 0;893894 sprintf(psmouse->devname, "%s %s %s",895 psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);···914 goto out;915916 ps2_init(&psmouse->ps2dev, serio);917+ INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse);918 psmouse->dev = input_dev;919 sprintf(psmouse->phys, "%s/input0", serio->phys);920···934 psmouse->rate = psmouse_rate;935 psmouse->resolution = psmouse_resolution;936 psmouse->resetafter = psmouse_resetafter;937+ psmouse->resync_time = parent ? 0 : psmouse_resync_time;938 psmouse->smartscroll = psmouse_smartscroll;939940 psmouse_switch_protocol(psmouse, NULL);···12781279static int __init psmouse_init(void)1280{1281+ kpsmoused_wq = create_singlethread_workqueue("kpsmoused");1282+ if (!kpsmoused_wq) {1283+ printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");1284+ return -ENOMEM;1285+ }1286+1287 serio_register_driver(&psmouse_drv);1288+1289 return 0;1290}12911292static void __exit psmouse_exit(void)1293{1294 serio_unregister_driver(&psmouse_drv);1295+ destroy_workqueue(kpsmoused_wq);1296}12971298module_init(psmouse_init);
···652 psmouse->disconnect = synaptics_disconnect;653 psmouse->reconnect = synaptics_reconnect;654 psmouse->pktsize = 6;655+ /* Synaptics can usually stay in sync without extra help */656+ psmouse->resync_time = 0;657658 if (SYN_CAP_PASS_THROUGH(priv->capabilities))659 synaptics_pt_create(psmouse);
···3738 If unsure, say Y.39000000000040config HID_FF41 bool "Force feedback support (EXPERIMENTAL)"42 depends on USB_HIDINPUT && EXPERIMENTAL
···3738 If unsure, say Y.3940+config USB_HIDINPUT_POWERBOOK41+ bool "Enable support for iBook/PowerBook special keys"42+ default n43+ depends on USB_HIDINPUT44+ help45+ Say Y here if you want support for the special keys (Fn, Numlock) on46+ Apple iBooks and PowerBooks.47+48+ If unsure, say N.49+50config HID_FF51 bool "Force feedback support (EXPERIMENTAL)"52 depends on USB_HIDINPUT && EXPERIMENTAL
···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)75000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,77 struct hid_usage *usage)78{···289 case HID_UP_SIMULATION:290291 switch (usage->hid & 0xffff) {292- case 0xba: map_abs(ABS_RUDDER); break;293 case 0xbb: map_abs(ABS_THROTTLE); break;000294 default: goto ignore;295 }296 break;···446 case 0x226: map_key_clear(KEY_STOP); break;447 case 0x227: map_key_clear(KEY_REFRESH); break;448 case 0x22a: map_key_clear(KEY_BOOKMARKS); break;00449 case 0x238: map_rel(REL_HWHEEL); break;450 case 0x279: map_key_clear(KEY_REDO); break;451 case 0x289: map_key_clear(KEY_REPLY); break;452 case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;453 case 0x28c: map_key_clear(KEY_SEND); break;000000454 default: goto ignore;455 }456 break;···490491 set_bit(EV_REP, input->evbit);492 switch(usage->hid & HID_USAGE) {493- case 0x003: map_key_clear(KEY_FN); break;00000494 default: goto ignore;495 }496 break;···652 return;653 }654000655 if (usage->hat_min < usage->hat_max || usage->hat_dir) {656 int hat_dir = usage->hat_dir;657 if (!hat_dir)···697 return;698 }699700- if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */701 return;702703 input_event(input, usage->type, usage->code, value);
···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)7576+#ifdef CONFIG_USB_HIDINPUT_POWERBOOK77+78+struct hidinput_key_translation {79+ u16 from;80+ u16 to;81+ u8 flags;82+};83+84+#define POWERBOOK_FLAG_FKEY 0x0185+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+ else171+ 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+ else177+ 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+ else193+ 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+#else219+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+#endif229+230static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,231 struct hid_usage *usage)232{···135 case HID_UP_SIMULATION:136137 switch (usage->hid & 0xffff) {138+ case 0xba: map_abs(ABS_RUDDER); break;139 case 0xbb: map_abs(ABS_THROTTLE); break;140+ case 0xc4: map_abs(ABS_GAS); break;141+ case 0xc5: map_abs(ABS_BRAKE); break;142+ case 0xc8: map_abs(ABS_WHEEL); break;143 default: goto ignore;144 }145 break;···289 case 0x226: map_key_clear(KEY_STOP); break;290 case 0x227: map_key_clear(KEY_REFRESH); break;291 case 0x22a: map_key_clear(KEY_BOOKMARKS); break;292+ case 0x233: map_key_clear(KEY_SCROLLUP); break;293+ case 0x234: map_key_clear(KEY_SCROLLDOWN); break;294 case 0x238: map_rel(REL_HWHEEL); break;295 case 0x279: map_key_clear(KEY_REDO); break;296 case 0x289: map_key_clear(KEY_REPLY); break;297 case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;298 case 0x28c: map_key_clear(KEY_SEND); break;299+300+ /* Reported on a Cherry Cymotion keyboard */301+ case 0x301: map_key_clear(KEY_PROG1); break;302+ case 0x302: map_key_clear(KEY_PROG2); break;303+ case 0x303: map_key_clear(KEY_PROG3); break;304+305 default: goto ignore;306 }307 break;···325326 set_bit(EV_REP, input->evbit);327 switch(usage->hid & HID_USAGE) {328+ case 0x003:329+ /* The fn key on Apple PowerBooks */330+ map_key_clear(KEY_FN);331+ hidinput_pb_setup(input);332+ break;333+334 default: goto ignore;335 }336 break;···482 return;483 }484485+ if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))486+ return;487+488 if (usage->hat_min < usage->hat_max || usage->hat_dir) {489 int hat_dir = usage->hat_dir;490 if (!hat_dir)···524 return;525 }526527+ if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */528 return;529530 input_event(input, usage->type, usage->code, value);
+19-11
drivers/usb/input/hid.h
···235 * HID device quirks.236 */237238-#define HID_QUIRK_INVERT 0x001239-#define HID_QUIRK_NOTOUCH 0x002240-#define HID_QUIRK_IGNORE 0x004241-#define HID_QUIRK_NOGET 0x008242-#define HID_QUIRK_HIDDEV 0x010243-#define HID_QUIRK_BADPAD 0x020244-#define HID_QUIRK_MULTI_INPUT 0x040245-#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080246-#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100247-#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200248-#define HID_QUIRK_2WHEEL_POWERMOUSE 0x400000249250/*251 * This is the global environment of the parser. This information is···434 void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */435 int (*ff_event)(struct hid_device *hid, struct input_dev *input,436 unsigned int type, unsigned int code, int value);00000437};438439#define HID_GLOBAL_STACK_SIZE 4
···235 * HID device quirks.236 */237238+#define HID_QUIRK_INVERT 0x00000001239+#define HID_QUIRK_NOTOUCH 0x00000002240+#define HID_QUIRK_IGNORE 0x00000004241+#define HID_QUIRK_NOGET 0x00000008242+#define HID_QUIRK_HIDDEV 0x00000010243+#define HID_QUIRK_BADPAD 0x00000020244+#define HID_QUIRK_MULTI_INPUT 0x00000040245+#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080246+#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100247+#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200248+#define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400249+#define HID_QUIRK_CYMOTION 0x00000800250+#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000251+#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000252253/*254 * This is the global environment of the parser. This information is···431 void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */432 int (*ff_event)(struct hid_device *hid, struct input_dev *input,433 unsigned int type, unsigned int code, int value);434+435+#ifdef CONFIG_USB_HIDINPUT_POWERBOOK436+ unsigned long pb_pressed_fn[NBITS(KEY_MAX)];437+ unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];438+#endif439};440441#define HID_GLOBAL_STACK_SIZE 4