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.
This commit is contained in:
phx 2010-12-20 19:18:24 +00:00
parent 722eddfd32
commit 155d37a03c
1 changed files with 40 additions and 13 deletions

View File

@ -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 @@ static struct pbms_dev pbms_devices[] =
.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 @@ static struct pbms_dev pbms_devices[] =
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 @@ pbms_attach(device_t parent, device_t self, void *aux)
sc->sc_datalen = 64;
sc->sc_y_sensors = 9;
}
else if (product == 0x030b)
sc->sc_y_sensors = 9;
break;
}
}
@ -421,6 +428,7 @@ pbms_enable(void *v)
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 @@ void
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. */