diff options
author | Andres Salomon <dilinger@debian.org> | 2008-09-12 18:33:06 -0400 |
---|---|---|
committer | Andres Salomon <dilinger@debian.org> | 2008-09-12 18:33:06 -0400 |
commit | 93970329291a9ff73301a96a27c4af274f096835 (patch) | |
tree | e3b20722e7946ef99ca5ccaff8e9298aad208d3a | |
parent | e31284e8bd4c73a93fbcc36916634b1f1c123c2b (diff) | |
download | lwn-93970329291a9ff73301a96a27c4af274f096835.tar.gz lwn-93970329291a9ff73301a96a27c4af274f096835.zip |
psmouse: upstream sync, fix low power toggle bugs
Signed-off-by: Andres Salomon <dilinger@debian.org>
-rw-r--r-- | drivers/input/mouse/olpc.c | 109 | ||||
-rw-r--r-- | drivers/input/mouse/olpc.h | 1 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 44 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse.h | 11 |
4 files changed, 79 insertions, 86 deletions
diff --git a/drivers/input/mouse/olpc.c b/drivers/input/mouse/olpc.c index 4d7adbfb3c01..af6169f1bfb1 100644 --- a/drivers/input/mouse/olpc.c +++ b/drivers/input/mouse/olpc.c @@ -69,7 +69,7 @@ static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y) /* My car gets forty rods to the hogshead and that's the * way I likes it! */ - queue_delayed_work(kpsmoused_wq, &priv->recalib_wq, + psmouse_queue_work(psmouse, &priv->recalib_wq, msecs_to_jiffies(1000)); } } @@ -93,33 +93,30 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, int l, int r, int x, int y) { struct hgpk_data *priv = psmouse->private; - static int count; - static int x_tally; - static int y_tally; /* ignore button press packets; many in a row could trigger * a false-positive! */ if (l || r) return; - count++; - x_tally += x; - y_tally += y; - if (count > 100) { - if (abs(x_tally) < 3 && abs(y_tally) < 3) { + priv->count++; + priv->x_tally += x; + priv->y_tally += y; + if (priv->count > 100) { + if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { hgpk_dbg(psmouse, "packet spew detected (%d,%d). :(\n", - x_tally, y_tally); + priv->x_tally, priv->y_tally); /* We had to say dickety 'cause that Kaiser had * stolen our word twenty. I chased that rascal to * get it back, but gave up after dickety six miles */ - queue_delayed_work(kpsmoused_wq, &priv->recalib_wq, + psmouse_queue_work(psmouse, &priv->recalib_wq, msecs_to_jiffies(1000)); } /* reset every 100 packets */ - count = 0; - x_tally = 0; - y_tally = 0; + priv->count = 0; + priv->x_tally = 0; + priv->y_tally = 0; } } @@ -192,7 +189,7 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) * window, schedule another recalibration. */ hgpk_dbg(psmouse, "packet inside calibration window, queueing another recalibration\n"); - queue_delayed_work(kpsmoused_wq, &priv->recalib_wq, + psmouse_queue_work(psmouse, &priv->recalib_wq, msecs_to_jiffies(1000)); } priv->recalib_window = 0; @@ -287,9 +284,16 @@ static int hgpk_toggle_power(struct psmouse *psmouse, int enable) psmouse_reset(psmouse); + /* should be all set, enable the touchpad */ + ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); + psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); + } else { hgpk_dbg(psmouse, "Powering off touchpad.\n"); - psmouse_set_state(psmouse, PSMOUSE_IGNORE); + + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) + return -1; + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); if (ps2_command(ps2dev, NULL, 0xec) || ps2_command(ps2dev, NULL, 0xec) || @@ -319,77 +323,47 @@ static int hgpk_reconnect(struct psmouse *psmouse) return 0; } -static ssize_t hgpk_show_pwred(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf) { - struct serio *serio = to_serio_port(dev); - struct psmouse *psmouse; struct hgpk_data *priv; - int retval; - retval = serio_pin_driver(serio); - if (retval) - return retval; - - psmouse = serio_get_drvdata(serio); priv = psmouse->private; - - retval = sprintf(buf, "%d\n", priv->powered); - serio_unpin_driver(serio); - return retval; + return sprintf(buf, "%d\n", priv->powered); } -static ssize_t hgpk_set_pwred(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, + const char *buf, size_t count) { - struct serio *serio = to_serio_port(dev); - struct psmouse *psmouse; struct hgpk_data *priv; - unsigned long val; - int retval; - - if (*buf == '1') - val = 1; - else if (*buf == '0') - val = 0; - else - return -EINVAL; - - retval = serio_pin_driver(serio); - if (retval) - return retval; + unsigned long value; + int err; -/* - * FUCK IT. I don't fucking care. locking in psmouse is fucking retarded! - retval = mutex_lock_interruptible(&psmouse_mutex); - if (retval) - goto out_unpin; -*/ + err = strict_strtoul(buf, 10, &value); + if (err || value > 1) + return -EINVAL; - psmouse = serio_get_drvdata(serio); priv = psmouse->private; + if (value == priv->powered) + return count; - if (val == priv->powered) - goto done; - - retval = hgpk_toggle_power(psmouse, val); - if (!retval) - priv->powered = val; + /* hgpk_toggle_power will deal w/ state so we're not racing w/ irq */ + err = hgpk_toggle_power(psmouse, value); + if (!err) + priv->powered = value; -done: - serio_unpin_driver(serio); - return retval ? retval : count; + return err ? err : count; } -static DEVICE_ATTR(pwred, S_IWUSR | S_IRUGO, hgpk_show_pwred, hgpk_set_pwred); +__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, hgpk_show_powered, + hgpk_set_powered, 0); static void hgpk_disconnect(struct psmouse *psmouse) { struct hgpk_data *priv = psmouse->private; - device_remove_file(&psmouse->ps2dev.serio->dev, &dev_attr_pwred); + device_remove_file(&psmouse->ps2dev.serio->dev, + &psmouse_attr_powered.dattr); psmouse_reset(psmouse); - flush_scheduled_work(); kfree(priv); } @@ -435,7 +409,8 @@ static int hgpk_init(struct psmouse *psmouse) /* Reset after a lot of bad bytes. */ psmouse->resetafter = 1024; - err = device_create_file(&psmouse->ps2dev.serio->dev, &dev_attr_pwred); + err = device_create_file(&psmouse->ps2dev.serio->dev, + &psmouse_attr_powered.dattr); if (err) hgpk_err(psmouse, "Failed to create sysfs attribute\n"); diff --git a/drivers/input/mouse/olpc.h b/drivers/input/mouse/olpc.h index c2d161b6d03d..319b570d8689 100644 --- a/drivers/input/mouse/olpc.h +++ b/drivers/input/mouse/olpc.h @@ -26,6 +26,7 @@ enum hgpk_model_t { struct hgpk_data { struct psmouse *psmouse; int powered; + int count, x_tally, y_tally; /* hardware workaround stuff */ unsigned long recalib_window; struct delayed_work recalib_wq; }; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 28aa38db166b..eb999580058b 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -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. */ @@ -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; } @@ -344,7 +350,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; } @@ -958,7 +964,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; @@ -1217,7 +1223,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); @@ -1418,25 +1424,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); diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 67af5a50ec4c..a573b7aa3d85 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -39,7 +39,7 @@ struct psmouse { void *private; struct input_dev *dev; struct ps2dev ps2dev; - struct work_struct resync_work; + struct delayed_work resync_work; char *vendor; char *name; unsigned char packet[8]; @@ -93,6 +93,8 @@ enum psmouse_type { PSMOUSE_AUTO /* This one should always be last */ }; +void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, + unsigned long delay); int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); int psmouse_reset(struct psmouse *psmouse); void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); @@ -106,6 +108,7 @@ struct psmouse_attribute { ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); ssize_t (*set)(struct psmouse *psmouse, void *data, const char *buf, size_t count); + int protect; }; #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) @@ -114,7 +117,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); -#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ +#define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ static ssize_t _show(struct psmouse *, void *data, char *); \ static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ static struct psmouse_attribute psmouse_attr_##_name = { \ @@ -129,6 +132,10 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ .data = _data, \ .show = _show, \ .set = _set, \ + .protect = _protect, \ } +#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ + __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1) + #endif /* _PSMOUSE_H */ |