diff options
Diffstat (limited to 'drivers/input/mouse/psmouse-base.c')
| -rw-r--r-- | drivers/input/mouse/psmouse-base.c | 520 |
1 files changed, 322 insertions, 198 deletions
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 401ac6b6edd..cff065f6261 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -11,6 +11,9 @@ * the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define psmouse_fmt(fmt) fmt + #include <linux/delay.h> #include <linux/module.h> #include <linux/slab.h> @@ -31,6 +34,7 @@ #include "touchkit_ps2.h" #include "elantech.h" #include "sentelic.h" +#include "cypress_ps2.h" #define DRIVER_DESC "PS/2 mouse driver" @@ -39,11 +43,13 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); static unsigned int psmouse_max_proto = PSMOUSE_AUTO; -static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); -static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); +static int psmouse_set_maxproto(const char *val, const struct kernel_param *); +static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp); +static struct kernel_param_ops param_ops_proto_abbrev = { + .set = psmouse_set_maxproto, + .get = psmouse_get_maxproto, +}; #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) -#define param_set_proto_abbrev psmouse_set_maxproto -#define param_get_proto_abbrev psmouse_get_maxproto module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644); MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches."); @@ -55,7 +61,7 @@ static unsigned int psmouse_rate = 100; module_param_named(rate, psmouse_rate, uint, 0644); MODULE_PARM_DESC(rate, "Report rate, in reports per second."); -static unsigned int psmouse_smartscroll = 1; +static bool psmouse_smartscroll = 1; module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); @@ -110,6 +116,7 @@ static struct workqueue_struct *kpsmoused_wq; struct psmouse_protocol { enum psmouse_type type; bool maxproto; + bool ignore_parity; /* Protocol should ignore parity errors from KBC */ const char *name; const char *alias; int (*detect)(struct psmouse *, bool); @@ -121,7 +128,7 @@ struct psmouse_protocol { * relevant events to the input module once full packet has arrived. */ -static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) +psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) { struct input_dev *dev = psmouse->dev; unsigned char *packet = psmouse->packet; @@ -146,18 +153,18 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) if (psmouse->type == PSMOUSE_IMEX) { switch (packet[3] & 0xC0) { - case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ - input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); - break; - case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ - input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); - break; - case 0x00: - case 0xC0: - input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); - input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); - input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); - break; + case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ + input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); + break; + case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ + input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); + break; + case 0x00: + case 0xC0: + input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); + input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); + input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); + break; } } @@ -246,31 +253,35 @@ static int psmouse_handle_byte(struct psmouse *psmouse) psmouse_ret_t rc = psmouse->protocol_handler(psmouse); switch (rc) { - case PSMOUSE_BAD_DATA: - if (psmouse->state == PSMOUSE_ACTIVATED) { - printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", - psmouse->name, psmouse->phys, psmouse->pktcnt); - if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { - __psmouse_set_state(psmouse, PSMOUSE_IGNORE); - printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); - serio_reconnect(psmouse->ps2dev.serio); - return -1; - } + case PSMOUSE_BAD_DATA: + if (psmouse->state == PSMOUSE_ACTIVATED) { + psmouse_warn(psmouse, + "%s at %s lost sync at byte %d\n", + psmouse->name, psmouse->phys, + psmouse->pktcnt); + if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { + __psmouse_set_state(psmouse, PSMOUSE_IGNORE); + psmouse_notice(psmouse, + "issuing reconnect request\n"); + serio_reconnect(psmouse->ps2dev.serio); + return -1; } - psmouse->pktcnt = 0; - break; - - case PSMOUSE_FULL_PACKET: - psmouse->pktcnt = 0; - if (psmouse->out_of_sync_cnt) { - psmouse->out_of_sync_cnt = 0; - printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", + } + psmouse->pktcnt = 0; + break; + + case PSMOUSE_FULL_PACKET: + psmouse->pktcnt = 0; + if (psmouse->out_of_sync_cnt) { + psmouse->out_of_sync_cnt = 0; + psmouse_notice(psmouse, + "%s at %s - driver resynced.\n", psmouse->name, psmouse->phys); - } - break; + } + break; - case PSMOUSE_GOOD_DATA: - break; + case PSMOUSE_GOOD_DATA: + break; } return 0; } @@ -288,11 +299,14 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, if (psmouse->state == PSMOUSE_IGNORE) goto out; - if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) { + if (unlikely((flags & SERIO_TIMEOUT) || + ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { + if (psmouse->state == PSMOUSE_ACTIVATED) - printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", - flags & SERIO_TIMEOUT ? " timeout" : "", - flags & SERIO_PARITY ? " bad parity" : ""); + psmouse_warn(psmouse, + "bad data from KBC -%s%s\n", + flags & SERIO_TIMEOUT ? " timeout" : "", + flags & SERIO_PARITY ? " bad parity" : ""); ps2_cmd_aborted(&psmouse->ps2dev); goto out; } @@ -310,8 +324,8 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, if (psmouse->state == PSMOUSE_ACTIVATED && psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { - printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", - psmouse->name, psmouse->phys, psmouse->pktcnt); + psmouse_info(psmouse, "%s at %s lost synchronization, throwing %d bytes away.\n", + psmouse->name, psmouse->phys, psmouse->pktcnt); psmouse->badbyte = psmouse->packet[0]; __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); psmouse_queue_work(psmouse, &psmouse->resync_work, 0); @@ -405,6 +419,49 @@ int psmouse_reset(struct psmouse *psmouse) return 0; } +/* + * Here we set the mouse resolution. + */ + +void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution) +{ + static const unsigned char params[] = { 0, 1, 2, 2, 3 }; + unsigned char p; + + if (resolution == 0 || resolution > 200) + resolution = 200; + + p = params[resolution / 50]; + ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES); + psmouse->resolution = 25 << p; +} + +/* + * Here we set the mouse report rate. + */ + +static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate) +{ + static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 }; + unsigned char r; + int i = 0; + + while (rates[i] > rate) i++; + r = rates[i]; + ps2_command(&psmouse->ps2dev, &r, PSMOUSE_CMD_SETRATE); + psmouse->rate = r; +} + +/* + * psmouse_poll() - default poll handler. Everyone except for ALPS uses it. + */ + +static int psmouse_poll(struct psmouse *psmouse) +{ + return ps2_command(&psmouse->ps2dev, psmouse->packet, + PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); +} + /* * Genius NetMouse magic init. @@ -590,6 +647,56 @@ static int cortron_detect(struct psmouse *psmouse, bool set_properties) } /* + * Apply default settings to the psmouse structure. Most of them will + * be overridden by individual protocol initialization routines. + */ + +static void psmouse_apply_defaults(struct psmouse *psmouse) +{ + struct input_dev *input_dev = psmouse->dev; + + memset(input_dev->evbit, 0, sizeof(input_dev->evbit)); + memset(input_dev->keybit, 0, sizeof(input_dev->keybit)); + memset(input_dev->relbit, 0, sizeof(input_dev->relbit)); + memset(input_dev->absbit, 0, sizeof(input_dev->absbit)); + memset(input_dev->mscbit, 0, sizeof(input_dev->mscbit)); + + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(EV_REL, input_dev->evbit); + + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_RIGHT, input_dev->keybit); + + __set_bit(REL_X, input_dev->relbit); + __set_bit(REL_Y, input_dev->relbit); + + psmouse->set_rate = psmouse_set_rate; + psmouse->set_resolution = psmouse_set_resolution; + psmouse->poll = psmouse_poll; + psmouse->protocol_handler = psmouse_process_byte; + psmouse->pktsize = 3; + psmouse->reconnect = NULL; + psmouse->disconnect = NULL; + psmouse->cleanup = NULL; + psmouse->pt_activate = NULL; + psmouse->pt_deactivate = NULL; +} + +/* + * Apply default settings to the psmouse structure and call specified + * protocol detection or initialization routine. + */ +static int psmouse_do_detect(int (*detect)(struct psmouse *psmouse, + bool set_properties), + struct psmouse *psmouse, bool set_properties) +{ + if (set_properties) + psmouse_apply_defaults(psmouse); + + return detect(psmouse, set_properties); +} + +/* * psmouse_extensions() probes for any extensions to the basic PS/2 protocol * the mouse may have. */ @@ -603,7 +710,7 @@ static int psmouse_extensions(struct psmouse *psmouse, * We always check for lifebook because it does not disturb mouse * (it only checks DMI information). */ - if (lifebook_detect(psmouse, set_properties) == 0) { + if (psmouse_do_detect(lifebook_detect, psmouse, set_properties) == 0) { if (max_proto > PSMOUSE_IMEX) { if (!set_properties || lifebook_init(psmouse) == 0) return PSMOUSE_LIFEBOOK; @@ -615,20 +722,30 @@ static int psmouse_extensions(struct psmouse *psmouse, * upsets the thinkingmouse). */ - if (max_proto > PSMOUSE_IMEX && thinking_detect(psmouse, set_properties) == 0) + if (max_proto > PSMOUSE_IMEX && + psmouse_do_detect(thinking_detect, psmouse, set_properties) == 0) { return PSMOUSE_THINKPS; + } /* * Try Synaptics TouchPad. Note that probing is done even if Synaptics protocol * support is disabled in config - we need to know if it is synaptics so we * can reset it properly after probing for intellimouse. */ - if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) { + if (max_proto > PSMOUSE_PS2 && + psmouse_do_detect(synaptics_detect, psmouse, set_properties) == 0) { synaptics_hardware = true; if (max_proto > PSMOUSE_IMEX) { - if (!set_properties || synaptics_init(psmouse) == 0) +/* + * Try activating protocol, but check if support is enabled first, since + * we try detecting Synaptics even when protocol is disabled. + */ + if (synaptics_supported() && + (!set_properties || synaptics_init(psmouse) == 0)) { return PSMOUSE_SYNAPTICS; + } + /* * Some Synaptics touchpads can emulate extended protocols (like IMPS/2). * Unfortunately Logitech/Genius probes confuse some firmware versions so @@ -643,11 +760,34 @@ static int psmouse_extensions(struct psmouse *psmouse, } /* + * Try Cypress Trackpad. + * Must try it before Finger Sensing Pad because Finger Sensing Pad probe + * upsets some modules of Cypress Trackpads. + */ + if (max_proto > PSMOUSE_IMEX && + cypress_detect(psmouse, set_properties) == 0) { + if (cypress_supported()) { + if (cypress_init(psmouse) == 0) + return PSMOUSE_CYPRESS; + + /* + * Finger Sensing Pad probe upsets some modules of + * Cypress Trackpad, must avoid Finger Sensing Pad + * probe if Cypress Trackpad device detected. + */ + return PSMOUSE_PS2; + } + + max_proto = PSMOUSE_IMEX; + } + +/* * Try ALPS TouchPad */ if (max_proto > PSMOUSE_IMEX) { ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); - if (alps_detect(psmouse, set_properties) == 0) { + if (psmouse_do_detect(alps_detect, + psmouse, set_properties) == 0) { if (!set_properties || alps_init(psmouse) == 0) return PSMOUSE_ALPS; /* @@ -661,7 +801,7 @@ static int psmouse_extensions(struct psmouse *psmouse, * Try OLPC HGPK touchpad. */ if (max_proto > PSMOUSE_IMEX && - hgpk_detect(psmouse, set_properties) == 0) { + psmouse_do_detect(hgpk_detect, psmouse, set_properties) == 0) { if (!set_properties || hgpk_init(psmouse) == 0) return PSMOUSE_HGPK; /* @@ -674,7 +814,7 @@ static int psmouse_extensions(struct psmouse *psmouse, * Try Elantech touchpad. */ if (max_proto > PSMOUSE_IMEX && - elantech_detect(psmouse, set_properties) == 0) { + psmouse_do_detect(elantech_detect, psmouse, set_properties) == 0) { if (!set_properties || elantech_init(psmouse) == 0) return PSMOUSE_ELANTECH; /* @@ -683,11 +823,31 @@ static int psmouse_extensions(struct psmouse *psmouse, max_proto = PSMOUSE_IMEX; } + if (max_proto > PSMOUSE_IMEX) { + if (psmouse_do_detect(genius_detect, + psmouse, set_properties) == 0) + return PSMOUSE_GENPS; + + if (psmouse_do_detect(ps2pp_init, + psmouse, set_properties) == 0) + return PSMOUSE_PS2PP; + + if (psmouse_do_detect(trackpoint_detect, + psmouse, set_properties) == 0) + return PSMOUSE_TRACKPOINT; + + if (psmouse_do_detect(touchkit_ps2_detect, + psmouse, set_properties) == 0) + return PSMOUSE_TOUCHKIT_PS2; + } + /* - * Try Finger Sensing Pad + * Try Finger Sensing Pad. We do it here because its probe upsets + * Trackpoint devices (causing TP_READ_ID command to time out). */ if (max_proto > PSMOUSE_IMEX) { - if (fsp_detect(psmouse, set_properties) == 0) { + if (psmouse_do_detect(fsp_detect, + psmouse, set_properties) == 0) { if (!set_properties || fsp_init(psmouse) == 0) return PSMOUSE_FSP; /* @@ -697,20 +857,6 @@ static int psmouse_extensions(struct psmouse *psmouse, } } - if (max_proto > PSMOUSE_IMEX) { - if (genius_detect(psmouse, set_properties) == 0) - return PSMOUSE_GENPS; - - if (ps2pp_init(psmouse, set_properties) == 0) - return PSMOUSE_PS2PP; - - if (trackpoint_detect(psmouse, set_properties) == 0) - return PSMOUSE_TRACKPOINT; - - if (touchkit_ps2_detect(psmouse, set_properties) == 0) - return PSMOUSE_TOUCHKIT_PS2; - } - /* * Reset to defaults in case the device got confused by extended * protocol probes. Note that we follow up with full reset because @@ -719,17 +865,23 @@ static int psmouse_extensions(struct psmouse *psmouse, ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); psmouse_reset(psmouse); - if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0) + if (max_proto >= PSMOUSE_IMEX && + psmouse_do_detect(im_explorer_detect, + psmouse, set_properties) == 0) { return PSMOUSE_IMEX; + } - if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0) + if (max_proto >= PSMOUSE_IMPS && + psmouse_do_detect(intellimouse_detect, + psmouse, set_properties) == 0) { return PSMOUSE_IMPS; + } /* * Okay, all failed, we have a standard mouse here. The number of the buttons * is still a question, though. We assume 3. */ - ps2bare_detect(psmouse, set_properties); + psmouse_do_detect(ps2bare_detect, psmouse, set_properties); if (synaptics_hardware) { /* @@ -750,6 +902,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .name = "PS/2", .alias = "bare", .maxproto = true, + .ignore_parity = true, .detect = ps2bare_detect, }, #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP @@ -766,6 +919,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { .alias = "thinkps", .detect = thinking_detect, }, +#ifdef CONFIG_MOUSE_PS2_CYPRESS + { + .type = PSMOUSE_CYPRESS, + .name = "CyPS/2", + .alias = "cypress", + .detect = cypress_detect, + .init = cypress_init, + }, +#endif { .type = PSMOUSE_GENPS, .name = "GenPS/2", @@ -777,6 +939,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .name = "ImPS/2", .alias = "imps", .maxproto = true, + .ignore_parity = true, .detect = intellimouse_detect, }, { @@ -784,6 +947,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .name = "ImExPS/2", .alias = "exps", .maxproto = true, + .ignore_parity = true, .detect = im_explorer_detect, }, #ifdef CONFIG_MOUSE_PS2_SYNAPTICS @@ -794,6 +958,13 @@ static const struct psmouse_protocol psmouse_protocols[] = { .detect = synaptics_detect, .init = synaptics_init, }, + { + .type = PSMOUSE_SYNAPTICS_RELATIVE, + .name = "SynRelPS/2", + .alias = "synaptics-relative", + .detect = synaptics_detect, + .init = synaptics_init_relative, + }, #endif #ifdef CONFIG_MOUSE_PS2_ALPS { @@ -926,45 +1097,13 @@ static int psmouse_probe(struct psmouse *psmouse) */ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS)) - printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", ps2dev->serio->phys); + psmouse_warn(psmouse, "Failed to reset mouse on %s\n", + ps2dev->serio->phys); return 0; } /* - * Here we set the mouse resolution. - */ - -void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution) -{ - static const unsigned char params[] = { 0, 1, 2, 2, 3 }; - unsigned char p; - - if (resolution == 0 || resolution > 200) - resolution = 200; - - p = params[resolution / 50]; - ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES); - psmouse->resolution = 25 << p; -} - -/* - * Here we set the mouse report rate. - */ - -static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate) -{ - static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 }; - unsigned char r; - int i = 0; - - while (rates[i] > rate) i++; - r = rates[i]; - ps2_command(&psmouse->ps2dev, &r, PSMOUSE_CMD_SETRATE); - psmouse->rate = r; -} - -/* * psmouse_initialize() initializes the mouse to a sane state. */ @@ -985,38 +1124,33 @@ static void psmouse_initialize(struct psmouse *psmouse) * psmouse_activate() enables the mouse so that we get motion reports from it. */ -static void psmouse_activate(struct psmouse *psmouse) +int psmouse_activate(struct psmouse *psmouse) { - if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) - printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", - psmouse->ps2dev.serio->phys); + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { + psmouse_warn(psmouse, "Failed to enable mouse on %s\n", + psmouse->ps2dev.serio->phys); + return -1; + } psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); + return 0; } - /* * psmouse_deactivate() puts the mouse into poll mode so that we don't get motion * reports from it unless we explicitly request it. */ -static void psmouse_deactivate(struct psmouse *psmouse) +int psmouse_deactivate(struct psmouse *psmouse) { - if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) - printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n", - psmouse->ps2dev.serio->phys); + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) { + psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n", + psmouse->ps2dev.serio->phys); + return -1; + } psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); -} - -/* - * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it. - */ - -static int psmouse_poll(struct psmouse *psmouse) -{ - return ps2_command(&psmouse->ps2dev, psmouse->packet, - PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); + return 0; } @@ -1098,14 +1232,15 @@ static void psmouse_resync(struct work_struct *work) } if (!enabled) { - printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", - psmouse->ps2dev.serio->phys); + psmouse_warn(psmouse, "failed to re-enable mouse on %s\n", + psmouse->ps2dev.serio->phys); failed = true; } if (failed) { psmouse_set_state(psmouse, PSMOUSE_IGNORE); - printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n"); + psmouse_info(psmouse, + "resync failed, issuing reconnect request\n"); serio_reconnect(serio); } else psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); @@ -1132,7 +1267,14 @@ static void psmouse_cleanup(struct serio *serio) psmouse_deactivate(parent); } - psmouse_deactivate(psmouse); + psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); + + /* + * Disable stream mode so cleanup routine can proceed undisturbed. + */ + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) + psmouse_warn(psmouse, "Failed to disable mouse on %s\n", + psmouse->ps2dev.serio->phys); if (psmouse->cleanup) psmouse->cleanup(psmouse); @@ -1206,32 +1348,29 @@ static void psmouse_disconnect(struct serio *serio) static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse_protocol *proto) { + const struct psmouse_protocol *selected_proto; struct input_dev *input_dev = psmouse->dev; input_dev->dev.parent = &psmouse->ps2dev.serio->dev; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - input_dev->keybit[BIT_WORD(BTN_MOUSE)] = - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); - input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - - psmouse->set_rate = psmouse_set_rate; - psmouse->set_resolution = psmouse_set_resolution; - psmouse->poll = psmouse_poll; - psmouse->protocol_handler = psmouse_process_byte; - psmouse->pktsize = 3; - if (proto && (proto->detect || proto->init)) { - if (proto->detect && proto->detect(psmouse, 1) < 0) + psmouse_apply_defaults(psmouse); + + if (proto->detect && proto->detect(psmouse, true) < 0) return -1; if (proto->init && proto->init(psmouse) < 0) return -1; psmouse->type = proto->type; - } else + selected_proto = proto; + } else { psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, true); + selected_proto = psmouse_protocol_by_type(psmouse->type); + } + + psmouse->ignore_parity = selected_proto->ignore_parity; /* * If mouse's packet size is 3 there is no point in polling the @@ -1251,7 +1390,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, psmouse->resync_time = 0; snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", - psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); + selected_proto->name, psmouse->vendor, psmouse->name); input_dev->name = psmouse->devname; input_dev->phys = psmouse->phys; @@ -1366,10 +1505,12 @@ static int psmouse_reconnect(struct serio *serio) struct psmouse *psmouse = serio_get_drvdata(serio); struct psmouse *parent = NULL; struct serio_driver *drv = serio->drv; + unsigned char type; int rc = -1; if (!drv || !psmouse) { - printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n"); + psmouse_dbg(psmouse, + "reconnect request, but serio is disconnected, ignoring...\n"); return -1; } @@ -1385,14 +1526,20 @@ static int psmouse_reconnect(struct serio *serio) if (psmouse->reconnect) { if (psmouse->reconnect(psmouse)) goto out; - } else if (psmouse_probe(psmouse) < 0 || - psmouse->type != psmouse_extensions(psmouse, - psmouse_max_proto, false)) { - goto out; + } else { + psmouse_reset(psmouse); + + if (psmouse_probe(psmouse) < 0) + goto out; + + type = psmouse_extensions(psmouse, psmouse_max_proto, false); + if (psmouse->type != type) + goto out; } - /* ok, the device type (and capabilities) match the old one, - * we can continue using it, complete intialization + /* + * OK, the device type (and capabilities) match the old one, + * we can continue using it, complete initialization */ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); @@ -1450,24 +1597,10 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de struct serio *serio = to_serio_port(dev); struct psmouse_attribute *attr = to_psmouse_attr(devattr); struct psmouse *psmouse; - int retval; - - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &psmouse_drv) { - retval = -ENODEV; - goto out; - } psmouse = serio_get_drvdata(serio); - retval = attr->show(psmouse, attr->data, buf); - -out: - serio_unpin_driver(serio); - return retval; + return attr->show(psmouse, attr->data, buf); } ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, @@ -1478,18 +1611,9 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev struct psmouse *psmouse, *parent = NULL; int retval; - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &psmouse_drv) { - retval = -ENODEV; - goto out_unpin; - } - retval = mutex_lock_interruptible(&psmouse_mutex); if (retval) - goto out_unpin; + goto out; psmouse = serio_get_drvdata(serio); @@ -1519,8 +1643,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev out_unlock: mutex_unlock(&psmouse_mutex); - out_unpin: - serio_unpin_driver(serio); + out: return retval; } @@ -1534,13 +1657,12 @@ static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count) { unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); - unsigned long value; - - if (strict_strtoul(buf, 10, &value)) - return -EINVAL; + unsigned int value; + int err; - if ((unsigned int)value != value) - return -EINVAL; + err = kstrtouint(buf, 10, &value); + if (err) + return err; *field = value; @@ -1572,19 +1694,16 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co if (!new_dev) return -ENOMEM; - while (serio->child) { + while (!list_empty(&serio->children)) { if (++retry > 3) { - printk(KERN_WARNING - "psmouse: failed to destroy child port, " - "protocol change aborted.\n"); + psmouse_warn(psmouse, + "failed to destroy children ports, protocol change aborted.\n"); input_free_device(new_dev); return -EIO; } mutex_unlock(&psmouse_mutex); - serio_unpin_driver(serio); serio_unregister_child_port(serio); - serio_pin_driver_uninterruptible(serio); mutex_lock(&psmouse_mutex); if (serio->drv != &psmouse_drv) { @@ -1650,10 +1769,12 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count) { - unsigned long value; + unsigned int value; + int err; - if (strict_strtoul(buf, 10, &value)) - return -EINVAL; + err = kstrtouint(buf, 10, &value); + if (err) + return err; psmouse->set_rate(psmouse, value); return count; @@ -1661,17 +1782,19 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count) { - unsigned long value; + unsigned int value; + int err; - if (strict_strtoul(buf, 10, &value)) - return -EINVAL; + err = kstrtouint(buf, 10, &value); + if (err) + return err; psmouse->set_resolution(psmouse, value); return count; } -static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) +static int psmouse_set_maxproto(const char *val, const struct kernel_param *kp) { const struct psmouse_protocol *proto; @@ -1688,7 +1811,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) return 0; } -static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) +static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp) { int type = *((unsigned int *)kp->arg); @@ -1701,10 +1824,11 @@ static int __init psmouse_init(void) lifebook_module_init(); synaptics_module_init(); + hgpk_module_init(); kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); if (!kpsmoused_wq) { - printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); + pr_err("failed to create kpsmoused workqueue\n"); return -ENOMEM; } |
