summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sys-kernel/mactel-linux-sources/files/mactel-patches-r142/appletouch-new.patch')
-rw-r--r--sys-kernel/mactel-linux-sources/files/mactel-patches-r142/appletouch-new.patch385
1 files changed, 385 insertions, 0 deletions
diff --git a/sys-kernel/mactel-linux-sources/files/mactel-patches-r142/appletouch-new.patch b/sys-kernel/mactel-linux-sources/files/mactel-patches-r142/appletouch-new.patch
new file mode 100644
index 0000000..a81fe75
--- /dev/null
+++ b/sys-kernel/mactel-linux-sources/files/mactel-patches-r142/appletouch-new.patch
@@ -0,0 +1,385 @@
+A few month ago I implemented palm-detection to the appletouch driver and
+
+From: Sven Anders <anders@anduras.de>
+
+released a development version. Currently I'm trying to reimplement these
+in a clean way and I'm planning to release it in parts, so I would be accepted
+by the kernel developers.
+
+Late in the develoment progress I found out, that the new Geyser 3/4 touchpad
+have special status flags. This patch implements the usage of them and corrects
+the calculation of the pressure (for later usage by the palm detection).
+
+It was tested by some debian people (Johannes Berg, Michel Dänzer, Gaudenz
+Steinlin) on the PowerBook and works there too.
+---
+
+ drivers/input/mouse/appletouch.c | 187 ++++++++++++++++++++++++++------------
+ 1 files changed, 126 insertions(+), 61 deletions(-)
+
+diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
+index 51cc7c3..4c838d1 100644
+--- a/drivers/input/mouse/appletouch.c
++++ b/drivers/input/mouse/appletouch.c
+@@ -8,8 +8,12 @@
+ * Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
+ * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
+ * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch)
++ * Copyright (C) 2007 Sven Anders (anders@anduras.de)
+ *
+ * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
++ * Jason Parekh <jasonparekh@gmail.com> for better finger detection.
++ * Matthew Garrett <mjg59@srcf.ucam.org> for power saving additions.
++ * Soeren Sonnenburg <mactel-ml@nn7.de> for corrections and ideas.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -38,16 +42,17 @@
+ #define APPLE_VENDOR_ID 0x05AC
+
+ /* These names come from Info.plist in AppleUSBTrackpad.kext */
++
++/* PowerBooks Feb 2005 / iBooks */
+ #define FOUNTAIN_ANSI_PRODUCT_ID 0x020E
+ #define FOUNTAIN_ISO_PRODUCT_ID 0x020F
+-
+ #define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A
+-
+ #define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B
+
+-#define GEYSER_ANSI_PRODUCT_ID 0x0214
+-#define GEYSER_ISO_PRODUCT_ID 0x0215
+-#define GEYSER_JIS_PRODUCT_ID 0x0216
++/* PowerBooks Oct 2005 */
++#define GEYSER2_ANSI_PRODUCT_ID 0x0214
++#define GEYSER2_ISO_PRODUCT_ID 0x0215
++#define GEYSER2_JIS_PRODUCT_ID 0x0216
+
+ /* MacBook devices */
+ #define GEYSER3_ANSI_PRODUCT_ID 0x0217
+@@ -58,9 +63,9 @@
+ * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext
+ * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables
+ */
+-#define GEYSER4_ANSI_PRODUCT_ID 0x021A
+-#define GEYSER4_ISO_PRODUCT_ID 0x021B
+-#define GEYSER4_JIS_PRODUCT_ID 0x021C
++#define GEYSER4_ANSI_PRODUCT_ID 0x021A
++#define GEYSER4_ISO_PRODUCT_ID 0x021B
++#define GEYSER4_JIS_PRODUCT_ID 0x021C
+
+ #define ATP_DEVICE(prod) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+@@ -73,15 +78,17 @@
+
+ /* table of devices that work with this driver */
+ static struct usb_device_id atp_table [] = {
++
++ /* PowerBooks Feb 2005, iBooks G4 */
+ { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) },
+
+ /* PowerBooks Oct 2005 */
+- { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
+- { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
+- { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
++ { ATP_DEVICE(GEYSER2_ANSI_PRODUCT_ID) },
++ { ATP_DEVICE(GEYSER2_ISO_PRODUCT_ID) },
++ { ATP_DEVICE(GEYSER2_JIS_PRODUCT_ID) },
+
+ /* Core Duo MacBook & MacBook Pro */
+ { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) },
+@@ -136,27 +143,36 @@ MODULE_DEVICE_TABLE (usb, atp_table);
+ #define ATP_GEYSER3_MODE_REQUEST_INDEX 0
+ #define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04
+
++/*
++ * Meaning of the status bits (only Geyser 3/4?)
++ */
++#define ATP_STATUS_BIT_BUTTON 0x01 /* The button was pressed */
++#define ATP_STATUS_BIT_UNKNOWN1 0x02 /* Unknown or unused */
++#define ATP_STATUS_BIT_BASE_UPDATE 0x04 /* Update of the base values (untouched pad) */
++#define ATP_STATUS_BIT_UNKNOWN2 0x08 /* Unknown or unused */
++#define ATP_STATUS_BIT_FROM_RESET 0x10 /* Reset previously performed */
++
+ /* Structure to hold all of our device specific stuff */
+ struct atp {
+ char phys[64];
+ struct usb_device * udev; /* usb device */
+ struct urb * urb; /* usb request block */
+- signed char * data; /* transferred data */
++ u8 * data; /* transferred data */
+ int open; /* non-zero if opened */
+ struct input_dev *input; /* input dev */
+ int valid; /* are the sensors valid ? */
+ int x_old; /* last reported x/y, */
+ int y_old; /* used for smoothing */
+ /* current value of the sensors */
+- signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
++ u16 xy_cur[ATP_XSENSORS + ATP_YSENSORS];
+ /* last value of the sensors */
+- signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
++ u16 xy_old[ATP_XSENSORS + ATP_YSENSORS];
+ /* accumulated sensors */
+ int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+ int overflowwarn; /* overflow warning printed? */
+ int datalen; /* size of an USB urb transfer */
+- int idlecount; /* number of empty packets */
+- struct work_struct work;
++ int idle_counter; /* idle counter */
++ struct work_struct work; /* kernel workqueue entry (for re-init) */
+ };
+
+ #define dbg_dump(msg, tab) \
+@@ -173,8 +189,12 @@ struct atp {
+ if (debug) printk(format, ##a); \
+ } while (0)
+
+-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
+-MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
++MODULE_AUTHOR("Johannes Berg");
++MODULE_AUTHOR("Stelian Pop");
++MODULE_AUTHOR("Frank Arnold");
++MODULE_AUTHOR("Michael Hanselmann");
++MODULE_AUTHOR("Sven Anders");
++MODULE_DESCRIPTION("Apple PowerBook and MacBook USB touchpad driver");
+ MODULE_LICENSE("GPL");
+
+ /*
+@@ -184,7 +204,7 @@ static int threshold = ATP_THRESHOLD;
+ module_param(threshold, int, 0644);
+ MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value");
+
+-static int debug = 1;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Activate debugging output");
+
+@@ -193,9 +213,9 @@ static inline int atp_is_geyser_2(struct atp *dev)
+ {
+ u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+- return (productId == GEYSER_ANSI_PRODUCT_ID) ||
+- (productId == GEYSER_ISO_PRODUCT_ID) ||
+- (productId == GEYSER_JIS_PRODUCT_ID);
++ return (productId == GEYSER2_ANSI_PRODUCT_ID) ||
++ (productId == GEYSER2_ISO_PRODUCT_ID) ||
++ (productId == GEYSER2_JIS_PRODUCT_ID);
+ }
+
+ static inline int atp_is_geyser_3(struct atp *dev)
+@@ -211,24 +231,29 @@ static inline int atp_is_geyser_3(struct atp *dev)
+ }
+
+ /*
+- * By default Geyser 3 device sends standard USB HID mouse
+- * packets (Report ID 2). This code changes device mode, so it
+- * sends raw sensor reports (Report ID 5).
++ * By default Geyser 3 and Geyser 4 devices sends standard
++ * USB HID mouse packets (Report ID 2). This code changes device
++ * mode, so it sends raw sensor reports (Report ID 5).
+ */
+-static int atp_geyser3_init(struct usb_device *udev)
++static int atp_geyser3_4_init(struct usb_device *udev)
+ {
+ char data[8];
+ int size;
++ int i;
+
+ size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+- ATP_GEYSER3_MODE_READ_REQUEST_ID,
+- USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+- ATP_GEYSER3_MODE_REQUEST_VALUE,
+- ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
++ ATP_GEYSER3_MODE_READ_REQUEST_ID,
++ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
++ ATP_GEYSER3_MODE_REQUEST_VALUE,
++ ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+
+ if (size != 8) {
++ printk("appletouch atp_geyser3_4_init READ error\n");
++ for (i=0; i<8; i++)
++ printk("appletouch[%d]: %d\n", i, (int) data[i]);
++
+ err("Could not do mode read request from device"
+- " (Geyser 3 mode)");
++ " (Geyser 3/4 mode)");
+ return -EIO;
+ }
+
+@@ -236,27 +261,31 @@ static int atp_geyser3_init(struct usb_device *udev)
+ data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE;
+
+ size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+- ATP_GEYSER3_MODE_WRITE_REQUEST_ID,
+- USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+- ATP_GEYSER3_MODE_REQUEST_VALUE,
+- ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
++ ATP_GEYSER3_MODE_WRITE_REQUEST_ID,
++ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
++ ATP_GEYSER3_MODE_REQUEST_VALUE,
++ ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+
+ if (size != 8) {
++ printk("appletouch atp_geyser3_4_init WRITE error\n");
++ for (i=0; i<8; i++)
++ printk("appletouch[%d]: %d\n", i, (int) data[i]);
++
+ err("Could not do mode write request to device"
+- " (Geyser 3 mode)");
++ " (Geyser 3/4 mode)");
+ return -EIO;
+ }
+ return 0;
+ }
+
+-/* Reinitialise the device if it's a geyser 3 */
++/* Reinitialise the device if it's a geyser 3/4 */
+ static void atp_reinit(struct work_struct *work)
+ {
+ struct atp *dev = container_of(work, struct atp, work);
+ struct usb_device *udev = dev->udev;
+
+- dev->idlecount = 0;
+- atp_geyser3_init(udev);
++ dprintk("appletouch: putting appletouch to sleep (reinit)\n");
++ atp_geyser3_4_init(udev);
+ }
+
+ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
+@@ -421,10 +450,15 @@ static void atp_complete(struct urb* urb)
+ dbg_dump("sample", dev->xy_cur);
+
+ if (!dev->valid) {
+- /* first sample */
++ /* first sample after init or resume */
+ dev->valid = 1;
+ dev->x_old = dev->y_old = -1;
+- memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
++ dev->idle_counter = 0;
++
++ /* store first sample on older Geyser */
++ if ((dev->data[dev->datalen-1] & ATP_STATUS_BIT_BASE_UPDATE) ||
++ !atp_is_geyser_3(dev))
++ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+ if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
+ goto exit;
+@@ -451,18 +485,39 @@ static void atp_complete(struct urb* urb)
+ goto exit;
+ }
+
++ /* Just update the base values (i.e. touchpad in untouched state) */
++ if (dev->data[dev->datalen-1] & ATP_STATUS_BIT_BASE_UPDATE)
++ {
++ if (debug > 0) printk("appletouch: updated base values\n");
++
++ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
++ goto exit;
++ }
++
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+- /* accumulate the change */
+- signed char change = dev->xy_old[i] - dev->xy_cur[i];
+- dev->xy_acc[i] -= change;
++ /* calculate the change */
++ dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i];
++
++ /* this is a round-robin value, so couple with that */
++ if (dev->xy_acc[i] > 127)
++ dev->xy_acc[i] -= 256;
++
++ if (dev->xy_acc[i] < -127)
++ dev->xy_acc[i] += 256;
++
++ /* Needed for the older Geyser */
++ if (!atp_is_geyser_3(dev))
++ {
++ /* store new 'untouched' value, if any new */
++ if (dev->xy_acc[i] < -1)
++ dev->xy_old[i] = dev->xy_cur[i];
++ }
+
+- /* prevent down drifting */
+- if (dev->xy_acc[i] < 0)
++ /* prevent down-drifting */
++ if (dev->xy_acc[i] < 0)
+ dev->xy_acc[i] = 0;
+ }
+
+- memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+-
+ dbg_dump("accumulator", dev->xy_acc);
+
+ x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
+@@ -478,7 +533,7 @@ static void atp_complete(struct urb* urb)
+ dev->x_old = x;
+ dev->y_old = y;
+
+- if (debug > 1)
++ if (debug > 0)
+ printk("appletouch: X: %3d Y: %3d "
+ "Xz: %3d Yz: %3d\n",
+ x, y, x_z, y_z);
+@@ -503,20 +558,30 @@ static void atp_complete(struct urb* urb)
+ /* reset the accumulator on release */
+ memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+
+- /* Geyser 3 will continue to send packets continually after
+- the first touch unless reinitialised. Do so if it's been
+- idle for a while in order to avoid waking the kernel up
+- several hundred times a second */
+- if (!key && atp_is_geyser_3(dev)) {
+- dev->idlecount++;
+- if (dev->idlecount == 10) {
+- dev->valid = 0;
++ /* Idle counter */
++ dev->idle_counter++;
++
++ /* Wait for 10 more packages before suspending */
++ if (dev->idle_counter > 10) {
++
++ /* Get every 10th sample, reset counter */
++ dev->idle_counter = 0;
++
++ /* Geyser 3/4 will continue to send packets continually
++ after the first touch. The function is called every
++ 8 milliseconds from interrups context, unless
++ reinitialised. Do so if it's been idle for a while
++ in order to avoid waking the kernel up several
++ hundred times a second */
++
++ if (!key && atp_is_geyser_3(dev))
+ schedule_work(&dev->work);
+- }
+ }
+ }
+
+- input_report_key(dev->input, BTN_LEFT, key);
++ input_report_key(dev->input, BTN_LEFT,
++ dev->data[dev->datalen - 1] & ATP_STATUS_BIT_BUTTON);
++
+ input_sync(dev->input);
+
+ exit:
+@@ -593,9 +658,8 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
+
+ if (atp_is_geyser_3(dev)) {
+ /* switch to raw sensor mode */
+- if (atp_geyser3_init(udev))
++ if (atp_geyser3_4_init(udev))
+ goto err_free_devs;
+-
+ printk("appletouch Geyser 3 inited.\n");
+ }
+
+@@ -670,6 +734,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(iface, dev);
+
++ /* initialize kernel work queue for re-init out of interrupt context */
+ INIT_WORK(&dev->work, atp_reinit);
+
+ return 0;