#include "synaptics.h"
#include "logips2pp.h"
#include "alps.h"
+#include "hgpk.h"
#include "lifebook.h"
#include "trackpoint.h"
#include "touchkit_ps2.h"
+#include "elantech.h"
+#include "sentelic.h"
#define DRIVER_DESC "PS/2 mouse driver"
struct psmouse_protocol {
enum psmouse_type type;
+ bool maxproto;
const char *name;
const char *alias;
- int maxproto;
- int (*detect)(struct psmouse *, int);
+ int (*detect)(struct psmouse *, bool);
int (*init)(struct 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.
*/
static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
{
psmouse->state = new_state;
- psmouse->pktcnt = psmouse->out_of_sync = 0;
+ psmouse->pktcnt = psmouse->out_of_sync_cnt = 0;
psmouse->ps2dev.flags = 0;
psmouse->last = jiffies;
}
* 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);
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 == psmouse->resetafter) {
+ 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);
case PSMOUSE_FULL_PACKET:
psmouse->pktcnt = 0;
- if (psmouse->out_of_sync) {
- psmouse->out_of_sync = 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);
}
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;
}
goto out;
}
- if (psmouse->packet[1] == PSMOUSE_RET_ID) {
+ if (psmouse->packet[1] == PSMOUSE_RET_ID ||
+ (psmouse->type == PSMOUSE_HGPK &&
+ psmouse->packet[1] == PSMOUSE_RET_BAT)) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
serio_reconnect(serio);
goto out;
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;
}
/*
* Genius NetMouse magic init.
*/
-static int genius_detect(struct psmouse *psmouse, int set_properties)
+static int genius_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[4];
return -1;
if (set_properties) {
- set_bit(BTN_EXTRA, psmouse->dev->keybit);
- set_bit(BTN_SIDE, psmouse->dev->keybit);
- set_bit(REL_WHEEL, psmouse->dev->relbit);
+ __set_bit(BTN_EXTRA, psmouse->dev->keybit);
+ __set_bit(BTN_SIDE, psmouse->dev->keybit);
+ __set_bit(REL_WHEEL, psmouse->dev->relbit);
psmouse->vendor = "Genius";
psmouse->name = "Mouse";
/*
* IntelliMouse magic init.
*/
-static int intellimouse_detect(struct psmouse *psmouse, int set_properties)
+static int intellimouse_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[2];
return -1;
if (set_properties) {
- set_bit(BTN_MIDDLE, psmouse->dev->keybit);
- set_bit(REL_WHEEL, psmouse->dev->relbit);
+ __set_bit(BTN_MIDDLE, psmouse->dev->keybit);
+ __set_bit(REL_WHEEL, psmouse->dev->relbit);
if (!psmouse->vendor) psmouse->vendor = "Generic";
if (!psmouse->name) psmouse->name = "Wheel Mouse";
/*
* Try IntelliMouse/Explorer magic init.
*/
-static int im_explorer_detect(struct psmouse *psmouse, int set_properties)
+static int im_explorer_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[2];
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
if (set_properties) {
- set_bit(BTN_MIDDLE, psmouse->dev->keybit);
- set_bit(REL_WHEEL, psmouse->dev->relbit);
- set_bit(REL_HWHEEL, psmouse->dev->relbit);
- set_bit(BTN_SIDE, psmouse->dev->keybit);
- set_bit(BTN_EXTRA, psmouse->dev->keybit);
+ __set_bit(BTN_MIDDLE, psmouse->dev->keybit);
+ __set_bit(REL_WHEEL, psmouse->dev->relbit);
+ __set_bit(REL_HWHEEL, psmouse->dev->relbit);
+ __set_bit(BTN_SIDE, psmouse->dev->keybit);
+ __set_bit(BTN_EXTRA, psmouse->dev->keybit);
if (!psmouse->vendor) psmouse->vendor = "Generic";
if (!psmouse->name) psmouse->name = "Explorer Mouse";
/*
* Kensington ThinkingMouse / ExpertMouse magic init.
*/
-static int thinking_detect(struct psmouse *psmouse, int set_properties)
+static int thinking_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[2];
return -1;
if (set_properties) {
- set_bit(BTN_EXTRA, psmouse->dev->keybit);
+ __set_bit(BTN_EXTRA, psmouse->dev->keybit);
psmouse->vendor = "Kensington";
psmouse->name = "ThinkingMouse";
/*
* Bare PS/2 protocol "detection". Always succeeds.
*/
-static int ps2bare_detect(struct psmouse *psmouse, int set_properties)
+static int ps2bare_detect(struct psmouse *psmouse, bool set_properties)
{
if (set_properties) {
if (!psmouse->vendor) psmouse->vendor = "Generic";
* Cortron PS/2 protocol detection. There's no special way to detect it, so it
* must be forced by sysfs protocol writing.
*/
-static int cortron_detect(struct psmouse *psmouse, int set_properties)
+static int cortron_detect(struct psmouse *psmouse, bool set_properties)
{
if (set_properties) {
psmouse->vendor = "Cortron";
psmouse->name = "PS/2 Trackball";
- set_bit(BTN_SIDE, psmouse->dev->keybit);
+ __set_bit(BTN_SIDE, psmouse->dev->keybit);
}
return 0;
*/
static int psmouse_extensions(struct psmouse *psmouse,
- unsigned int max_proto, int set_properties)
+ unsigned int max_proto, bool set_properties)
{
- int synaptics_hardware = 0;
+ bool synaptics_hardware = true;
/*
* We always check for lifebook because it does not disturb mouse
* can reset it properly after probing for intellimouse.
*/
if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) {
- synaptics_hardware = 1;
+ synaptics_hardware = true;
if (max_proto > PSMOUSE_IMEX) {
if (!set_properties || synaptics_init(psmouse) == 0)
}
}
+/*
+ * 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;
+ }
+
+/*
+ * Try Elantech touchpad.
+ */
+ if (max_proto > PSMOUSE_IMEX &&
+ elantech_detect(psmouse, set_properties) == 0) {
+ if (!set_properties || elantech_init(psmouse) == 0)
+ return PSMOUSE_ELANTECH;
+/*
+ * Init failed, try basic relative protocols
+ */
+ 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)
return PSMOUSE_GENPS;
.type = PSMOUSE_PS2,
.name = "PS/2",
.alias = "bare",
- .maxproto = 1,
+ .maxproto = true,
.detect = ps2bare_detect,
},
#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
.type = PSMOUSE_IMPS,
.name = "ImPS/2",
.alias = "imps",
- .maxproto = 1,
+ .maxproto = true,
.detect = intellimouse_detect,
},
{
.type = PSMOUSE_IMEX,
.name = "ImExPS/2",
.alias = "exps",
- .maxproto = 1,
+ .maxproto = true,
.detect = im_explorer_detect,
},
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
.detect = touchkit_ps2_detect,
},
#endif
+#ifdef CONFIG_MOUSE_PS2_OLPC
+ {
+ .type = PSMOUSE_HGPK,
+ .name = "OLPC HGPK",
+ .alias = "hgpk",
+ .detect = hgpk_detect,
+ },
+#endif
+#ifdef CONFIG_MOUSE_PS2_ELANTECH
+ {
+ .type = PSMOUSE_ELANTECH,
+ .name = "ETPS/2",
+ .alias = "elantech",
+ .detect = elantech_detect,
+ .init = elantech_init,
+ },
+#endif
+#ifdef CONFIG_MOUSE_PS2_SENTELIC
+ {
+ .type = PSMOUSE_FSP,
+ .name = "FSPPS/2",
+ .alias = "fsp",
+ .detect = fsp_detect,
+ .init = fsp_init,
+ },
+#endif
{
.type = PSMOUSE_CORTRON,
.name = "CortronPS/2",
.type = PSMOUSE_AUTO,
.name = "auto",
.alias = "any",
- .maxproto = 1,
+ .maxproto = true,
},
};
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;
+ bool failed = false, enabled = false;
int i;
mutex_lock(&psmouse_mutex);
if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) {
if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command)
- failed = 1;
+ failed = true;
} else
- psmouse->acks_disable_command = 1;
+ psmouse->acks_disable_command = true;
/*
* Poll the mouse. If it was reset the packet will be shorter than
*/
if (!failed) {
if (psmouse->poll(psmouse))
- failed = 1;
+ failed = true;
else {
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
for (i = 0; i < psmouse->pktsize; i++) {
break;
}
if (rc != PSMOUSE_FULL_PACKET)
- failed = 1;
+ failed = true;
psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
}
}
*/
for (i = 0; i < 5; i++) {
if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
- enabled = 1;
+ enabled = true;
break;
}
msleep(200);
if (!enabled) {
printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",
psmouse->ps2dev.serio->phys);
- failed = 1;
+ failed = true;
}
if (failed) {
psmouse->type = proto->type;
}
else
- psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
+ psmouse->type = psmouse_extensions(psmouse,
+ psmouse_max_proto, true);
/*
* If mouse's packet size is 3 there is no point in polling the
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);
if (psmouse->reconnect(psmouse))
goto out;
} else if (psmouse_probe(psmouse) < 0 ||
- psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0))
+ psmouse->type != psmouse_extensions(psmouse,
+ psmouse_max_proto, false)) {
goto out;
+ }
/* ok, the device type (and capabilities) match the old one,
* we can continue using it, complete intialization
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);
{
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)
while (serio->child) {
if (++retry > 3) {
- printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n");
+ printk(KERN_WARNING
+ "psmouse: failed to destroy child port, "
+ "protocol change aborted.\n");
input_free_device(new_dev);
return -EIO;
}
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);
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);
{
int type = *((unsigned int *)kp->arg);
- return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name);
+ return sprintf(buffer, "%s", psmouse_protocol_by_type(type)->name);
}
static int __init psmouse_init(void)