On Fri, May 2, 2008 at 10:42 PM, Denver Gingerich <[EMAIL PROTECTED]> wrote:
>
> On Thu, May 1, 2008 at 11:38 PM, Denver Gingerich <[EMAIL PROTECTED]> wrote:
> > On 2.6.22-20080123.4 and newer master kernels (specifically
> > 2.6.22-20080123.4, 2.6.25-20080430.1, 2.6.25-20080501.2, and
> > 2.6.25-20080501.3), the cursor cannot move from side to side with the
> > touchpad, only up and down. Using a USB mouse works fine.
> >
> > Here is an example X session:
> > 1. start X, cursor is in the center of the screen; touchpad has not been
> touched
> > 2. touch touchpad, cursor immediately jumps to the left side of the screen
See below for more details on Step 2.
> > 3. move around on touchpad, cursor stays "stuck" to the left side of
> > the screen, but moves up and down relative to how much vertical
> > touchpad movement there is
> > 4a. release finger from touchpad, cursor immediately jumps to the
> > top-left corner of the screen (this may not be exactly the top-left
> > corner, but it is always on the left-most column of pixels within the
> > top 50-100 rows of pixels)
> > 4b. move finger across right edge of touchpad, cursor moves very
> > quickly from left to right across the screen (there appears to be a
> > small area between the touchpad and the right third of the drawing pad
> > where left to right motion is detected)
> >
> > Performing steps 2-4 consistently gives the same results within the
> > same X session and across reboots.
[...]
>
> The problem is present in 2.6.22-2008115.1 but not in
> 2.6.22-20080113.1.
The problem is also present in 2.6.22-20080114.2. So the problem is
between the following commits:
f8709785a433a5a3344304f9796fb26a65d69a1e
cb6634de39d36cb9cc719c2940e456929ccceea2
I attached the diff between those commits for
drivers/input/mouse/olpc.c. There may be other files that were
changed so a proper git diff might be better to look at if you have a
tree handy.
I have narrowed down the problem as far as I can without compiling my
own kernel (there aren't any master kernels between 20080113.1 and
20080114.2 at http://dev.laptop.org/~dilinger/master/). I currently
don't have the resources to setup my own build environment so if
someone would like to give me an account on a Fedora machine where I
can compile additional kernels for testing it would be much
appreciated. Alternately you could send me kernel/module binaries to
test.
I will take a look at the code and touchpad specs to try to further
narrow down the problem if I get some spare time.
Here are some additional details for Step 2 (touch touchpad): the
vertical position that the cursor jumps to is correlated with the
location on the touchpad that my finger is on. For example, if I
touch the top part of the touchpad, the cursor will jump to the top
part of the screen. So there is some absolute positioning going on.
Additionally, a button press is registered when I touch the touchpad
(even when I don't click the button) and a button release is
registered when I take my finger off the touchpad. So moving my
finger on the touchpad is essentially dragging whatever happens to be
under the cursor. The button press is registered after the cursor
jumps to its new position on the screen following my finger touching
the touchpad.
Denver
--- drivers-input-mouse-olpc.f87.c 2008-05-03 17:30:33.000000000 -0400
+++ drivers-input-mouse-olpc.cb6.c 2008-05-03 17:31:41.000000000 -0400
@@ -45,8 +45,6 @@
module_param(ignore_delta, int, 0644);
MODULE_PARM_DESC(ignore_delta, "ignore packets that cause an X or Y delta larger than this value.");
-static int olpc_absolute_mode(struct psmouse *psmouse, int mode);
-
/*
* With older hardware, a finger-up event is sometimes not sent. If it's been
* more than 50mS since the last packet, we can safely assume that there was
@@ -71,10 +69,7 @@
struct input_dev *gs = priv->gs;
input_report_key(pt, BTN_TOUCH, 0);
- input_report_key(pt, BTN_TOOL_PEN, 0);
input_report_key(gs, BTN_TOUCH, 0);
- input_report_key(gs, BTN_TOOL_FINGER, 0);
-
input_sync(pt);
input_sync(gs);
hgpk_dbg(psmouse, "Missing finger-up packet detected, "
@@ -112,8 +107,7 @@
if (p->gs_down && !test_bit(BTN_TOUCH, p->dev->key)) {
hgpk_dbg(psmouse, "spurious GS finger-down packet\n");
p->gs_down = 0;
- } else if (psmouse->packet[0] == HGPK_PT && p->pt_down &&
- !test_bit(BTN_TOUCH, p->dev->key)) {
+ } else if (p->pt_down && !test_bit(BTN_TOUCH, p->dev->key)) {
hgpk_dbg(psmouse, "spurious PT finger-down packet\n");
p->pt_down = 0;
}
@@ -136,19 +130,17 @@
/* afaik, this happens on all hardware */
/* ensure that we're not a finger-down packet */
- if ((p->pt_down && test_bit(BTN_TOUCH, dev->key)) ||
- (p->gs_down && test_bit(BTN_TOUCH, dev->key))) {
- if (abs(dev->abs[ABS_X] - p->x) > ignore_delta ||
- abs(dev->abs[ABS_Y] - p->y) > ignore_delta) {
- hgpk_dbg(psmouse, "axis change (%d,%d) => (%d,%d) is "
- "over delta threshold\n",
- dev->abs[ABS_X], dev->abs[ABS_Y],
- p->x, p->y);
- input_report_key(dev, BTN_TOUCH, 0);
- input_report_key(dev, BTN_TOOL_PEN, 0);/* XXX: temporary; this will go away */
- input_report_key(dev, BTN_TOOL_FINGER, 0);
- input_sync(dev);
- }
+ if ((p->pt_down && !test_bit(BTN_TOUCH, dev->key)) ||
+ (p->gs_down && !test_bit(BTN_TOUCH, dev->key)))
+ return;
+
+ if (abs(dev->abs[ABS_X] - p->x) > ignore_delta ||
+ abs(dev->abs[ABS_Y] - p->y) > ignore_delta) {
+ hgpk_dbg(psmouse, "axis change (%d,%d) => (%d,%d) is over "
+ "delta threshold\n", dev->abs[ABS_X],
+ dev->abs[ABS_Y], p->x, p->y);
+ input_report_key(dev, BTN_TOUCH, 0);
+ input_sync(dev);
}
}
@@ -202,7 +194,13 @@
p->pt_down = !!(packet[2] & 1);
p->gs_down = !!(packet[2] & 2);
p->dev = ((struct hgpk_data *) psmouse->private)->gs;
- p->mode_switch = p->pt_down ? HGPK_PT : 0;
+ if (p->pt_down) {
+ /* we miss spurious PT finger-downs if pt_down is set */
+ p->mode_switch = HGPK_PT;
+ p->pt_down = 0;
+ } else {
+ p->mode_switch = 0;
+ }
} else if (packet[0] == HGPK_PT) {
p->pt_down = !!(packet[2] & 2);
p->gs_down = 0;
@@ -216,9 +214,9 @@
psmouse->packet[1], psmouse->packet[2],
psmouse->packet[3], psmouse->packet[4],
psmouse->packet[5]);
- hgpk_dbg(psmouse, "l=%d r=%d p=%d g=%d x=%d y=%d z=%d\n",
+ hgpk_dbg(psmouse, "l=%d r=%d p=%d g=%d x=%d y=%d z=%d m=%x\n",
p->left, p->right, p->pt_down, p->gs_down,
- p->x, p->y, p->z);
+ p->x, p->y, p->z, p->mode_switch);
}
}
@@ -238,12 +236,10 @@
input_report_key(pt, BTN_LEFT, pkt.left);
input_report_key(pt, BTN_RIGHT, pkt.right);
input_report_key(pt, BTN_TOUCH, pkt.pt_down);
- input_report_key(pt, BTN_TOOL_PEN, pkt.pt_down);
input_report_key(gs, BTN_LEFT, pkt.left);
input_report_key(gs, BTN_RIGHT, pkt.right);
input_report_key(gs, BTN_TOUCH, pkt.gs_down);
- input_report_key(gs, BTN_TOOL_FINGER, pkt.gs_down);
input_report_abs(pkt.dev, ABS_X, pkt.x);
input_report_abs(pkt.dev, ABS_Y, pkt.y);
@@ -312,56 +308,43 @@
/*
* Touchpad should be disabled before calling this!
*/
-static int olpc_new_mode(struct psmouse *psmouse, int mode)
+static int hgpk_new_mode(struct psmouse *psmouse, int mode)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
struct hgpk_data *priv = psmouse->private;
- unsigned char param;
- int ret;
- if (tpdebug)
- hgpk_warn(psmouse, "Switching to %d. [%lu]\n", mode, jiffies);
+ /*
+ * PT mode: F2, F2, F2, E7
+ * GS mode: F2, F2, F2, E6
+ */
+ if (ps2_command(ps2dev, NULL, 0xF2) ||
+ ps2_command(ps2dev, NULL, 0xF2) ||
+ ps2_command(ps2dev, NULL, 0xF2))
+ return -EIO;
- if ((ret = ps2_command(ps2dev, ¶m, 0x01F2)))
- goto failed;
- if ((ret = ps2_command(ps2dev, ¶m, 0x01F2)))
- goto failed;
- if ((ret = ps2_command(ps2dev, ¶m, 0x01F2)))
- goto failed;
-
- switch (mode) {
- default:
- hgpk_warn(psmouse, "Invalid mode %d. Defaulting to GS.\n", mode);
- case HGPK_GS:
- ret = ps2_command(ps2dev, NULL, 0xE6);
- break;
- case HGPK_PT:
- ret = ps2_command(ps2dev, NULL, 0xE7);
- break;
- }
- if (ret)
- goto failed;
-
- /* XXX: This is a bit hacky, make sure this isn't screwing stuff up. */
- psmouse->pktcnt = psmouse->out_of_sync = 0;
- psmouse->last = jiffies;
- psmouse->state = PSMOUSE_ACTIVATED;
+ if (mode == HGPK_GS) {
+ if (ps2_command(ps2dev, NULL, 0xE6))
+ return -EIO;
+ } else {
+ if (ps2_command(ps2dev, NULL, 0xE7))
+ return -EIO;
+ }
+
+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
+ return -EIO;
- if ((ret = ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)))
- goto failed;
+ /* tell the irq handler to stop ignoring packets */
+ psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
priv->current_mode = mode;
priv->pending_mode = 0;
if (tpdebug)
- hgpk_warn(psmouse, "Switched to mode %d successful.\n", mode);
+ hgpk_warn(psmouse, "Switched to mode 0x%x successful.\n", mode);
-failed:
- if (ret)
- hgpk_warn(psmouse, "Mode switch to %d failed! (%d) [%lu]\n", mode, ret, jiffies);
- return ret;
+ return 0;
}
-static int olpc_absolute_mode(struct psmouse *psmouse, int mode)
+static int hgpk_advanced_mode(struct psmouse *psmouse)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
@@ -372,7 +355,7 @@
ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
return -1;
- return olpc_new_mode(psmouse, mode);
+ return hgpk_new_mode(psmouse, HGPK_GS);
}
/*
@@ -393,8 +376,8 @@
psmouse_reset(psmouse);
- if (olpc_absolute_mode(psmouse, HGPK_GS)) {
- hgpk_err(psmouse, "Failed to reenable absolute mode.\n");
+ if (hgpk_advanced_mode(psmouse)) {
+ hgpk_err(psmouse, "failed to reenable advanced mode.\n");
return -1;
}
@@ -416,27 +399,24 @@
struct hgpk_data *priv = container_of(work, struct hgpk_data, mode_switch);
struct psmouse *psmouse = priv->psmouse;
struct ps2dev *ps2dev = &psmouse->ps2dev;
- int pending_mode, ret;
+ int pending_mode;
+
+ if (tpdebug)
+ hgpk_dbg(psmouse, "Starting mode switch to 0x%x. [%lu]\n",
+ priv->pending_mode, jiffies);
if (priv->pending_mode == priv->current_mode) {
priv->pending_mode = 0;
- hgpk_dbg(psmouse, "In switch_mode, no target mode.\n");
+ hgpk_dbg(psmouse, "Already in target mode, no-op.\n");
return;
}
- if (tpdebug)
- hgpk_dbg(psmouse, "Disable for switch to %d. [%lu]\n", priv->pending_mode, jiffies);
-
- /* XXX: This is a bit hacky, make sure this isn't screwing stuff up. */
- psmouse->state = PSMOUSE_INITIALIZING;
+ /* tell the irq handler to ignore any further packets */
+ psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
priv->late = 0;
- ret = ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE);
- if (ret) {
- /* XXX: if this ever fails, we need to do a full reset! */
- hgpk_warn(psmouse, "Disable failed for switch to %d. (%d) [%lu]\n", priv->pending_mode, ret, jiffies);
- return;
- }
+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
+ goto bad;
/*
* ALPS tells us that it may take up to 20msec for the disable to
@@ -446,7 +426,7 @@
*/
pending_mode = priv->pending_mode;
- if (olpc_new_mode(psmouse, priv->pending_mode))
+ if (hgpk_new_mode(psmouse, priv->pending_mode))
goto bad;
/*
@@ -454,16 +434,16 @@
*
* If there is a brief tap of a stylus or a fingernail that
* triggers a mode switch to PT mode, and the stylus/fingernail is
- * lifted after the DISABLE above, but before we reenable in the new mode,
- * then we can get stuck in PT mode.
+ * lifted after the DISABLE above, but before we reenable in the
+ * new mode then we can get stuck in PT mode.
*/
if (pending_mode == HGPK_PT) {
priv->pending_mode = HGPK_GS;
- queue_delayed_work(kpsmoused_wq, &priv->mode_switch, msecs_to_jiffies(50));
+ queue_delayed_work(kpsmoused_wq, &priv->mode_switch,
+ msecs_to_jiffies(50));
}
return;
-
bad:
hgpk_warn(psmouse, "Failure to switch modes, resetting device...\n");
hgpk_reconnect(psmouse);
@@ -486,26 +466,27 @@
psmouse_reset(psmouse);
- if (olpc_absolute_mode(psmouse, HGPK_GS)) {
- hgpk_err(psmouse, "Failed to enable absolute mode\n");
+ if (hgpk_advanced_mode(psmouse)) {
+ hgpk_err(psmouse, "failed to enable advanced mode\n");
goto init_fail;
}
- /*
- * Unset some of the default bits for things we don't have.
- */
- pt->evbit[LONG(EV_REL)] &= ~BIT(EV_REL);
- pt->relbit[LONG(REL_X)] &= ~(BIT(REL_X) | BIT(REL_Y));
- pt->keybit[LONG(BTN_MIDDLE)] &= ~BIT(BTN_MIDDLE);
-
- pt->evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
- pt->keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
- pt->keybit[LONG(BTN_TOOL_PEN)] |= BIT(BTN_TOOL_PEN);
- pt->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+ /* Unset things that psmouse-base sets that we don't have */
+ pt->evbit[0] &= ~BIT(EV_REL);
+ pt->keybit[LONG(BTN_MOUSE)] &= ~BIT(BTN_MIDDLE);
+ pt->relbit[0] &= ~(BIT(REL_X) | BIT(REL_Y));
+
+ /* Set all the things we *do* have */
+ set_bit(EV_KEY, pt->evbit);
+ set_bit(EV_ABS, pt->evbit);
+
+ set_bit(BTN_LEFT, pt->keybit);
+ set_bit(BTN_RIGHT, pt->keybit);
+ set_bit(BTN_TOUCH, pt->keybit);
- pt->evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
input_set_abs_params(pt, ABS_X, 2, 1000, 0, 0);
input_set_abs_params(pt, ABS_Y, 0, 717, 0, 0);
+ input_set_abs_params(pt, ABS_PRESSURE, 0, 127, 0, 0);
snprintf(priv->phys, sizeof(priv->phys),
"%s/input1", psmouse->ps2dev.serio->phys);
@@ -516,18 +497,16 @@
gs->id.product = PSMOUSE_OLPC;
gs->id.version = psmouse->model;
- gs->evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
- gs->keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
- gs->keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
- gs->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT);
-
- /* bernie: argh -- needed for hal to see it as a mouse */
- gs->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
- gs->evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
+ set_bit(EV_KEY, gs->evbit);
+ set_bit(EV_ABS, gs->evbit);
+
+ set_bit(BTN_LEFT, gs->keybit);
+ set_bit(BTN_RIGHT, gs->keybit);
+ set_bit(BTN_TOUCH, gs->keybit);
+
input_set_abs_params(gs, ABS_X, 350, 512, 0, 0);
input_set_abs_params(gs, ABS_Y, 70, 325, 0, 0);
- /* bernie: argh -- needed for hal to see it as a mouse */
- /* input_set_abs_params(gs, ABS_PRESSURE, 0, 63, 0, 0); */
+ input_set_abs_params(gs, ABS_PRESSURE, 0, 15, 0, 0);
if (input_register_device(gs)) {
hgpk_err(psmouse, "Failed to register GlideSensor\n");
_______________________________________________
Devel mailing list
[email protected]
http://lists.laptop.org/listinfo/devel