diff options
author | Robert Nagy <robert@cvs.openbsd.org> | 2009-03-08 14:10:09 +0000 |
---|---|---|
committer | Robert Nagy <robert@cvs.openbsd.org> | 2009-03-08 14:10:09 +0000 |
commit | b6ca9278d75a74ad0ab6bff945cdb805ea26416e (patch) | |
tree | fdd18b8ac50d329bdcc52877fca6f75f1de9afee /sys/arch | |
parent | 797f2dbac12ca3faa807f2d0e06d78d59afa24c0 (diff) |
Add support for Geyser2 devices from NetBSD and fix some Geyser1 devices that
can be found in iBook G4 12".
Remove references for LCD panel sizes because the same device can be found
on different sized laptops and it has nothing to do with the trackpad.
Introduce a type variable that stores the device type: FOUNTAIN, GEYSER1 or
GEYSER2. This value helps deciding some of the device parameters and it gets
printed in the dmesg instead of the panel size.
Introduce "mouse button emulation" on multi-touch trackpads just like in
macos, so it's not needed to bind mouse buttons to the keyboard anymore:
Tap two fingers + mouse button = 3rd mouse button = right click
Tap three fingers + mouse button = 2nd mouse button = middle click
Discussed with and ok: miod@ and maja@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/macppc/dev/tpms.c | 209 |
1 files changed, 114 insertions, 95 deletions
diff --git a/sys/arch/macppc/dev/tpms.c b/sys/arch/macppc/dev/tpms.c index 5319a9e405c..13be917e32b 100644 --- a/sys/arch/macppc/dev/tpms.c +++ b/sys/arch/macppc/dev/tpms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tpms.c,v 1.12 2007/06/14 10:11:16 mbalmer Exp $ */ +/* $OpenBSD: tpms.c,v 1.13 2009/03/08 14:10:08 robert Exp $ */ /* * Copyright (c) 2005, Johan Wallén @@ -35,7 +35,7 @@ /* * The tpms driver provides support for the trackpad on new (post - * February 2005) Apple PowerBooks (and iBooks?) that are not standard + * February 2005) Apple PowerBooks and iBooks that are not standard * USB HID mice. */ @@ -125,35 +125,6 @@ #include <dev/wscons/wsmousevar.h> /* - * Debugging output. - */ - -/* XXX Should be redone, and its use should be added back. */ - -#ifdef TPMS_DEBUG - -/* - * Print the error message (preceded by the driver and function) - * specified by the string literal fmt (followed by newline) if - * tpmsdebug is greater than n. The macro may only be used in the - * scope of sc, which must be castable to struct device *. There must - * be at least one vararg. Do not define TPMS_DEBUG on non-C99 - * compilers. - */ - -#define DPRINTFN(n, fmt, ...) \ -do { \ - if (tpmsdebug > (n)) \ - logprintf("%s: %s: " fmt "\n", \ - ((struct device *) sc)->dv_xname, \ - __func__, __VA_ARGS__); \ -} while ( /* CONSTCOND */ 0) - -int tpmsdebug = 0; - -#endif /* TPMS_DEBUG */ - -/* * Magic numbers. */ @@ -170,7 +141,8 @@ int tpmsdebug = 0; * can be different for each device. The meanings of the parameters * are as follows. * - * desc: A printable description used for dmesg output. + * type: Type of the trackpad device, used for dmesg output, and + * to know some of the device parameters. * * noise: Amount of noise in the computed position. This controls * how large a change must be to get reported, and how @@ -200,7 +172,10 @@ int tpmsdebug = 0; */ struct tpms_dev { - const char *descr; /* Description of the driver (for dmesg). */ + int type; /* Type of the trackpad. */ +#define FOUNTAIN 0x00 +#define GEYSER1 0x01 +#define GEYSER2 0x02 int noise; /* Amount of noise in the computed position. */ int threshold; /* Changes less than this are ignored. */ int x_factor; /* Factor used in computation with X-coordinates. */ @@ -214,9 +189,9 @@ struct tpms_dev { /* Devices supported by this driver. */ static struct tpms_dev tpms_devices[] = { -#define POWERBOOK_TOUCHPAD(inches, prod, x_fact, x_sens, y_fact) \ +#define POWERBOOK_TOUCHPAD(ttype, prod, x_fact, x_sens, y_fact) \ { \ - .descr = #inches " inch PowerBook Trackpad", \ + .type = (ttype), \ .vendor = USB_VENDOR_APPLE, \ .product = (prod), \ .noise = 16, \ @@ -227,14 +202,17 @@ static struct tpms_dev tpms_devices[] = .y_sensors = 16 \ } /* 12 inch PowerBooks */ - POWERBOOK_TOUCHPAD(12, 0x030a, 69, 16, 52), /* XXX Not tested. */ - /* 14 inch iBook G4 */ - POWERBOOK_TOUCHPAD(14, 0x030b, 69, 16, 52), + POWERBOOK_TOUCHPAD(FOUNTAIN, 0x030a, 69, 16, 52), /* XXX Not tested. */ + /* 12 and 14 inch iBook G4 */ + POWERBOOK_TOUCHPAD(GEYSER1, 0x030b, 69, 16, 52), /* 15 inch PowerBooks */ - POWERBOOK_TOUCHPAD(15, 0x020e, 85, 16, 57), /* XXX Not tested. */ - POWERBOOK_TOUCHPAD(15, 0x020f, 85, 16, 57), + POWERBOOK_TOUCHPAD(FOUNTAIN, 0x020e, 85, 16, 57), /* XXX Not tested. */ + POWERBOOK_TOUCHPAD(FOUNTAIN, 0x020f, 85, 16, 57), + POWERBOOK_TOUCHPAD(GEYSER2, 0x0214, 90, 15, 107), + POWERBOOK_TOUCHPAD(GEYSER2, 0x0215, 90, 15, 107), + POWERBOOK_TOUCHPAD(GEYSER2, 0x0216, 90, 15, 107), /* 17 inch PowerBooks */ - POWERBOOK_TOUCHPAD(17, 0x020d, 71, 26, 68) /* XXX Not tested. */ + POWERBOOK_TOUCHPAD(FOUNTAIN, 0x020d, 71, 26, 68) /* XXX Not tested. */ #undef POWERBOOK_TOUCHPAD }; @@ -248,9 +226,11 @@ static struct tpms_dev tpms_devices[] = /* Device data. */ struct tpms_softc { struct uhidev sc_hdev; /* USB parent (got the struct device). */ + int sc_type; /* Type of the trackpad */ + int sc_datalen; int sc_acc[TPMS_SENSORS]; /* Accumulated sensor values. */ - signed char sc_prev[TPMS_SENSORS]; /* Previous sample. */ - signed char sc_sample[TPMS_SENSORS]; /* Current sample. */ + unsigned char sc_prev[TPMS_SENSORS]; /* Previous sample. */ + unsigned char sc_sample[TPMS_SENSORS]; /* Current sample. */ struct device *sc_wsmousedev; /* WSMouse device. */ int sc_noise; /* Amount of noise. */ int sc_threshold; /* Threshold value. */ @@ -275,7 +255,7 @@ void tpms_intr(struct uhidev *, void *, unsigned int); int tpms_enable(void *); void tpms_disable(void *); int tpms_ioctl(void *, unsigned long, caddr_t, int, struct proc *); -void reorder_sample(signed char *, signed char *); +void reorder_sample(struct tpms_softc*, unsigned char *, unsigned char *); int compute_delta(struct tpms_softc *, int *, int *, int *, uint32_t *); int detect_pos(int *, int, int, int, int *, int *); int smooth_pos(int, int, int); @@ -352,6 +332,8 @@ tpms_attach(struct device *parent, struct device *self, void *aux) int i; uint16_t vendor, product; + sc->sc_datalen = TPMS_DATA_LEN; + /* Fill in device-specific parameters. */ if ((udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) { product = UGETW(udd->idProduct); @@ -359,7 +341,21 @@ tpms_attach(struct device *parent, struct device *self, void *aux) for (i = 0; i < TPMS_NUM_DEVICES; i++) { pd = &tpms_devices[i]; if (product == pd->product && vendor == pd->vendor) { - printf(": %s\n", pd->descr); + switch (pd->type) { + case FOUNTAIN: + printf(": Fountain"); + break; + case GEYSER1: + printf(": Geyser"); + break; + case GEYSER2: + sc->sc_type = GEYSER2; + sc->sc_datalen = 64; + sc->sc_y_sensors = 9; + printf(": Geyser 2"); + break; + } + printf(" Trackpad\n"); sc->sc_noise = pd->noise; sc->sc_threshold = pd->threshold; sc->sc_x_factor = pd->x_factor; @@ -480,20 +476,20 @@ void tpms_intr(struct uhidev *addr, void *ibuf, unsigned int len) { struct tpms_softc *sc = (struct tpms_softc *)addr; - signed char *data; + unsigned char *data; int dx, dy, dz, i, s; uint32_t buttons; /* Ignore incomplete data packets. */ - if (len != TPMS_DATA_LEN) + if (len != sc->sc_datalen) return; data = ibuf; /* The last byte is 1 if the button is pressed and 0 otherwise. */ - buttons = !!data[TPMS_DATA_LEN - 1]; + buttons = !!data[sc->sc_datalen - 1]; /* Everything below assumes that the sample is reordered. */ - reorder_sample(sc->sc_sample, data); + reorder_sample(sc, sc->sc_sample, data); /* Is this the first sample? */ if (!(sc->sc_status & TPMS_VALID)) { @@ -506,7 +502,9 @@ tpms_intr(struct uhidev *addr, void *ibuf, unsigned int len) } /* Accumulate the sensor change while keeping it nonnegative. */ for (i = 0; i < TPMS_SENSORS; i++) { - sc->sc_acc[i] += sc->sc_sample[i] - sc->sc_prev[i]; + sc->sc_acc[i] += + (signed char)(sc->sc_sample[i] - sc->sc_prev[i]); + if (sc->sc_acc[i] < 0) sc->sc_acc[i] = 0; } @@ -535,26 +533,40 @@ tpms_intr(struct uhidev *addr, void *ibuf, unsigned int len) */ void -reorder_sample(signed char *to, signed char *from) +reorder_sample(struct tpms_softc *sc, unsigned char *to, unsigned char *from) { int i; - for (i = 0; i < 8; i++) { - /* X-sensors. */ - to[i] = from[5 * i + 2]; - to[i + 8] = from[5 * i + 4]; - to[i + 16] = from[5 * i + 42]; + if (sc->sc_type == GEYSER2) { + int j; + + memset(to, 0, TPMS_SENSORS); + for (i = 0, j = 19; i < 20; i += 2, j += 3) { + to[i] = from[j]; + to[i + 1] = from[j + 1]; + } + for (i = 0, j = 1; i < 9; i += 2, j += 3) { + to[TPMS_X_SENSORS + i] = from[j]; + to[TPMS_X_SENSORS + i + 1] = from[j + 1]; + } + } else { + for (i = 0; i < 8; i++) { + /* X-sensors. */ + to[i] = from[5 * i + 2]; + to[i + 8] = from[5 * i + 4]; + to[i + 16] = from[5 * i + 42]; #if 0 - /* - * XXX This seems to introduce random vertical jumps, so - * we ignore these sensors until we figure out their meaning. - */ - if (i < 2) - to[i + 24] = from[5 * i + 44]; + /* + * XXX This seems to introduce random ventical jumps, so + * we ignore these sensors until we figure out their meaning. + */ + if (i < 2) + to[i + 24] = from[5 * i + 44]; #endif /* 0 */ - /* Y-sensors. */ - to[i + 26] = from[5 * i + 1]; - to[i + 34] = from[5 * i + 3]; + /* Y-sensors. */ + to[i + 26] = from[5 * i + 1]; + to[i + 34] = from[5 * i + 3]; + } } } @@ -582,42 +594,49 @@ compute_delta(struct tpms_softc *sc, int *dx, int *dy, int *dz, fingers = max(x_fingers, y_fingers); /* Check the number of fingers and if we have detected a position. */ - if (fingers > 1) { - /* More than one finger detected, resetting. */ - memset(sc->sc_acc, 0, sizeof(sc->sc_acc)); - sc->sc_x_raw = sc->sc_y_raw = sc->sc_x = sc->sc_y = -1; - return 0; - } else if (x_det == 0 && y_det == 0) { + if (x_det == 0 && y_det == 0) { /* No position detected, resetting. */ memset(sc->sc_acc, 0, sizeof(sc->sc_acc)); sc->sc_x_raw = sc->sc_y_raw = sc->sc_x = sc->sc_y = -1; } else if (x_det > 0 && y_det > 0) { - /* Smooth position. */ - if (sc->sc_x_raw >= 0) { - sc->sc_x_raw = (3 * sc->sc_x_raw + x_raw) / 4; - sc->sc_y_raw = (3 * sc->sc_y_raw + y_raw) / 4; - /* - * Compute virtual position and change if we already - * have a decent position. - */ - if (sc->sc_x >= 0) { - x = smooth_pos(sc->sc_x, sc->sc_x_raw, - sc->sc_noise); - y = smooth_pos(sc->sc_y, sc->sc_y_raw, - sc->sc_noise); - *dx = x - sc->sc_x; - *dy = y - sc->sc_y; - sc->sc_x = x; - sc->sc_y = y; + switch (fingers) { + case 1: + /* Smooth position. */ + if (sc->sc_x_raw >= 0) { + sc->sc_x_raw = (3 * sc->sc_x_raw + x_raw) / 4; + sc->sc_y_raw = (3 * sc->sc_y_raw + y_raw) / 4; + /* + * Compute virtual position and change if we + * already have a decent position. + */ + if (sc->sc_x >= 0) { + x = smooth_pos(sc->sc_x, sc->sc_x_raw, + sc->sc_noise); + y = smooth_pos(sc->sc_y, sc->sc_y_raw, + sc->sc_noise); + *dx = x - sc->sc_x; + *dy = y - sc->sc_y; + sc->sc_x = x; + sc->sc_y = y; + } else { + /* Initialise virtual position. */ + sc->sc_x = sc->sc_x_raw; + sc->sc_y = sc->sc_y_raw; + } } else { - /* Initialise virtual position. */ - sc->sc_x = sc->sc_x_raw; - sc->sc_y = sc->sc_y_raw; + /* Initialise raw position. */ + sc->sc_x_raw = x_raw; + sc->sc_y_raw = y_raw; } - } else { - /* Initialise raw position. */ - sc->sc_x_raw = x_raw; - sc->sc_y_raw = y_raw; + break; + case 2: + if (*buttons == 1) + *buttons = 4; + break; + case 3: + if (*buttons == 1) + *buttons = 2; + break; } } return (1); |