Input: elantech - relax signature checks
[cascardo/linux.git] / drivers / input / mouse / elantech.c
index 0520c2e..b18862b 100644 (file)
@@ -10,6 +10,8 @@
  * Trademarks are the property of their respective owners.
  */
 
+#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
+
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include "psmouse.h"
 #include "elantech.h"
 
-#define elantech_debug(format, arg...)                         \
-       do {                                                    \
-               if (etd->debug)                                 \
-                       printk(KERN_DEBUG format, ##arg);       \
+#define elantech_debug(fmt, ...)                                       \
+       do {                                                            \
+               if (etd->debug)                                         \
+                       printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__);  \
        } while (0)
 
 static bool force_elantech;
@@ -37,7 +39,7 @@ static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c,
 {
        if (psmouse_sliced_command(psmouse, c) ||
            ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
-               pr_err("elantech.c: synaptics_send_cmd query 0x%02x failed.\n", c);
+               pr_err("synaptics_send_cmd query 0x%02x failed.\n", c);
                return -1;
        }
 
@@ -60,13 +62,13 @@ static int elantech_ps2_command(struct psmouse *psmouse,
                if (rc == 0)
                        break;
                tries--;
-               elantech_debug("elantech.c: retrying ps2 command 0x%02x (%d).\n",
-                       command, tries);
+               elantech_debug("retrying ps2 command 0x%02x (%d).\n",
+                               command, tries);
                msleep(ETP_PS2_COMMAND_DELAY);
        } while (tries > 0);
 
        if (rc)
-               pr_err("elantech.c: ps2 command 0x%02x failed.\n", command);
+               pr_err("ps2 command 0x%02x failed.\n", command);
 
        return rc;
 }
@@ -108,7 +110,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
        }
 
        if (rc)
-               pr_err("elantech.c: failed to read register 0x%02x.\n", reg);
+               pr_err("failed to read register 0x%02x.\n", reg);
        else
                *val = param[0];
 
@@ -154,7 +156,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
        }
 
        if (rc)
-               pr_err("elantech.c: failed to write register 0x%02x with value 0x%02x.\n",
+               pr_err("failed to write register 0x%02x with value 0x%02x.\n",
                        reg, val);
 
        return rc;
@@ -167,7 +169,7 @@ static void elantech_packet_dump(unsigned char *packet, int size)
 {
        int     i;
 
-       printk(KERN_DEBUG "elantech.c: PS/2 packet [");
+       printk(KERN_DEBUG pr_fmt("PS/2 packet ["));
        for (i = 0; i < size; i++)
                printk("%s0x%02x ", (i) ? ", " : " ", packet[i]);
        printk("]\n");
@@ -185,7 +187,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
        int fingers;
        static int old_fingers;
 
-       if (etd->fw_version_maj == 0x01) {
+       if (etd->fw_version < 0x020000) {
                /*
                 * byte 0:  D   U  p1  p2   1  p3   R   L
                 * byte 1:  f   0  th  tw  x9  x8  y9  y8
@@ -203,7 +205,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
        if (etd->jumpy_cursor) {
                /* Discard packets that are likely to have bogus coordinates */
                if (fingers > old_fingers) {
-                       elantech_debug("elantech.c: discarding packet\n");
+                       elantech_debug("discarding packet\n");
                        goto discard_packet_v1;
                }
        }
@@ -227,7 +229,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
        input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
        input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
 
-       if ((etd->fw_version_maj == 0x01) &&
+       if (etd->fw_version < 0x020000 &&
            (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
                /* rocker up */
                input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
@@ -321,7 +323,7 @@ static int elantech_check_parity_v1(struct psmouse *psmouse)
        unsigned char p1, p2, p3;
 
        /* Parity bits are placed differently */
-       if (etd->fw_version_maj == 0x01) {
+       if (etd->fw_version < 0x020000) {
                /* byte 0:  D   U  p1  p2   1  p3   R   L */
                p1 = (packet[0] & 0x20) >> 5;
                p2 = (packet[0] & 0x10) >> 4;
@@ -413,23 +415,21 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
                        if (rc == 0)
                                break;
                        tries--;
-                       elantech_debug("elantech.c: retrying read (%d).\n",
-                                       tries);
+                       elantech_debug("retrying read (%d).\n", tries);
                        msleep(ETP_READ_BACK_DELAY);
                } while (tries > 0);
 
                if (rc) {
-                       pr_err("elantech.c: failed to read back register 0x10.\n");
+                       pr_err("failed to read back register 0x10.\n");
                } else if (etd->hw_version == 1 &&
                           !(val & ETP_R10_ABSOLUTE_MODE)) {
-                       pr_err("elantech.c: touchpad refuses "
-                               "to switch to absolute mode.\n");
+                       pr_err("touchpad refuses to switch to absolute mode.\n");
                        rc = -1;
                }
        }
 
        if (rc)
-               pr_err("elantech.c: failed to initialise registers.\n");
+               pr_err("failed to initialise registers.\n");
 
        return rc;
 }
@@ -457,7 +457,7 @@ static void elantech_set_input_params(struct psmouse *psmouse)
        switch (etd->hw_version) {
        case 1:
                /* Rocker button */
-               if ((etd->fw_version_maj == 0x01) &&
+               if (etd->fw_version < 0x020000 &&
                    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
                        __set_bit(BTN_FORWARD, dev->keybit);
                        __set_bit(BTN_BACK, dev->keybit);
@@ -575,6 +575,24 @@ static struct attribute_group elantech_attr_group = {
        .attrs = elantech_attrs,
 };
 
+static bool elantech_is_signature_valid(const unsigned char *param)
+{
+       static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10 };
+       int i;
+
+       if (param[0] == 0)
+               return false;
+
+       if (param[1] == 0)
+               return true;
+
+       for (i = 0; i < ARRAY_SIZE(rates); i++)
+               if (param[2] == rates[i])
+                       return false;
+
+       return true;
+}
+
 /*
  * Use magic knock to detect Elantech touchpad
  */
@@ -590,7 +608,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
            ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
            ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
            ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
-               pr_debug("elantech.c: sending Elantech magic knock failed.\n");
+               pr_debug("sending Elantech magic knock failed.\n");
                return -1;
        }
 
@@ -599,8 +617,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
         * set of magic numbers
         */
        if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) {
-               pr_debug("elantech.c: "
-                        "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
+               pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
                         param[0], param[1], param[2]);
                return -1;
        }
@@ -611,20 +628,20 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
         * to Elantech magic knock and there might be more.
         */
        if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
-               pr_debug("elantech.c: failed to query firmware version.\n");
+               pr_debug("failed to query firmware version.\n");
                return -1;
        }
 
-       pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
+       pr_debug("Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
                 param[0], param[1], param[2]);
 
-       if (param[0] == 0 || param[1] != 0) {
+       if (!elantech_is_signature_valid(param)) {
                if (!force_elantech) {
-                       pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n");
+                       pr_debug("Probably not a real Elantech touchpad. Aborting.\n");
                        return -1;
                }
 
-               pr_debug("elantech.c: Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n");
+               pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n");
        }
 
        if (set_properties) {
@@ -655,7 +672,7 @@ static int elantech_reconnect(struct psmouse *psmouse)
                return -1;
 
        if (elantech_set_absolute_mode(psmouse)) {
-               pr_err("elantech.c: failed to put touchpad back into absolute mode.\n");
+               pr_err("failed to put touchpad back into absolute mode.\n");
                return -1;
        }
 
@@ -683,18 +700,17 @@ int elantech_init(struct psmouse *psmouse)
         * Do the version query again so we can store the result
         */
        if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
-               pr_err("elantech.c: failed to query firmware version.\n");
+               pr_err("failed to query firmware version.\n");
                goto init_fail;
        }
-       etd->fw_version_maj = param[0];
-       etd->fw_version_min = param[2];
+
+       etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
 
        /*
         * Assume every version greater than this is new EeePC style
         * hardware with 6 byte packets
         */
-       if ((etd->fw_version_maj == 0x02 && etd->fw_version_min >= 0x30) ||
-           etd->fw_version_maj > 0x02) {
+       if (etd->fw_version >= 0x020030) {
                etd->hw_version = 2;
                /* For now show extra debug information */
                etd->debug = 1;
@@ -704,14 +720,15 @@ int elantech_init(struct psmouse *psmouse)
                etd->hw_version = 1;
                etd->paritycheck = 1;
        }
-       pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n",
-               etd->hw_version, etd->fw_version_maj, etd->fw_version_min);
+
+       pr_info("assuming hardware version %d, firmware version %d.%d.%d\n",
+               etd->hw_version, param[0], param[1], param[2]);
 
        if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) {
-               pr_err("elantech.c: failed to query capabilities.\n");
+               pr_err("failed to query capabilities.\n");
                goto init_fail;
        }
-       pr_info("elantech.c: Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
+       pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
                param[0], param[1], param[2]);
        etd->capabilities = param[0];
 
@@ -720,14 +737,13 @@ int elantech_init(struct psmouse *psmouse)
         * a touch action starts causing the mouse cursor or scrolled page
         * to jump. Enable a workaround.
         */
-       if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) {
-               pr_info("elantech.c: firmware version 2.34 detected, "
-                       "enabling jumpy cursor workaround\n");
+       if (etd->fw_version == 0x020022) {
+               pr_info("firmware version 2.0.34 detected, enabling jumpy cursor workaround\n");
                etd->jumpy_cursor = 1;
        }
 
        if (elantech_set_absolute_mode(psmouse)) {
-               pr_err("elantech.c: failed to put touchpad into absolute mode.\n");
+               pr_err("failed to put touchpad into absolute mode.\n");
                goto init_fail;
        }
 
@@ -736,8 +752,7 @@ int elantech_init(struct psmouse *psmouse)
        error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
                                   &elantech_attr_group);
        if (error) {
-               pr_err("elantech.c: failed to create sysfs attributes, error: %d.\n",
-                       error);
+               pr_err("failed to create sysfs attributes, error: %d.\n", error);
                goto init_fail;
        }