Input: psmouse - small formatting changes to better follow coding style
[cascardo/linux.git] / drivers / input / mouse / psmouse-base.c
index 401ac6b..979c502 100644 (file)
@@ -110,6 +110,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);
@@ -146,18 +147,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 +247,31 @@ 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) {
+                       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;
                        }
-                       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->name, psmouse->phys);
-                       }
-                       break;
+               }
+               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->name, psmouse->phys);
+               }
+               break;
 
-               case PSMOUSE_GOOD_DATA:
-                       break;
+       case PSMOUSE_GOOD_DATA:
+               break;
        }
        return 0;
 }
@@ -288,7 +289,9 @@ 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" : "",
@@ -627,8 +630,15 @@ static int psmouse_extensions(struct psmouse *psmouse,
                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
@@ -683,19 +693,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
                max_proto = PSMOUSE_IMEX;
        }
 
-/*
- * Try Finger Sensing Pad
- */
-       if (max_proto > PSMOUSE_IMEX) {
-               if (fsp_detect(psmouse, set_properties) == 0) {
-                       if (!set_properties || fsp_init(psmouse) == 0)
-                               return PSMOUSE_FSP;
-/*
- * Init failed, try basic relative protocols
- */
-                       max_proto = PSMOUSE_IMEX;
-               }
-       }
 
        if (max_proto > PSMOUSE_IMEX) {
                if (genius_detect(psmouse, set_properties) == 0)
@@ -711,6 +708,21 @@ static int psmouse_extensions(struct psmouse *psmouse,
                        return PSMOUSE_TOUCHKIT_PS2;
        }
 
+/*
+ * 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 (!set_properties || fsp_init(psmouse) == 0)
+                               return PSMOUSE_FSP;
+/*
+ * Init failed, try basic relative protocols
+ */
+                       max_proto = PSMOUSE_IMEX;
+               }
+       }
+
 /*
  * Reset to defaults in case the device got confused by extended
  * protocol probes. Note that we follow up with full reset because
@@ -750,6 +762,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
@@ -777,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
                .name           = "ImPS/2",
                .alias          = "imps",
                .maxproto       = true,
+               .ignore_parity  = true,
                .detect         = intellimouse_detect,
        },
        {
@@ -784,6 +798,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
@@ -1132,7 +1147,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))
+               printk(KERN_WARNING "psmouse.c: Failed to disable mouse on %s\n",
+                       psmouse->ps2dev.serio->phys);
 
        if (psmouse->cleanup)
                psmouse->cleanup(psmouse);
@@ -1206,6 +1228,7 @@ 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;
@@ -1222,16 +1245,21 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
        psmouse->pktsize = 3;
 
        if (proto && (proto->detect || proto->init)) {
-               if (proto->detect && proto->detect(psmouse, 1) < 0)
+               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 +1279,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,6 +1394,7 @@ 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) {
@@ -1385,10 +1414,15 @@ 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,
@@ -1450,24 +1484,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 +1498,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 +1530,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;
 }
 
@@ -1582,9 +1592,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
                }
 
                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) {