Module Name:    src
Committed By:   phx
Date:           Mon Dec 20 19:18:24 UTC 2010

Modified Files:
        src/sys/arch/macppc/dev: pbms.c

Log Message:
The driver didn't work, because it expects the whole data packet in a
single interrupt. Reality shows that with current kernels a 81 bytes packet
is split into 3 interrupts with 32 + 32 + 17 bytes. I have added a workaround
to deal with it. The Geyser2 devices with 64 byte packets are unsupported
at the moment. Somebody needs to test it.

New: Added support for the iBook 12-inch trackpad.


To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/sys/arch/macppc/dev/pbms.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/macppc/dev/pbms.c
diff -u src/sys/arch/macppc/dev/pbms.c:1.11 src/sys/arch/macppc/dev/pbms.c:1.12
--- src/sys/arch/macppc/dev/pbms.c:1.11	Fri Nov 19 18:27:12 2010
+++ src/sys/arch/macppc/dev/pbms.c	Mon Dec 20 19:18:24 2010
@@ -1,4 +1,4 @@
-/* $Id: pbms.c,v 1.11 2010/11/19 18:27:12 phx Exp $ */
+/* $Id: pbms.c,v 1.12 2010/12/20 19:18:24 phx Exp $ */
 
 /*
  * Copyright (c) 2005, Johan Wallén
@@ -67,10 +67,11 @@
  *   2, 7, 12, 17, 22, 27, 32, 37, 4, 9, 14, 19, 24, 29, 34, 39, 42,
  *   47, 52, 57, 62, 67, 72, 77, 44 and 49;
  * 
- * in the Y direction, the sensors correspond to byte positions
+ * In the Y direction, the sensors correspond to byte positions
  *
  *   1, 6, 11, 16, 21, 26, 31, 36, 3, 8, 13, 18, 23, 28, 33 and 38.
  *
+ * On 12 inch iBooks only the 9 first sensors in Y-direction are used.
  * The change in the sensor values over time is more interesting than
  * their absolute values: if the pressure increases, we know that the
  * finger has just moved there.
@@ -128,6 +129,7 @@
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdevs.h>
 #include <dev/usb/uhidev.h>
+#include <dev/usb/hid.h>
 
 #include <dev/wscons/wsconsio.h>
 #include <dev/wscons/wsmousevar.h>
@@ -206,8 +208,9 @@
 		.y_factor = (y_fact),					      \
 		.y_sensors = 16						      \
        }
-       /* 12 inch PowerBooks */
+       /* 12 inch PowerBooks/iBooks */
        POWERBOOK_TOUCHPAD(12, 0x030a, 69, 16, 52), /* XXX Not tested. */
+       POWERBOOK_TOUCHPAD(12, 0x030b, 73, 15, 96),
        /* 15 inch PowerBooks */
        POWERBOOK_TOUCHPAD(15, 0x020e, 85, 16, 57), /* XXX Not tested. */
        POWERBOOK_TOUCHPAD(15, 0x020f, 85, 16, 57),
@@ -230,10 +233,12 @@
 struct pbms_softc {
 	struct uhidev sc_hdev;	      /* USB parent (got the struct device). */
 	int is_geyser2;
-	int sc_datalen;
+	int sc_datalen;		      /* Size of a data packet */
+	int sc_bufusage;	      /* Number of bytes in sc_databuf */
 	int sc_acc[PBMS_SENSORS];     /* Accumulated sensor values. */
 	unsigned char sc_prev[PBMS_SENSORS];   /* Previous sample. */
 	unsigned char sc_sample[PBMS_SENSORS]; /* Current sample. */
+	uint8_t sc_databuf[PBMS_DATA_LEN];     /* Buffer for a data packet */
 	device_t sc_wsmousedev; /* WSMouse device. */
 	int sc_noise;		      /* Amount of noise. */
 	int sc_theshold;	      /* Threshold value. */
@@ -354,6 +359,8 @@
 					sc->sc_datalen = 64;
 					sc->sc_y_sensors = 9;
 				}
+				else if (product == 0x030b)
+					sc->sc_y_sensors = 9;
 				break;
 			}
 		}
@@ -421,6 +428,7 @@
 
 	sc->sc_status |= PBMS_ENABLED;
 	sc->sc_status &= ~PBMS_VALID;
+	sc->sc_bufusage = 0;
 	sc->sc_buttons = 0;
 	memset(sc->sc_sample, 0, sizeof(sc->sc_sample));
 
@@ -463,20 +471,39 @@
 pbms_intr(struct uhidev *addr, void *ibuf, unsigned int len)
 {
 	struct pbms_softc *sc = (struct pbms_softc *)addr;
-	unsigned char *data;
+	uint8_t *data;
 	int dx, dy, dz, i, s;
 	uint32_t buttons;
 
-	/* Ignore incomplete data packets. */
-	if (len != sc->sc_datalen)
-		return;
-	data = ibuf;
+	/*
+	 * We may have to construct the full data packet over two or three
+	 * sequential interrupts, as the device only sends us chunks of
+	 * 32 or 64 bytes of data.
+	 * This also requires some synchronization, to make sure we place
+	 * the first protocol-byte at the first byte in the bufffer.
+	 */
+	if (sc->is_geyser2) {
+		/* XXX Need to check this. */
+	} else {
+		/* the last chunk is always 17 bytes */
+		if (len == 17 && sc->sc_bufusage + len != sc->sc_datalen) {
+			sc->sc_bufusage = 0;	/* discard bad packet */
+			return;
+		}
+	}
 
+	memcpy(sc->sc_databuf + sc->sc_bufusage, ibuf, len);
+	sc->sc_bufusage += len;
+	if (sc->sc_bufusage != sc->sc_datalen)
+		return;		/* wait until packet is complete */
+
+	/* process the now complete protocol and clear the buffer */
+	data = sc->sc_databuf;
+	sc->sc_bufusage = 0;
 #if 0
-	printf("(");
-	for (i = 0; i < len; i++)
-		printf(" %d", data[i]);
-	printf(" )\n");
+	for (i = 0; i < sc->sc_datalen; i++)
+		printf(" %02x", data[i]);
+	printf("\n");
 #endif
 
 	/* The last byte is 1 if the button is pressed and 0 otherwise. */

Reply via email to