]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/input/mouse/psmouse-base.c
Merge branch 'linus' into core/urgent
[linux-2.6-omap-h63xx.git] / drivers / input / mouse / psmouse-base.c
index 21a9c0b69a1f461befa62691f0a35baaa99641a6..126e977e199e00764d3f2ab32aafbd0e26fbe7e8 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/delay.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
@@ -26,6 +25,7 @@
 #include "synaptics.h"
 #include "logips2pp.h"
 #include "alps.h"
+#include "hgpk.h"
 #include "lifebook.h"
 #include "trackpoint.h"
 #include "touchkit_ps2.h"
@@ -202,6 +202,12 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
        return PSMOUSE_FULL_PACKET;
 }
 
+void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
+               unsigned long delay)
+{
+       queue_delayed_work(kpsmoused_wq, work, delay);
+}
+
 /*
  * __psmouse_set_state() sets new psmouse state and resets all flags.
  */
@@ -221,7 +227,7 @@ static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_sta
  * is not a concern.
  */
 
-static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
 {
        serio_pause_rx(psmouse->ps2dev.serio);
        __psmouse_set_state(psmouse, new_state);
@@ -306,7 +312,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
                       psmouse->name, psmouse->phys, psmouse->pktcnt);
                psmouse->badbyte = psmouse->packet[0];
                __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
-               queue_work(kpsmoused_wq, &psmouse->resync_work);
+               psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
                goto out;
        }
 
@@ -343,7 +349,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
            time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {
                psmouse->badbyte = psmouse->packet[0];
                __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
-               queue_work(kpsmoused_wq, &psmouse->resync_work);
+               psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
                goto out;
        }
 
@@ -631,8 +637,20 @@ static int psmouse_extensions(struct psmouse *psmouse,
                }
        }
 
-       if (max_proto > PSMOUSE_IMEX) {
+/*
+ * Try OLPC HGPK touchpad.
+ */
+       if (max_proto > PSMOUSE_IMEX &&
+                       hgpk_detect(psmouse, set_properties) == 0) {
+               if (!set_properties || hgpk_init(psmouse) == 0)
+                       return PSMOUSE_HGPK;
+/*
+ * Init failed, try basic relative protocols
+ */
+               max_proto = PSMOUSE_IMEX;
+       }
 
+       if (max_proto > PSMOUSE_IMEX) {
                if (genius_detect(psmouse, set_properties) == 0)
                        return PSMOUSE_GENPS;
 
@@ -762,6 +780,14 @@ static const struct psmouse_protocol psmouse_protocols[] = {
                .alias          = "touchkit",
                .detect         = touchkit_ps2_detect,
        },
+#endif
+#ifdef CONFIG_MOUSE_PS2_OLPC
+       {
+               .type           = PSMOUSE_HGPK,
+               .name           = "OLPC HGPK",
+               .alias          = "hgpk",
+               .detect         = hgpk_detect,
+       },
 #endif
        {
                .type           = PSMOUSE_CORTRON,
@@ -936,7 +962,7 @@ static int psmouse_poll(struct psmouse *psmouse)
 static void psmouse_resync(struct work_struct *work)
 {
        struct psmouse *parent = NULL, *psmouse =
-               container_of(work, struct psmouse, resync_work);
+               container_of(work, struct psmouse, resync_work.work);
        struct serio *serio = psmouse->ps2dev.serio;
        psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
        int failed = 0, enabled = 0;
@@ -1195,7 +1221,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
                goto err_free;
 
        ps2_init(&psmouse->ps2dev, serio);
-       INIT_WORK(&psmouse->resync_work, psmouse_resync);
+       INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync);
        psmouse->dev = input_dev;
        snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
 
@@ -1247,6 +1273,8 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
  err_pt_deactivate:
        if (parent && parent->pt_deactivate)
                parent->pt_deactivate(parent);
+       input_unregister_device(psmouse->dev);
+       input_dev = NULL; /* so we don't try to free it below */
  err_protocol_disconnect:
        if (psmouse->disconnect)
                psmouse->disconnect(psmouse);
@@ -1394,25 +1422,29 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
 
        psmouse = serio_get_drvdata(serio);
 
-       if (psmouse->state == PSMOUSE_IGNORE) {
-               retval = -ENODEV;
-               goto out_unlock;
-       }
+       if (attr->protect) {
+               if (psmouse->state == PSMOUSE_IGNORE) {
+                       retval = -ENODEV;
+                       goto out_unlock;
+               }
 
-       if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
-               parent = serio_get_drvdata(serio->parent);
-               psmouse_deactivate(parent);
-       }
+               if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+                       parent = serio_get_drvdata(serio->parent);
+                       psmouse_deactivate(parent);
+               }
 
-       psmouse_deactivate(psmouse);
+               psmouse_deactivate(psmouse);
+       }
 
        retval = attr->set(psmouse, attr->data, buf, count);
 
-       if (retval != -ENODEV)
-               psmouse_activate(psmouse);
+       if (attr->protect) {
+               if (retval != -ENODEV)
+                       psmouse_activate(psmouse);
 
-       if (parent)
-               psmouse_activate(parent);
+               if (parent)
+                       psmouse_activate(parent);
+       }
 
  out_unlock:
        mutex_unlock(&psmouse_mutex);
@@ -1432,10 +1464,8 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const
 {
        unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset);
        unsigned long value;
-       char *rest;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest)
+       if (strict_strtoul(buf, 10, &value))
                return -EINVAL;
 
        if ((unsigned int)value != value)
@@ -1548,10 +1578,8 @@ 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;
-       char *rest;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest)
+       if (strict_strtoul(buf, 10, &value))
                return -EINVAL;
 
        psmouse->set_rate(psmouse, value);
@@ -1561,10 +1589,8 @@ 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;
-       char *rest;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest)
+       if (strict_strtoul(buf, 10, &value))
                return -EINVAL;
 
        psmouse->set_resolution(psmouse, value);