Updates from Zephaniah

Andres Salomon dilinger at debian.unroutableorg
Wed Jan 3 03:36:24 EST 2007


Commit:     4ad40f5258f1bdf3250a191f08811a10e15c4f64
Parent:     91a1b86bf57adeb44b0c9415da8983a74d2b5b60
commit 4ad40f5258f1bdf3250a191f08811a10e15c4f64
Author:     Andres Salomon <dilinger at debian.org>
AuthorDate: Mon Dec 18 16:10:07 2006 -0500
Commit:     Andres Salomon <dilinger at debian.org>
CommitDate: Mon Dec 18 16:10:07 2006 -0500

    Updates from Zephaniah
    
    New driver from zephaniah, as of 12/17.
---
 drivers/input/mouse/olpc.c |  437 ++++++++++++++++++++++++--------------------
 drivers/input/mouse/olpc.h |    7 +
 2 files changed, 245 insertions(+), 199 deletions(-)

diff --git a/drivers/input/mouse/olpc.c b/drivers/input/mouse/olpc.c
index 087dc64..9282470 100644
--- a/drivers/input/mouse/olpc.c
+++ b/drivers/input/mouse/olpc.c
@@ -42,83 +42,19 @@ module_param(tpmode, int, 0644);
 static int tpdebug;
 module_param(tpdebug, int, 0644);
 
-static const struct olpc_model_info olpc_model_data[] = {
-	{ { 0x67, 0x00, 0x0a }, 0 }, /* v1 in PT+GS mode. */
-	{ { 0x67, 0x00, 0x14 }, 0 }, /* v2 in PT+GS mode. */
-	{ { 0x67, 0x00, 0x28 }, 1 }, /* v3, single-mode. */
+#define OLPC_GS		1	/* The GS sensor. */
+#define OLPC_PT		2	/* The PT sensor. */
+
+static struct olpc_model_info olpc_model_data[] = {
+	{ { 0x67, 0x00, 0x0a }, OLPC_GS | OLPC_PT }, /* 1st gen. */
+	{ { 0x67, 0x00, 0x14 }, OLPC_GS }, /* 2nd gen. */
+	{ { 0x67, 0x00, 0x28 }, OLPC_GS | OLPC_PT }, /* 3nd gen. */
 };
 
-#define OLPC_PKT_SIM	0xeb
 #define OLPC_PKT_PT	0xcf
 #define OLPC_PKT_GS	0xff
 
-/*
- * OLPC absolute Mode - simultaneous format
- *
- * byte 0:  1    1    1    0    1    0     1     1
- * byte 1:  0  gx6  gx5  gx4  gx3  gx2   gx1   gx0
- * byte 2:  0  gx10 gx9  gx8  gx7  px9   px8   px7
- * byte 3:  0  gy9  gy8  gy7    1    ? pt-dsw gs-dsw
- * byte 4:  0  gy6  gy5  gy4  gy3  gy2   gy1   gy0
- * byte 5:  0  gz6  gz5  gz4  gz3  gz2   gz1   gz0
- * byte 6:  0  py9  py8  py7    1    ?   swr   swl
- * byte 7:  0  py6  py5  py4  py3  py2   py1   py0
- * byte 8:  0  px6  px5  px4  px3  px2   px1   px0
- *
- * ?'s are not defined in the protocol spec, may vary between models.
- *
- * gx/gy/gz is for the GlideSensor.
- * px/py is for the PenTablet sensor.
- *
- * swr/swl are the left/right buttons.
- *
- * pt-dsw/gs-dsw indicate that the pt/gs sensor is detecting a
- * pen/finger and is thus sending data this packet.
- */
-
-static void olpc_process_packet(struct psmouse *psmouse)
-{
-	struct olpc_data *priv = psmouse->private;
-	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = psmouse->dev;
-	struct input_dev *dev2 = priv->dev2;
-	int px, py, gx, gy, gz, gs_down, pt_down, left, right;
-
-	left = packet[6] & 1;
-	right = packet[6] & 2;
-	gx = packet[1] | ((packet[2] & 0x78) << (7 - 3));
-	gy = packet[4] | ((packet[3] & 0x70) << (7 - 4));
-	gz = packet[5];
-	px = packet[8] | ((packet[2] & 0x7) << 7);
-	py = packet[7] | ((packet[6] & 0x70) << (7 - 4));
-
-	pt_down = packet[3] & 1;
-	gs_down = packet[3] & 2;
-
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev2, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
-	input_report_key(dev2, BTN_RIGHT, right);
-
-	input_report_key(dev, BTN_TOUCH, pt_down);
-	input_report_key(dev, BTN_TOOL_PEN, pt_down);
-	input_report_key(dev2, BTN_TOUCH, gs_down);
-	input_report_key(dev2, BTN_TOOL_FINGER, gs_down);
-
-	if (gs_down) {
-		input_report_abs(dev2, ABS_X, gx);
-		input_report_abs(dev2, ABS_Y, gy);
-	}
-	input_report_abs(dev2, ABS_PRESSURE, gz);
-
-	if (pt_down) {
-		input_report_abs(dev, ABS_X, px);
-		input_report_abs(dev, ABS_Y, py);
-	}
-
-	input_sync(dev);
-	input_sync(dev2);
-}
+static int olpc_absolute_mode(struct psmouse *psmouse, int mode);
 
 /*
  * OLPC absolute Mode - single-mode format
@@ -139,13 +75,13 @@ static void olpc_process_packet(struct p
  * pen/finger
  */
 
-static void olpc_process_pt_packet(struct psmouse *psmouse)
+static void olpc_process_packet_gspt(struct psmouse *psmouse)
 {
 	struct olpc_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
 	struct input_dev *dev = psmouse->dev;
 	struct input_dev *dev2 = priv->dev2;
-	int x, y, z, gs_down, pt_down, left, right;
+	int x, y, z, gs_down = 0, pt_down = 0, left, right;
 
 	left = packet[3] & 1;
 	right = packet[3] & 2;
@@ -153,8 +89,13 @@ static void olpc_process_pt_packet(struc
 	y = packet[4] | ((packet[3] & 0x70) << (7 - 4));
 	z = packet[5];
 
-	pt_down = packet[2] & 2;
-	gs_down = packet[2] & 1;
+	if (psmouse->packet[0] == OLPC_PKT_GS) {
+		pt_down = !!(packet[2] & 1);
+		gs_down = !!(packet[2] & 2);
+	} else if (psmouse->packet[0] == OLPC_PKT_PT) {
+		gs_down = !!(packet[2] & 1);
+		pt_down = !!(packet[2] & 2);
+	}
 
 	if (tpdebug) {
 		printk(KERN_DEBUG "%s %02x %02x %02x %02x %02x %02x\n",
@@ -165,10 +106,15 @@ static void olpc_process_pt_packet(struc
 		       left, right, pt_down, gs_down, x, y, z);
 	}
 
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev2, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
-	input_report_key(dev2, BTN_RIGHT, right);
+	if (psmouse->packet[0] == OLPC_PKT_PT) {
+		input_report_key(dev, BTN_LEFT, left);
+		input_report_key(dev, BTN_RIGHT, right);
+	} else if (psmouse->packet[0] == OLPC_PKT_GS) {
+		input_report_key(dev, BTN_LEFT, left);
+		input_report_key(dev, BTN_RIGHT, right);
+		input_report_key(dev2, BTN_LEFT, left);
+		input_report_key(dev2, BTN_RIGHT, right);
+	}
 
 	input_report_key(dev, BTN_TOUCH, pt_down);
 	input_report_key(dev, BTN_TOOL_PEN, pt_down);
@@ -177,68 +123,46 @@ static void olpc_process_pt_packet(struc
 
 	input_report_abs(dev2, ABS_PRESSURE, z);
 
-	if (pt_down) {
+	if (psmouse->packet[0] == OLPC_PKT_PT && pt_down) {
 		input_report_abs(dev, ABS_X, x);
 		input_report_abs(dev, ABS_Y, y);
+	} else if (psmouse->packet[0] == OLPC_PKT_GS && gs_down) {
+		input_report_abs(dev2, ABS_X, x);
+		input_report_abs(dev2, ABS_Y, y);
 	}
 
 	input_sync(dev);
 	input_sync(dev2);
-}
-
-static void olpc_process_gs_packet(struct psmouse *psmouse)
-{
-	struct olpc_data *priv = psmouse->private;
-	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = psmouse->dev;
-	struct input_dev *dev2 = priv->dev2;
-	int x, y, z, gs_down, pt_down, left, right;
-
-	left = packet[3] & 1;
-	right = packet[3] & 2;
-	x = packet[1] | ((packet[2] & 0x78) << (7 - 3));
-	y = packet[4] | ((packet[3] & 0x70) << (7 - 4));
-	z = packet[5];
 
-	gs_down = packet[2] & 2;
-	pt_down = packet[2] & 1;
+	if (!priv->pending_mode)
+		goto switch_mode;
 
-	if (tpdebug) {
-		printk(KERN_DEBUG "%s %02x %02x %02x %02x %02x %02x\n",
-		       __func__, psmouse->packet[0], psmouse->packet[1],
-		       psmouse->packet[2], psmouse->packet[3], psmouse->packet[4],
-		       psmouse->packet[5]);
-		printk(KERN_DEBUG "l=%d r=%d p=%d g=%d x=%d y=%d z=%d\n",
-		       left, right, pt_down, gs_down, x, y, z);
+	if (priv->pending_mode == OLPC_GS && pt_down) {
+		priv->pending_mode = 0;
+		cancel_delayed_work(&priv->modeswitch_work_0);
 	}
 
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev2, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
-	input_report_key(dev2, BTN_RIGHT, right);
-
-	input_report_key(dev, BTN_TOUCH, pt_down);
-	input_report_key(dev, BTN_TOOL_PEN, pt_down);
-	input_report_key(dev2, BTN_TOUCH, gs_down);
-	input_report_key(dev2, BTN_TOOL_FINGER, gs_down);
-
-	input_report_abs(dev2, ABS_PRESSURE, z);
-
-	if (gs_down) {
-		input_report_abs(dev2, ABS_X, x);
-		input_report_abs(dev2, ABS_Y, y);
+	return;
+
+switch_mode:
+	if (priv->i->flags & OLPC_PT && priv->i->flags & OLPC_GS) {
+		if (psmouse->packet[0] == OLPC_PKT_PT && !pt_down) {
+			printk(KERN_WARNING "Scheduling switch to GS.\n");
+			priv->pending_mode = OLPC_GS;
+			queue_work(kpsmoused_wq, &priv->modeswitch_work_0);
+		} else if (psmouse->packet[0] == OLPC_PKT_GS && pt_down) {
+			printk(KERN_WARNING "Scheduling switch to PT.\n");
+			priv->pending_mode = OLPC_PT;
+			queue_work(kpsmoused_wq, &priv->modeswitch_work_0);
+		}
 	}
-
-	input_sync(dev);
-	input_sync(dev2);
 }
 
 static psmouse_ret_t olpc_process_byte(struct psmouse *psmouse)
 {
 	psmouse_ret_t ret = PSMOUSE_BAD_DATA;
 
-	if (psmouse->packet[0] != OLPC_PKT_SIM &&
-	    psmouse->packet[0] != OLPC_PKT_PT &&
+	if (psmouse->packet[0] != OLPC_PKT_PT &&
 	    psmouse->packet[0] != OLPC_PKT_GS)
 		goto out;
 
@@ -247,55 +171,24 @@ static psmouse_ret_t olpc_process_byte(s
 			(psmouse->packet[psmouse->pktcnt - 1] & 0x80))
 		goto out;
 
-	/*
-	 * For simultaneous mode, bytes 4 and 7 should have 1 in the 4th bit,
-	 * and the high bit unset.
-	 */
-	if (psmouse->packet[0] == OLPC_PKT_SIM &&
-	    (psmouse->pktcnt == 4 || psmouse->pktcnt == 7) &&
-	    ((psmouse->packet[psmouse->pktcnt - 1] & 0x88) != 8))
-		goto out;
-
-	/*
-	 * For single mode, byte 4 should have bit 3 set and bit 2 clear
-	 */
-	if (psmouse->packet[0] != OLPC_PKT_SIM &&
-	    psmouse->pktcnt == 4 &&
-	    ((psmouse->packet[psmouse->pktcnt - 1] & 0xc) != 0x8))
-		goto out;
-
-	if (psmouse->packet[0] == OLPC_PKT_PT &&
-	    psmouse->pktcnt == 6) {
-		olpc_process_pt_packet(psmouse);
-		ret = PSMOUSE_FULL_PACKET;
-		goto out;
-	} else if (psmouse->packet[0] == OLPC_PKT_GS &&
-		   psmouse->pktcnt == 6) {
-		olpc_process_gs_packet(psmouse);
-		ret = PSMOUSE_FULL_PACKET;
-		goto out;
-	} else if (psmouse->pktcnt == 9) {
-		olpc_process_packet(psmouse);
-
+	if (psmouse->pktcnt == 6) {
+		olpc_process_packet_gspt(psmouse);
 		ret = PSMOUSE_FULL_PACKET;
 		goto out;
 	}
 
 	ret = PSMOUSE_GOOD_DATA;
 out:
-	if (ret != PSMOUSE_GOOD_DATA)
-		dev_dbg(psmouse->dev->cdev.dev, "olpc.c(%d): ret: %d, len: %u,"
-			"data: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x",
-			__LINE__, ret, psmouse->pktcnt,
-			psmouse->packet[0], psmouse->packet[1],
-			psmouse->packet[2], psmouse->packet[3],
-			psmouse->packet[4], psmouse->packet[5],
-			psmouse->packet[6], psmouse->packet[7],
-			psmouse->packet[8]);
+	if (ret != PSMOUSE_GOOD_DATA && ret != PSMOUSE_FULL_PACKET)
+		printk(KERN_DEBUG "%s: (%d) %02x %02x %02x %02x %02x %02x\n",
+		       __func__, psmouse->pktcnt, psmouse->packet[0],
+			   psmouse->packet[1], psmouse->packet[2],
+			   psmouse->packet[3], psmouse->packet[4],
+		       psmouse->packet[5]);
 	return ret;
 }
 
-static const struct olpc_model_info *olpc_get_model(struct psmouse *psmouse)
+static struct olpc_model_info *olpc_get_model(struct psmouse *psmouse)
 {
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
 	unsigned char param[4];
@@ -325,42 +218,63 @@ static const struct olpc_model_info *olp
 	return NULL;
 }
 
-static int olpc_absolute_mode(struct psmouse *psmouse)
+static int olpc_find_mode (struct psmouse *psmouse)
+{
+	struct olpc_data *priv = psmouse->private;
+	int mode;
+
+	if (tpmode < -1 || tpmode > 4)
+		return -1;
+
+	if (tpmode)
+		priv->i->flags = tpmode;
+
+	mode = priv->i->flags;
+
+	if (mode & OLPC_GS) {
+		priv->initial = OLPC_GS;
+	} else if (mode & OLPC_PT) {
+		priv->initial = OLPC_PT;
+	} else
+		return -1;
+
+	return priv->initial;
+}
+
+static int olpc_absolute_mode(struct psmouse *psmouse, int mode)
 {
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
 	unsigned char param;
 
 	/* Switch to 'Advanced mode.', four disables in a row. */
 	if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
-	    ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
-	    ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
-	    ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
+			ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
+			ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
+			ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
 		return -1;
 
-	/*
-	 * Switch to simultaneous mode, F2 (GETID) three times with no
-	 * arguments or reply, followed by SETRES with an argument of 2.
-	 */
-	ps2_command(ps2dev, NULL, 0xF2);
-	ps2_command(ps2dev, NULL, 0xF2);
-	ps2_command(ps2dev, NULL, 0xF2);
-	switch(tpmode) {
+	if (ps2_command(ps2dev, &param, 0x01F2))
+		return -3;
+	if (ps2_command(ps2dev, &param, 0x01F2))
+		return -4;
+	if (ps2_command(ps2dev, &param, 0x01F2))
+		return -5;
+
+	switch(mode) {
 	default:
-		printk(KERN_WARNING "Invalid tpmode %d. Default to simultaneous mode\n", tpmode);
-	case 0: /* Dual mode */
-		param = 0x02;
-		ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
-		ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+		printk(KERN_WARNING __FILE__ ": Invalid tpmode %d. Default to GS mode\n", tpmode);
+	case OLPC_GS: /* GS only */
+		if (ps2_command(ps2dev, NULL, 0xE6))
+			return -8;
 		break;
-	case 1: /* GS only */
-		ps2_command(ps2dev, NULL, 0xe6);
-		break;
-	case 2: /* PT only */
-		ps2_command(ps2dev, NULL, 0xe7);
+	case OLPC_PT: /* PT only */
+		if (ps2_command(ps2dev, NULL, 0xE7))
+			return -9;
 		break;
 	}
-	param = 100;
-	ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
+
+	if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
+		return -10;
 
 	return 0;
 }
@@ -384,8 +298,11 @@ static int olpc_reconnect(struct psmouse
 	if (!(priv->i = olpc_get_model(psmouse)))
 		return -1;
 
-	if (olpc_absolute_mode(psmouse)) {
-		printk(KERN_ERR "olpc.c: Failed to reenable absolute mode.\n");
+	if (olpc_find_mode (psmouse) < 0)
+		return -1;
+
+	if (olpc_absolute_mode(psmouse, priv->initial)) {
+		printk(KERN_ERR __FILE__ ": Failed to reenable absolute mode.\n");
 		return -1;
 	}
 
@@ -401,6 +318,122 @@ static void olpc_disconnect(struct psmou
 	kfree(priv);
 }
 
+static void olpc_switch_mode_0 (void *p)
+{
+	struct psmouse *psmouse = p;
+	struct olpc_data *priv = psmouse->private;
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	int pending_mode, ret, count;
+	unsigned char param[3];
+
+	pending_mode = priv->pending_mode;
+	if (!pending_mode) {
+		printk (KERN_WARNING __FILE__ ": In switch_mode, no target mode.\n");
+		return;
+	}
+	if (pending_mode == priv->current_mode && 0) {
+		printk (KERN_WARNING __FILE__ ": In switch_mode, pending == current.\n");
+		return;
+	}
+
+	if (tpdebug)
+		printk(KERN_WARNING __FILE__ ": Disable for switch to %d. [%lu]\n", pending_mode, jiffies);
+
+	/* XXX: This is a bit hacky, make sure this isn't screwing stuff up. */
+	psmouse->state = PSMOUSE_INITIALIZING;
+
+	ret = ps2_command(ps2dev, NULL, 0xF5);
+	if (ret) {
+		/* Wait 100ms, then continue. */
+		queue_delayed_work(kpsmoused_wq, &priv->modeswitch_work_1, msecs_to_jiffies(100));
+			return;
+		}
+		printk(KERN_WARNING __FILE__ ": Disable failed for switch to %d. (%d) [%lu]\n", pending_mode, ret, jiffies);
+	}
+}
+
+static void olpc_switch_mode_1 (void *p)
+{
+	struct psmouse *psmouse = p;
+	struct olpc_data *priv = psmouse->private;
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	unsigned char param[3];
+	int ret = 0, pending_mode, count;
+
+	pending_mode = priv->pending_mode;
+	if (!pending_mode) {
+		printk (KERN_WARNING __FILE__ ": In switch_mode, no target mode.\n");
+		return;
+	}
+	if (pending_mode == priv->current_mode && 0) {
+		printk (KERN_WARNING __FILE__ ": In switch_mode, pending == current.\n");
+		return;
+	}
+
+	if (tpdebug)
+		printk(KERN_WARNING __FILE__ ": Switching to %d. [%lu]\n", pending_mode, jiffies);
+
+	if (ps2_command(ps2dev, param, 0x01F2)) {
+		ret = 3;
+		goto bad;
+	}
+	if (ps2_command(ps2dev, param, 0x01F2)) {
+		ret = 4;
+		goto bad;
+	}
+	if (ps2_command(ps2dev, param, 0x01F2)) {
+		ret = 5;
+		goto bad;
+	}
+
+	switch(pending_mode) {
+	default:
+		printk(KERN_WARNING __FILE__ ": Invalid tpmode %d. Default to simultaneous mode\n", tpmode);
+	case OLPC_GS: /* GS only */
+		if (ps2_command(ps2dev, NULL, 0xE6)) {
+			ret = -20;
+			goto bad;
+		}
+		break;
+	case OLPC_PT: /* PT only */
+		if (ps2_command(ps2dev, NULL, 0xE7)) {
+			ret = -30;
+			goto bad;
+		}
+		break;
+	}
+
+	count = 0;
+	while (count++ < 5) {
+		/* 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;
+
+		ret = ps2_sendbyte(ps2dev, 0xF4, 500);
+		if (!ret) {
+			break;
+		} else if (tpdebug) {
+			printk(KERN_WARNING __FILE__ ": Enable failed for switch to %d. (%d) [%lu]\n", pending_mode, ret, jiffies);
+		}
+		ps2_command(ps2dev, param, 0x03E9);
+	}
+
+	if (tpdebug)
+		printk(KERN_WARNING __FILE__ ": Switched to %d: %d.\n", pending_mode, ret);
+
+	if (!ret)
+		priv->current_mode = pending_mode;
+	priv->pending_mode = 0;
+
+	return;
+
+bad:
+	printk(KERN_WARNING __FILE__ ": Failure in switching to %d. (%d)  Retrying..\n", pending_mode, ret);
+	/* Delay, restart. */
+	queue_delayed_work(kpsmoused_wq, &priv->modeswitch_work_1, HZ/10);
+}
+
 int olpc_init(struct psmouse *psmouse)
 {
 	struct olpc_data *priv;
@@ -418,12 +451,13 @@ int olpc_init(struct psmouse *psmouse)
 	if (!(priv->i = olpc_get_model(psmouse)))
 		goto init_fail;
 
-	if (!tpmode && (priv->i->flags & 1)) {
-		/* Can't do dual-mode on newest device; use GS mode to start */
-		tpmode = 1;
+	if (olpc_find_mode (psmouse) < 0) {
+		printk(KERN_ERR __FILE__ ": Failed to identify proper mode\n");
+		goto init_fail;
 	}
-	if (olpc_absolute_mode(psmouse)) {
-		printk(KERN_ERR "olpc.c: Failed to enable absolute mode\n");
+
+	if (olpc_absolute_mode(psmouse, priv->initial)) {
+		printk(KERN_ERR __FILE__ ": Failed to enable absolute mode\n");
 		goto init_fail;
 	}
 
@@ -462,17 +496,24 @@ int olpc_init(struct psmouse *psmouse)
 	input_set_abs_params(dev2, ABS_Y, 70, 325, 0, 0);
 	input_set_abs_params(dev2, ABS_PRESSURE, 0, 63, 0, 0);
 
-	if (input_register_device(dev2))
+	if (input_register_device(dev2)) {
+		printk(KERN_ERR __FILE__ ": Failed to register GlideSensor\n");
 		goto init_fail;
+	}
 
 	psmouse->protocol_handler = olpc_process_byte;
 	psmouse->poll = olpc_poll;
 	psmouse->disconnect = olpc_disconnect;
 	psmouse->reconnect = olpc_reconnect;
-	psmouse->pktsize = 9;
+	psmouse->pktsize = 6;
 
 	/* Disable the idle resync. */
 	psmouse->resync_time = 0;
+	/* Reset after a lot of bad bytes. */
+	psmouse->resetafter = 1024;
+
+	INIT_WORK(&priv->modeswitch_work_0, olpc_switch_mode_0, psmouse);
+	INIT_WORK(&priv->modeswitch_work_1, olpc_switch_mode_1, psmouse);
 
 	return 0;
 
diff --git a/drivers/input/mouse/olpc.h b/drivers/input/mouse/olpc.h
index 4e7c76a..3b147e8 100644
--- a/drivers/input/mouse/olpc.h
+++ b/drivers/input/mouse/olpc.h
@@ -27,7 +27,12 @@ struct olpc_data {
 	struct input_dev *dev2;		/* Relative device */
 	char name[32];			/* Name */
 	char phys[32];			/* Phys */
-	const struct olpc_model_info *i;/* Info */
+	struct olpc_model_info *i; /* Info */
+	int initial;
+	int pending_mode;
+	int current_mode;
+	struct work_struct modeswitch_work_0;
+	struct work_struct modeswitch_work_1;
 };
 
 


More information about the Commits-kernel mailing list