···3232MODULE_DESCRIPTION(DRIVER_DESC);3333MODULE_LICENSE("GPL");34343535-static unsigned int psmouse_max_proto = -1U;3535+static unsigned int psmouse_max_proto = PSMOUSE_AUTO;3636static int psmouse_set_maxproto(const char *val, struct kernel_param *kp);3737static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp);3838-static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, "lifebook" };3938#define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int)4039#define param_set_proto_abbrev psmouse_set_maxproto4140#define param_get_proto_abbrev psmouse_get_maxproto4241module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644);4343-MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, lifebook, any). Useful for KVM switches.");4242+MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches.");44434544static unsigned int psmouse_resolution = 200;4645module_param_named(resolution, psmouse_resolution, uint, 0644);···5758module_param_named(resetafter, psmouse_resetafter, uint, 0644);5859MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");59606161+PSMOUSE_DEFINE_ATTR(protocol);6062PSMOUSE_DEFINE_ATTR(rate);6163PSMOUSE_DEFINE_ATTR(resolution);6264PSMOUSE_DEFINE_ATTR(resetafter);···7777 */7878static DECLARE_MUTEX(psmouse_sem);79798080-static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2", "LBPS/2" };8080+struct psmouse_protocol {8181+ enum psmouse_type type;8282+ char *name;8383+ char *alias;8484+ int maxproto;8585+ int (*detect)(struct psmouse *, int);8686+ int (*init)(struct psmouse *);8787+};81888289/*8390 * psmouse_process_byte() analyzes the PS/2 data stream and reports···424417 */425418static int ps2bare_detect(struct psmouse *psmouse, int set_properties)426419{427427- if (!psmouse->vendor) psmouse->vendor = "Generic";428428- if (!psmouse->name) psmouse->name = "Mouse";420420+ if (set_properties) {421421+ if (!psmouse->vendor) psmouse->vendor = "Generic";422422+ if (!psmouse->name) psmouse->name = "Mouse";423423+ }429424430425 return 0;431426}427427+432428433429/*434430 * psmouse_extensions() probes for any extensions to the basic PS/2 protocol···447437 * We always check for lifebook because it does not disturb mouse448438 * (it only checks DMI information).449439 */450450- if (lifebook_detect(psmouse, set_properties) == 0 ||451451- max_proto == PSMOUSE_LIFEBOOK) {452452-440440+ if (lifebook_detect(psmouse, set_properties) == 0) {453441 if (max_proto > PSMOUSE_IMEX) {454442 if (!set_properties || lifebook_init(psmouse) == 0)455443 return PSMOUSE_LIFEBOOK;···536528537529 return PSMOUSE_PS2;538530}531531+532532+static struct psmouse_protocol psmouse_protocols[] = {533533+ {534534+ .type = PSMOUSE_PS2,535535+ .name = "PS/2",536536+ .alias = "bare",537537+ .maxproto = 1,538538+ .detect = ps2bare_detect,539539+ },540540+ {541541+ .type = PSMOUSE_PS2PP,542542+ .name = "PS2++",543543+ .alias = "logitech",544544+ .detect = ps2pp_init,545545+ },546546+ {547547+ .type = PSMOUSE_THINKPS,548548+ .name = "ThinkPS/2",549549+ .alias = "thinkps",550550+ .detect = thinking_detect,551551+ },552552+ {553553+ .type = PSMOUSE_GENPS,554554+ .name = "GenPS/2",555555+ .alias = "genius",556556+ .detect = genius_detect,557557+ },558558+ {559559+ .type = PSMOUSE_IMPS,560560+ .name = "ImPS/2",561561+ .alias = "imps",562562+ .maxproto = 1,563563+ .detect = intellimouse_detect,564564+ },565565+ {566566+ .type = PSMOUSE_IMEX,567567+ .name = "ImExPS/2",568568+ .alias = "exps",569569+ .maxproto = 1,570570+ .detect = im_explorer_detect,571571+ },572572+ {573573+ .type = PSMOUSE_SYNAPTICS,574574+ .name = "SynPS/2",575575+ .alias = "synaptics",576576+ .detect = synaptics_detect,577577+ .init = synaptics_init,578578+ },579579+ {580580+ .type = PSMOUSE_ALPS,581581+ .name = "AlpsPS/2",582582+ .alias = "alps",583583+ .detect = alps_detect,584584+ .init = alps_init,585585+ },586586+ {587587+ .type = PSMOUSE_LIFEBOOK,588588+ .name = "LBPS/2",589589+ .alias = "lifebook",590590+ .init = lifebook_init,591591+ },592592+ {593593+ .type = PSMOUSE_AUTO,594594+ .name = "auto",595595+ .alias = "any",596596+ .maxproto = 1,597597+ },598598+};599599+600600+static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type)601601+{602602+ int i;603603+604604+ for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++)605605+ if (psmouse_protocols[i].type == type)606606+ return &psmouse_protocols[i];607607+608608+ WARN_ON(1);609609+ return &psmouse_protocols[0];610610+}611611+612612+static struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len)613613+{614614+ struct psmouse_protocol *p;615615+ int i;616616+617617+ for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) {618618+ p = &psmouse_protocols[i];619619+620620+ if ((strlen(p->name) == len && !strncmp(p->name, name, len)) ||621621+ (strlen(p->alias) == len && !strncmp(p->alias, name, len)))622622+ return &psmouse_protocols[i];623623+ }624624+625625+ return NULL;626626+}627627+539628540629/*541630 * psmouse_probe() probes for a PS/2 mouse.···785680786681 psmouse = serio_get_drvdata(serio);787682683683+ device_remove_file(&serio->dev, &psmouse_attr_protocol);788684 device_remove_file(&serio->dev, &psmouse_attr_rate);789685 device_remove_file(&serio->dev, &psmouse_attr_resolution);790686 device_remove_file(&serio->dev, &psmouse_attr_resetafter);···818712 up(&psmouse_sem);819713}820714715715+static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)716716+{717717+ memset(&psmouse->dev, 0, sizeof(struct input_dev));718718+719719+ init_input_dev(&psmouse->dev);720720+721721+ psmouse->dev.private = psmouse;722722+ psmouse->dev.dev = &psmouse->ps2dev.serio->dev;723723+724724+ psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);725725+ psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);726726+ psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);727727+728728+ psmouse->set_rate = psmouse_set_rate;729729+ psmouse->set_resolution = psmouse_set_resolution;730730+ psmouse->protocol_handler = psmouse_process_byte;731731+ psmouse->pktsize = 3;732732+733733+ if (proto && (proto->detect || proto->init)) {734734+ if (proto->detect && proto->detect(psmouse, 1) < 0)735735+ return -1;736736+737737+ if (proto->init && proto->init(psmouse) < 0)738738+ return -1;739739+740740+ psmouse->type = proto->type;741741+ }742742+ else743743+ psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);744744+745745+ sprintf(psmouse->devname, "%s %s %s",746746+ psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);747747+748748+ psmouse->dev.name = psmouse->devname;749749+ psmouse->dev.phys = psmouse->phys;750750+ psmouse->dev.id.bustype = BUS_I8042;751751+ psmouse->dev.id.vendor = 0x0002;752752+ psmouse->dev.id.product = psmouse->type;753753+ psmouse->dev.id.version = psmouse->model;754754+755755+ return 0;756756+}757757+821758/*822759 * psmouse_connect() is a callback from the serio module when823760 * an unhandled serio port is found.···888739889740 ps2_init(&psmouse->ps2dev, serio);890741 sprintf(psmouse->phys, "%s/input0", serio->phys);891891- psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);892892- psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);893893- psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);894894- psmouse->dev.private = psmouse;895895- psmouse->dev.dev = &serio->dev;742742+896743 psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);897744898745 serio_set_drvdata(serio, psmouse);···912767 psmouse->resolution = psmouse_resolution;913768 psmouse->resetafter = psmouse_resetafter;914769 psmouse->smartscroll = psmouse_smartscroll;915915- psmouse->set_rate = psmouse_set_rate;916916- psmouse->set_resolution = psmouse_set_resolution;917917- psmouse->protocol_handler = psmouse_process_byte;918918- psmouse->pktsize = 3;919770920920- psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);921921-922922- sprintf(psmouse->devname, "%s %s %s",923923- psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);924924-925925- psmouse->dev.name = psmouse->devname;926926- psmouse->dev.phys = psmouse->phys;927927- psmouse->dev.id.bustype = BUS_I8042;928928- psmouse->dev.id.vendor = 0x0002;929929- psmouse->dev.id.product = psmouse->type;930930- psmouse->dev.id.version = psmouse->model;771771+ psmouse_switch_protocol(psmouse, NULL);931772932773 input_register_device(&psmouse->dev);933933-934774 printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);935775936776 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);···925795 if (parent && parent->pt_activate)926796 parent->pt_activate(parent);927797798798+ device_create_file(&serio->dev, &psmouse_attr_protocol);928799 device_create_file(&serio->dev, &psmouse_attr_rate);929800 device_create_file(&serio->dev, &psmouse_attr_resolution);930801 device_create_file(&serio->dev, &psmouse_attr_resetafter);···1077946 parent = serio_get_drvdata(serio->parent);1078947 psmouse_deactivate(parent);1079948 }949949+1080950 psmouse_deactivate(psmouse);10819511082952 retval = handler(psmouse, buf, count);108395310841084- psmouse_activate(psmouse);954954+ if (retval != -ENODEV)955955+ psmouse_activate(psmouse);956956+1085957 if (parent)1086958 psmouse_activate(parent);1087959···1093959 out_unpin:1094960 serio_unpin_driver(serio);1095961 return retval;962962+}963963+964964+static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf)965965+{966966+ return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);967967+}968968+969969+static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count)970970+{971971+ struct serio *serio = psmouse->ps2dev.serio;972972+ struct psmouse *parent = NULL;973973+ struct psmouse_protocol *proto;974974+ int retry = 0;975975+976976+ if (!(proto = psmouse_protocol_by_name(buf, count)))977977+ return -EINVAL;978978+979979+ if (psmouse->type == proto->type)980980+ return count;981981+982982+ while (serio->child) {983983+ if (++retry > 3) {984984+ printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n");985985+ return -EIO;986986+ }987987+988988+ up(&psmouse_sem);989989+ serio_unpin_driver(serio);990990+ serio_unregister_child_port(serio);991991+ serio_pin_driver_uninterruptible(serio);992992+ down(&psmouse_sem);993993+994994+ if (serio->drv != &psmouse_drv)995995+ return -ENODEV;996996+997997+ if (psmouse->type == proto->type)998998+ return count; /* switched by other thread */999999+ }10001000+10011001+ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {10021002+ parent = serio_get_drvdata(serio->parent);10031003+ if (parent->pt_deactivate)10041004+ parent->pt_deactivate(parent);10051005+ }10061006+10071007+ if (psmouse->disconnect)10081008+ psmouse->disconnect(psmouse);10091009+10101010+ psmouse_set_state(psmouse, PSMOUSE_IGNORE);10111011+ input_unregister_device(&psmouse->dev);10121012+10131013+ psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);10141014+10151015+ if (psmouse_switch_protocol(psmouse, proto) < 0) {10161016+ psmouse_reset(psmouse);10171017+ /* default to PSMOUSE_PS2 */10181018+ psmouse_switch_protocol(psmouse, &psmouse_protocols[0]);10191019+ }10201020+10211021+ psmouse_initialize(psmouse);10221022+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);10231023+10241024+ input_register_device(&psmouse->dev);10251025+ printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);10261026+10271027+ if (parent && parent->pt_activate)10281028+ parent->pt_activate(parent);10291029+10301030+ return count;10961031}1097103210981033static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf)···1220101712211018static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)12221019{12231223- int i;10201020+ struct psmouse_protocol *proto;1224102112251022 if (!val)12261023 return -EINVAL;1227102412281228- if (!strncmp(val, "any", 3)) {12291229- *((unsigned int *)kp->arg) = -1U;12301230- return 0;12311231- }10251025+ proto = psmouse_protocol_by_name(val, strlen(val));1232102612331233- for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) {12341234- if (!psmouse_proto_abbrev[i])12351235- continue;10271027+ if (!proto || !proto->maxproto)10281028+ return -EINVAL;1236102912371237- if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) {12381238- *((unsigned int *)kp->arg) = i;12391239- return 0;12401240- }12411241- }10301030+ *((unsigned int *)kp->arg) = proto->type;1242103112431243- return -EINVAL; \10321032+ return 0; \12441033}1245103412461035static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)12471036{12481248- return sprintf(buffer, "%s\n",12491249- psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ?12501250- psmouse_proto_abbrev[psmouse_max_proto] : "any");10371037+ int type = *((unsigned int *)kp->arg);10381038+10391039+ return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name);12511040}1252104112531042static int __init psmouse_init(void)
+1
drivers/input/mouse/psmouse.h
···7878 PSMOUSE_SYNAPTICS,7979 PSMOUSE_ALPS,8080 PSMOUSE_LIFEBOOK,8181+ PSMOUSE_AUTO /* This one should always be last */8182};82838384int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
+16-2
drivers/input/serio/serio.c
···4242EXPORT_SYMBOL(serio_interrupt);4343EXPORT_SYMBOL(__serio_register_port);4444EXPORT_SYMBOL(serio_unregister_port);4545+EXPORT_SYMBOL(serio_unregister_child_port);4546EXPORT_SYMBOL(__serio_unregister_port_delayed);4647EXPORT_SYMBOL(__serio_register_driver);4748EXPORT_SYMBOL(serio_unregister_driver);···180179 spin_lock_irqsave(&serio_event_lock, flags);181180182181 /*183183- * Scan event list for the other events for the same serio port,182182+ * Scan event list for the other events for the same serio port,184183 * starting with the most recent one. If event is the same we185184 * do not need add new one. If event is of different type we186185 * need to add this event and should not look further because187186 * we need to preseve sequence of distinct events.188188- */187187+ */189188 list_for_each_entry_reverse(event, &serio_event_list, node) {190189 if (event->object == object) {191190 if (event->type == event_type)···651650 down(&serio_sem);652651 serio_disconnect_port(serio);653652 serio_destroy_port(serio);653653+ up(&serio_sem);654654+}655655+656656+/*657657+ * Safely unregisters child port if one is present.658658+ */659659+void serio_unregister_child_port(struct serio *serio)660660+{661661+ down(&serio_sem);662662+ if (serio->child) {663663+ serio_disconnect_port(serio->child);664664+ serio_destroy_port(serio->child);665665+ }654666 up(&serio_sem);655667}656668