This is a driver for the USB touchpad which can be found on
post-February 2005 Apple PowerBooks (PowerBook5,6).
This driver is derived from Johannes Berg's appletrackpad driver [1],
but it has been improved in some areas:
* appletouch is a full kernel driver, no userspace program is necessary
* appletouch can be interfaced with the synaptics X11 driver[2], in order
to have touchpad acceleration, scrolling, etc.
This driver has been tested by the readers of the 'debian-powerpc'
mailing list for a few weeks now and I believe it is now ready for
inclusion into the mainline kernel.
Credits go to Johannes Berg for reverse-engineering the touchpad
protocol, Frank Arnold for further improvements, and Alex Harper for
some additional information about the inner workings of the touchpad
sensors.
Please apply.
Stelian.
[1]: http://johannes.sipsolutions.net/PowerBook/touchpad/
[2]: http://web.telia.com/~u89404340/touchpad/index.html
Index: linux-2.6-trunk.git/drivers/usb/input/Makefile
===================================================================
--- linux-2.6-trunk.git.orig/drivers/usb/input/Makefile 2005-06-28 10:25:42.000000000 +0200
+++ linux-2.6-trunk.git/drivers/usb/input/Makefile 2005-07-08 11:10:29.000000000 +0200
@@ -39,3 +39,4 @@
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
obj-$(CONFIG_USB_XPAD) += xpad.o
+obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o
Index: linux-2.6-trunk.git/drivers/usb/input/Kconfig
===================================================================
--- linux-2.6-trunk.git.orig/drivers/usb/input/Kconfig 2005-06-28 10:25:42.000000000 +0200
+++ linux-2.6-trunk.git/drivers/usb/input/Kconfig 2005-07-08 11:14:48.000000000 +0200
@@ -259,3 +259,21 @@
To compile this driver as a module, choose M here: the module will be
called ati_remote.
+config USB_APPLETOUCH
+ tristate "Apple USB Touchpad support"
+ depends on USB && INPUT
+ ---help---
+ Say Y here if you want to use an Apple USB Touchpad.
+
+ These are the touchpads that can be found on post-February 2005
+ Apple Powerbooks (PowerBook5,6).
+
+ This driver provides a basic mouse driver but can be interfaced
+ with the synaptics X11 driver to provide acceleration and
+ scrolling in X11.
+
+ For further information, see
+ <file:Documentation/input/appletouch.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called appletouch.
Index: linux-2.6-trunk.git/Documentation/input/appletouch.txt
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-trunk.git/Documentation/input/appletouch.txt 2005-07-08 11:15:03.000000000 +0200
@@ -0,0 +1,120 @@
+Apple Touchpad Driver (appletouch)
+----------------------------------
+ Copyright (C) 2005 Stelian Pop <ste...@popies.net>
+
+appletouch is a Linux kernel driver for the USB touchpad found on post
+February 2005 Apple Alu Powerbooks.
+
+This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
+been improved in some areas:
+ * appletouch is a full kernel driver, no userspace program is necessary
+ * appletouch can be interfaced with the synaptics X11 driver, in order
+ to have touchpad acceleration, scrolling, etc.
+
+Credits go to Johannes Berg for reverse-engineering the touchpad protocol,
+Frank Arnold for further improvements, and Alex Harper for some additional
+information about the inner workings of the touchpad sensors.
+
+Usage:
+------
+
+In order to use the touchpad in the basic mode, compile the driver and load
+the module. A new input device will be detected and you will be able to read
+the mouse data from /dev/input/mice (using gpm, or X11).
+
+In X11, you can configure the touchpad to use the synaptics X11 driver, which
+will give additional functionalities, like acceleration, scrolling etc. In
+order to do this, make sure you're using a recent version of the synaptics
+driver (tested with 0.14.2, available from [2]), and configure a new input
+device in your X11 configuration file (take a look below for an example). For
+additional configuration, see the synaptics driver documentation.
+
+ Section "InputDevice"
+ Identifier "Synaptics Touchpad"
+ Driver "synaptics"
+ Option "SendCoreEvents" "true"
+ Option "Device" "/dev/input/mice"
+ Option "Protocol" "auto-dev"
+ Option "LeftEdge" "0"
+ Option "RightEdge" "850"
+ Option "TopEdge" "0"
+ Option "BottomEdge" "645"
+ Option "MinSpeed" "0.4"
+ Option "MaxSpeed" "1"
+ Option "AccelFactor" "0.02"
+ Option "FingerLow" "55"
+ Option "FingerHigh" "60"
+ Option "MaxTapMove" "20"
+ Option "MaxTapTime" "100"
+ Option "HorizScrollDelta" "0"
+ Option "VertScrollDelta" "30"
+ Option "SHMConfig" "on"
+ EndSection
+
+ Section "ServerLayout"
+ ...
+ InputDevice "Mouse"
+ InputDevice "Synaptics Touchpad"
+ ...
+ EndSection
+
+Fuzz problems:
+--------------
+
+The touchpad sensors are very sensitive to heat, and will generate a lot of
+noise when the temperature changes. This is especially true when you power-on
+the laptop for the first time.
+
+The appletouch driver tries to handle this noise and auto adapt itself, but it
+is not perfect. If finger movements are not recognized anymore, try reloading
+the driver.
+
+You can activate debugging using the 'debug' module parameter. A value of 0
+deactivates any debugging, 1 activates tracing of invalid samples, 2 activates
+full tracing (each sample is being traced):
+ modprobe appletouch debug=1
+ or
+ echo "1" > /sys/module/appletouch/parameters/debug
+
+Synaptics re-detection problems:
+--------------------------------
+
+The synaptics X11 driver tries to re-open the touchpad input device file
+(/dev/input/eventX) each time you change from text mode back to X11. If the
+input device file does not exist at this precise moment, the synaptics driver
+will give up searching for a touchpad, permanently. You will need to restart
+X11 if you want to reissue a scan.
+
+In normal circumstances, this is not a problem since the touchpad driver is
+loaded before X11 starts, so all will go well.
+
+But if you rmmod/insmod the appletouch driver (because you're hacking it), or
+if you need to unload the usb modules before doing a suspend to disk (like I
+need to), you will get into problems.
+
+The solution I found is to modify udev configuration files in order to create a
+stable device file for the touchpad (/dev/input/appletouch), and point the
+synaptics driver to this fixed device file.
+
+You need to add this rule to /etc/udev/udev.rules:
+
+ # Add a symlink for the touchpad
+ KERNEL="event[0-9]*", BUS="usb", SYSFS{interface}="Touchpad", SYMLINK="input/appletouch"
+
+And of course instruct X11 to look at /dev/input/appletouch instead of
+/dev/input/mice:
+
+ Section "InputDevice"
+ Identifier "Synaptics Touchpad"
+ Driver "synaptics"
+ Option "SendCoreEvents" "true"
+ Option "Device" "/dev/input/appletouch"
+ Option "Protocol" "event"
+ ...
+ EndSection
+
+Links:
+------
+
+[1]: http://johannes.sipsolutions.net/PowerBook/touchpad/
+[2]: http://web.telia.com/~u89404340/touchpad/index.html
Index: linux-2.6-trunk.git/drivers/usb/input/appletouch.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-trunk.git/drivers/usb/input/appletouch.c 2005-07-08 11:35:06.000000000 +0200
@@ -0,0 +1,515 @@
+/*
+ * Apple USB Touchpad (PowerBook5,6) driver
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (gr...@kroah.com)
+ * Copyright (C) 2005 Johannes Berg (joha...@sipsolutions.net)
+ * Copyright (C) 2005 Stelian Pop (ste...@popies.net)
+ * Copyright (C) 2005 Frank Arnold (fr...@scirocco-5v-turbo.de)
+ *
+ * Thanks to Alex Harper <basi...@foobox.net> for his inputs.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+
+/* Apple has powerbooks which have the keyboard with different Product IDs */
+#define APPLE_VENDOR_ID 0x05AC
+#define ATP_12INCH_ID1 0x030A
+#define ATP_15INCH_ID1 0x020E
+#define ATP_15INCH_ID2 0x020F
+#define ATP_17INCH_ID1 0xFFFF /* XXX need a tester !!! */
+
+#define ATP_DRIVER_VERSION 0x0006 /* 00.06 */
+
+#define ATP_DEVICE(prod) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_INT_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
+ .idVendor = APPLE_VENDOR_ID, \
+ .idProduct = (prod), \
+ .bInterfaceClass = 0x03, \
+ .bInterfaceProtocol = 0x02
+
+/* table of devices that work with this driver */
+static struct usb_device_id atp_table [] = {
+ { ATP_DEVICE(ATP_12INCH_ID1) },
+ { ATP_DEVICE(ATP_15INCH_ID1) },
+ { ATP_DEVICE(ATP_15INCH_ID2) },
+#if 0
+ Disabled until someone gives us the real USB id and tests the driver
+ { ATP_DEVICE(ATP_17INCH_ID1) },
+#endif
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, atp_table);
+
+/* size of a USB urb transfer */
+#define ATP_DATASIZE 81
+
+/*
+ * number of sensors. Note that only 16 of the 26 x sensors are used on
+ * 12" and 15" Powerbooks.
+ */
+#define ATP_XSENSORS 26
+#define ATP_YSENSORS 16
+
+/* amount of fuzz this touchpad generates */
+#define ATP_FUZZ 16
+
+/*
+ * multiplication factor for the X and Y coordinates.
+ * We try to keep the touchpad aspect ratio while still doing only simple
+ * arithmetics.
+ * The factors below give coordinates like:
+ * 0 <= x < 960 on 12" and 15" Powerbooks
+ * 0 <= x < 1600 on 17" Powerbooks
+ * 0 <= y < 646
+ */
+#define ATP_XFACT 64
+#define ATP_YFACT 43
+
+/*
+ * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
+ * ignored.
+ */
+#define ATP_THRESHOLD 4
+
+/*
+ * Size of the history for smoothing.
+ */
+#define ATP_HSIZE 5
+
+struct point {
+ unsigned int x;
+ unsigned int y;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct atp {
+ struct usb_device * udev; /* usb device */
+ struct urb * urb; /* usb request block */
+ signed char * data; /* transferred data */
+ int open; /* open count */
+ struct input_dev input; /* input dev */
+ int h_count; /* history for smoothing */
+ struct point h[ATP_HSIZE];
+ unsigned int h_index;
+};
+
+#define dbg_dump(msg, tab) \
+ if (debug > 1) { \
+ int i; \
+ printk("appletouch: %s ", msg); \
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
+ printk("%02x ", tab[i]); \
+ printk("\n"); \
+ }
+
+#define dprintk(format, a...) \
+ do { \
+ if (debug) printk(format, ##a); \
+ } while (0)
+
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_DESCRIPTION("Touchpad driver for Apple Powerbooks Alu (PowerBook5,6)");
+MODULE_LICENSE("GPL");
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activate debugging output");
+
+/* are the sensors in a valid state ? */
+static int valid = 0;
+
+/*
+ * Smooth the data sequence by estimating the slope for the data sequence
+ * [x3, x2, x1, x0] by using linear regression to fit a line to the data and
+ * use the slope of the line. Taken from the synaptics X driver.
+ */
+
+#define HIST(a) (dev->h[((dev->h_index - (a) + ATP_HSIZE) % ATP_HSIZE)])
+
+static inline void store_history(struct atp *atp, int x, int y)
+{
+ atp->h_index = (atp->h_index + 1) % ATP_HSIZE;
+ atp->h[atp->h_index].x = x;
+ atp->h[atp->h_index].y = y;
+ atp->h_count++;
+}
+
+static inline int smooth_history(int x0, int x1, int x2, int x3)
+{
+ return x0 - ( x0 * 3 + x1 - x2 - x3 * 3 ) / 10;
+}
+
+static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact) {
+ int i;
+ /* values to calculate mean */
+ int pcum = 0, psum = 0;
+ /* indexes of the first and last triggered sensors */
+ int istart = -1, iend = -1;
+
+ for (i = 0; i < nb_sensors; i++) {
+ if (xy_sensors[i] > ATP_THRESHOLD && istart == -1)
+ istart = i;
+ if (xy_sensors[i] < ATP_THRESHOLD && istart != -1 && iend == -1)
+ iend = i;
+ if (xy_sensors[i] > ATP_THRESHOLD && iend != -1) {
+ /*
+ * in the future, we could add here code to search for
+ * a second finger...
+ * for now, scrolling using the synaptics X driver is
+ * much more simpler to achieve.
+ */
+ dprintk("appletouch: invalid sensor at %d"
+ " (2 fingers ?)\n", i);
+ return -1;
+ }
+ }
+
+ if (istart == -1)
+ return 0;
+
+ if (iend == -1)
+ iend = nb_sensors;
+
+ for (i = istart; i < iend; i++) {
+ pcum += xy_sensors[i] * i;
+ psum += xy_sensors[i];
+ }
+
+ return pcum * fact / psum;
+}
+
+static void atp_complete(struct urb* urb, struct pt_regs* regs) {
+ static int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+ static signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
+ static signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
+ int retval, i;
+ int x_hw, y_hw;
+ struct atp *dev = urb->context;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* This urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+ /* drop incomplete datasets */
+ if (dev->urb->actual_length != ATP_DATASIZE) {
+ dprintk("appletouch: incomplete data package.\n");
+ goto exit;
+ }
+
+ /* reorder the sensors values */
+ for (i = 0; i < 8; i++) {
+ /* X values */
+ xy_cur[i ] = dev->data[5 * i + 2];
+ xy_cur[i + 8] = dev->data[5 * i + 4];
+ xy_cur[i + 16] = dev->data[5 * i + 42];
+ if (i < 2)
+ xy_cur[i + 24] = dev->data[5 * i + 44];
+
+ /* Y values */
+ xy_cur[i + 26] = dev->data[5 * i + 1];
+ xy_cur[i + 34] = dev->data[5 * i + 3];
+ }
+
+ dbg_dump("sample", xy_cur);
+
+ if (!valid) {
+ /* first sample */
+ valid = 1;
+ memcpy(xy_old, xy_cur, sizeof(xy_old));
+ dev->h_count = 0;
+ goto exit;
+ }
+
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+
+ /* accumulate the change */
+ signed char change = xy_old[i] - xy_cur[i];
+ xy_acc[i] -= change;
+
+ /* prevent down drifting */
+ if (xy_acc[i] < 0)
+ xy_acc[i] = 0;
+ }
+
+ memcpy(xy_old, xy_cur, sizeof(xy_old));
+
+ dbg_dump("accumulator", xy_acc);
+
+ x_hw = atp_calculate_abs(xy_acc,
+ ATP_XSENSORS, ATP_XFACT);
+ y_hw = atp_calculate_abs(xy_acc + ATP_XSENSORS,
+ ATP_YSENSORS, ATP_YFACT);
+
+ if (x_hw < 0 || y_hw < 0) {
+ memset(xy_acc, 0, sizeof(xy_acc));
+ goto exit;
+ }
+
+ if (x_hw && y_hw) {
+
+ /* need at least 3 points to smooth */
+ if (dev->h_count > 3) {
+ unsigned int x_sm, y_sm;
+ x_sm = smooth_history(x_hw, HIST(0).x,
+ HIST(1).x, HIST(2).x);
+ y_sm = smooth_history(y_hw, HIST(0).y,
+ HIST(1).y, HIST(2).y);
+
+ if (debug > 1)
+ printk("appletouch: Xhw: %3d Yhw: %3d "
+ "Xsm: %3d Ysm: %3d\n",
+ x_hw, y_hw, x_sm, y_sm);
+
+ input_report_key(&dev->input, BTN_TOUCH, 1);
+ input_report_abs(&dev->input, ABS_X, x_sm);
+ input_report_abs(&dev->input, ABS_Y, y_sm);
+ input_report_abs(&dev->input, ABS_PRESSURE, 100);
+ input_report_key(&dev->input, BTN_TOOL_FINGER, 1);
+ }
+ store_history(dev, x_hw, y_hw);
+ }
+ else if (!x_hw && !y_hw) {
+
+ dev->h_count = 0;
+ input_report_key(&dev->input, BTN_TOUCH, 0);
+ input_report_abs(&dev->input, ABS_PRESSURE, 0);
+ input_report_key(&dev->input, BTN_TOOL_FINGER, 0);
+
+ /* reset the accumulator on release */
+ memset(xy_acc, 0, sizeof(xy_acc));
+ }
+
+ input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);
+
+ input_sync(&dev->input);
+
+exit:
+ retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+ if (retval) {
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, retval);
+ }
+}
+
+static int atp_open(struct input_dev *input)
+{
+ struct atp *dev = input->private;
+
+ if (dev->open++)
+ return 0;
+
+ if (usb_submit_urb(dev->urb, GFP_ATOMIC)) {
+ dev->open--;
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void atp_close(struct input_dev *input)
+{
+ struct atp *dev = input->private;
+
+ if (!--dev->open)
+ usb_kill_urb(dev->urb);
+}
+
+static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
+{
+ struct atp *dev = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int int_in_endpointAddr = 0;
+ int i, retval = -ENOMEM;
+
+ /* allocate memory for our device state and initialize it */
+ dev = kmalloc(sizeof(struct atp), GFP_KERNEL);
+ if (dev == NULL) {
+ err("Out of memory");
+ goto err_kmalloc;
+ }
+ memset(dev, 0, sizeof(struct atp));
+
+ dev->udev = interface_to_usbdev(iface);
+
+ /* set up the endpoint information */
+ /* use only the first interrupt-in endpoint */
+ iface_desc = iface->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+ endpoint = &iface_desc->endpoint[i].desc;
+ if (!int_in_endpointAddr &&
+ (endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT)) {
+ /* we found an interrupt in endpoint */
+ int_in_endpointAddr = endpoint->bEndpointAddress;
+ break;
+ }
+ }
+ if (!int_in_endpointAddr) {
+ retval = -EIO;
+ err("Could not find int-in endpoint");
+ goto err_endpoint;
+ }
+
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(iface, dev);
+
+ dev->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->urb) {
+ retval = -ENOMEM;
+ goto err_usballoc;
+ }
+ dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+ &dev->urb->transfer_dma);
+ if (!dev->data) {
+ retval = -ENOMEM;
+ goto err_usbbufalloc;
+ }
+ usb_fill_int_urb(dev->urb, dev->udev,
+ usb_rcvintpipe(dev->udev, int_in_endpointAddr),
+ dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+
+ init_input_dev(&dev->input);
+ dev->input.name = "appletouch";
+ dev->input.dev = &iface->dev;
+ dev->input.private = dev;
+ dev->input.open = atp_open;
+ dev->input.close = atp_close;
+
+ dev->input.id.bustype = BUS_USB;
+ dev->input.id.vendor = id->idVendor;
+ dev->input.id.product = id->idProduct;
+ dev->input.id.version = ATP_DRIVER_VERSION;
+
+ set_bit(EV_ABS, dev->input.evbit);
+ if (id->idProduct == ATP_17INCH_ID1)
+ input_set_abs_params(&dev->input, ABS_X, 0,
+ (ATP_XSENSORS - 1) * ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+ else
+ /* 12" and 15" Powerbooks only have 16 x sensors */
+ input_set_abs_params(&dev->input, ABS_X, 0,
+ (16 - 1) * ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+ input_set_abs_params(&dev->input, ABS_Y, 0,
+ (ATP_YSENSORS - 1) * ATP_YFACT - 1,
+ ATP_FUZZ, 0);
+ input_set_abs_params(&dev->input, ABS_PRESSURE, 0, 100, 0, 0);
+
+ set_bit(EV_KEY, dev->input.evbit);
+ set_bit(BTN_TOUCH, dev->input.keybit);
+ set_bit(BTN_TOOL_FINGER, dev->input.keybit);
+ set_bit(BTN_LEFT, dev->input.keybit);
+
+ input_register_device(&dev->input);
+
+ printk(KERN_INFO "input: appletouch connected\n");
+
+ return 0;
+
+err_usbbufalloc:
+ usb_free_urb(dev->urb);
+err_usballoc:
+ usb_set_intfdata(iface, NULL);
+err_endpoint:
+ kfree(dev);
+err_kmalloc:
+ return retval;
+}
+
+static void atp_disconnect(struct usb_interface *iface)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+
+ usb_set_intfdata(iface, NULL);
+ if (dev) {
+ usb_kill_urb(dev->urb);
+ input_unregister_device(&dev->input);
+ usb_free_urb(dev->urb);
+ usb_buffer_free(dev->udev, ATP_DATASIZE,
+ dev->data, dev->urb->transfer_dma);
+ kfree(dev);
+ }
+ printk(KERN_INFO "input: appletouch disconnected\n");
+}
+
+static int atp_suspend(struct usb_interface *iface, pm_message_t message)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+ if (dev->open)
+ usb_kill_urb(dev->urb);
+ valid = 0;
+ return 0;
+}
+
+static int atp_resume(struct usb_interface *iface)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+ if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC)) {
+ dev->open--;
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static struct usb_driver atp_driver = {
+ .owner = THIS_MODULE,
+ .name = "appletouch",
+ .probe = atp_probe,
+ .disconnect = atp_disconnect,
+ .suspend = atp_suspend,
+ .resume = atp_resume,
+ .id_table = atp_table,
+};
+
+static int __init atp_init(void)
+{
+ return usb_register(&atp_driver);
+}
+
+static void __exit atp_exit(void)
+{
+ usb_deregister(&atp_driver);
+}
+
+module_init (atp_init);
+module_exit (atp_exit);
--
Stelian Pop <ste...@popies.net>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Nice to see this going into the kernel :)
> This is a driver for the USB touchpad which can be found on
> post-February 2005 Apple PowerBooks (PowerBook5,6).
This is not perfectly correct, the PowerBook5,6 is afaik only the 15"
model, the 12" and 17" have other numbers. Maybe you should just leave
that out, likewise in the code/Kconfig file.
> +/*
> + * number of sensors. Note that only 16 of the 26 x sensors are used on
> + * 12" and 15" Powerbooks.
> + */
I think that is misleading, those sensors don't even exist on 12" and
15" powerbooks. Maybe it should say 'Note that only 16 instead of 26
sensors exist on 12" and 15" models'
johannes
> Hi all,
>
> Nice to see this going into the kernel :)
>
> > This is a driver for the USB touchpad which can be found on
> > post-February 2005 Apple PowerBooks (PowerBook5,6).
>
> This is not perfectly correct, the PowerBook5,6 is afaik only the 15"
> model, the 12" and 17" have other numbers. Maybe you should just leave
> that out, likewise in the code/Kconfig file.
Indeed, corrected.
> > +/*
> > + * number of sensors. Note that only 16 of the 26 x sensors are used on
> > + * 12" and 15" Powerbooks.
> > + */
>
> I think that is misleading, those sensors don't even exist on 12" and
> 15" powerbooks. Maybe it should say 'Note that only 16 instead of 26
> sensors exist on 12" and 15" models'
Sure, I clarified a bit that sentence.
Updated patch follows.
Thanks.
Stelian.
Index: linux-2.6-trunk.git/drivers/usb/input/Makefile
===================================================================
--- linux-2.6-trunk.git.orig/drivers/usb/input/Makefile 2005-06-28 10:25:42.000000000 +0200
+++ linux-2.6-trunk.git/drivers/usb/input/Makefile 2005-07-08 11:10:29.000000000 +0200
@@ -39,3 +39,4 @@
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
obj-$(CONFIG_USB_XPAD) += xpad.o
+obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o
Index: linux-2.6-trunk.git/drivers/usb/input/Kconfig
===================================================================
--- linux-2.6-trunk.git.orig/drivers/usb/input/Kconfig 2005-06-28 10:25:42.000000000 +0200
+++ linux-2.6-trunk.git/drivers/usb/input/Kconfig 2005-07-08 14:05:15.000000000 +0200
@@ -259,3 +259,22 @@
To compile this driver as a module, choose M here: the module will be
called ati_remote.
+config USB_APPLETOUCH
+ tristate "Apple USB Touchpad support"
+ depends on USB && INPUT
+ ---help---
+ Say Y here if you want to use an Apple USB Touchpad.
+
+ These are the touchpads that can be found on post-February 2005
+ Apple Powerbooks (prior models have a Synaptics touchpad connected
+ to the ADB bus).
+++ linux-2.6-trunk.git/drivers/usb/input/appletouch.c 2005-07-08 14:07:41.000000000 +0200
@@ -0,0 +1,516 @@
+/*
+ * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
+/*
+ * number of sensors. Note that only 16 instead of 26 X (horizontal)
+ * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
+ * (vertical) sensors.
+MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
Looks good. If you remove the open counter (the open
callback is called only once for each device), and the
> +module_init (atp_init);
> +module_exit (atp_exit);
spaces here, I think I can merge it.
Btw, what I don't completely understand is why you need linear
regression, when you're not trying to detect motion or something like
that. Basic floating average, or even simpler filtering like the input
core uses for fuzz could work well enough I believe.
--
Vojtech Pavlik
SuSE Labs, SuSE CR
> Btw, what I don't completely understand is why you need linear
> regression, when you're not trying to detect motion or something like
> that. Basic floating average, or even simpler filtering like the input
> core uses for fuzz could work well enough I believe.
Indeed, this function doesn't make much sense:
+static inline int smooth_history(int x0, int x1, int x2, int x3)
+{
+ return x0 - ( x0 * 3 + x1 - x2 - x3 * 3 ) / 10;
+}
In the X driver, a derivative estimate is computed from the last 4
absolute positions, and in that case the least squares estimate is
given by the factors [.3 .1 -.1 -.3]. However, in this case you want
to compute an absolute position estimate from the last 4 absolute
positions, and in this case the least squares estimate is given by the
factors [.25 .25 .25 .25], ie a floating average. If the function is
changed to this:
+static inline int smooth_history(int x0, int x1, int x2, int x3)
+{
+ return (x0 + x1 + x2 + x3) / 4;
+}
the standard deviation of the noise will be reduced by a factor of 2
compared to the unfiltered values. With the old smooth_history()
function, the noise reduction will only be a factor of 1.29.
--
Peter Osterlund - pet...@telia.com
http://web.telia.com/~u89404340
> +Synaptics re-detection problems:
> +--------------------------------
> +
> +The synaptics X11 driver tries to re-open the touchpad input device file
> +(/dev/input/eventX) each time you change from text mode back to X11. If the
> +input device file does not exist at this precise moment, the synaptics driver
> +will give up searching for a touchpad, permanently. You will need to restart
> +X11 if you want to reissue a scan.
I think this particular problem is fixed by the following patch to the
X driver:
--- synaptics.c.old 2005-07-10 00:09:02.000000000 +0200
+++ synaptics.c 2005-07-10 00:09:12.000000000 +0200
@@ -524,6 +524,11 @@
local->fd = xf86OpenSerial(local->options);
if (local->fd == -1) {
+ xf86ReplaceStrOption(local->options, "Device", "");
+ SetDeviceAndProtocol(local);
+ local->fd = xf86OpenSerial(local->options);
+ }
+ if (local->fd == -1) {
xf86Msg(X_WARNING, "%s: cannot open input device\n", local->name);
return !Success;
}
> +static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact) {
I think this CodingStyle violation is quite annoying, because it
prevents emacs from finding the beginning of the function. It should
be written like this:
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact)
{
--
Peter Osterlund - pet...@telia.com
http://web.telia.com/~u89404340
--
Vojtech Pavlik
SuSE Labs, SuSE CR
return (x_old * 3 + x) / 4;
eliminates the need for a FIFO, and has similar (if not better)
properties to floating average, because its coefficients are
[ .25 .18 .14 .10 ... ].
Setting
absfuzz[ABS_X] = some number;
activates the abovementioned filtering (with additional cutoff and fast
motion compensation) directly in input.c, which should eliminate a lot
of the code in the appletouch driver.
--
Vojtech Pavlik
SuSE Labs, SuSE CR
> On Sun, Jul 10, 2005 at 12:48:30AM +0200, Peter Osterlund wrote:
> > Vojtech Pavlik <voj...@suse.cz> writes:
> >
> > > Btw, what I don't completely understand is why you need linear
> > > regression, when you're not trying to detect motion or something like
> > > that. Basic floating average, or even simpler filtering like the input
> > > core uses for fuzz could work well enough I believe.
> >
> > Indeed, this function doesn't make much sense:
> >
> > +static inline int smooth_history(int x0, int x1, int x2, int x3)
> > +{
> > + return x0 - ( x0 * 3 + x1 - x2 - x3 * 3 ) / 10;
> > +}
>
> Using a function like
>
> return (x_old * 3 + x) / 4;
>
> eliminates the need for a FIFO, and has similar (if not better)
> properties to floating average, because its coefficients are
> [ .25 .18 .14 .10 ... ].
Agreed.
> Setting
>
> absfuzz[ABS_X] = some number;
The patch already does that.
> activates the abovementioned filtering (with additional cutoff and fast
> motion compensation) directly in input.c, which should eliminate a lot
> of the code in the appletouch driver.
I took the liberty to modify the patch myself, making these changes:
* Removed the extra filtering.
* Converted the "open" counter to an "open" flag. (It is still needed
by the atp_resume() function.)
* CodingStyle fixes.
I have only compile tested this as I don't have access to the
hardware, so I don't know how well this works in practice. It's
possible that the "dev->h_count > 3" test in the old patch filtered
out spikes in the input signal.
Also, it might be a good idea to compute an ABS_PRESSURE value instead
of hardcoding it to 100. I think the psum variable in
atp_calculate_abs() can be used, possibly after rescaling.
Signed-off-by: Peter Osterlund <pet...@telia.com>
---
Documentation/input/appletouch.txt | 120 +++++++++
drivers/usb/input/Kconfig | 19 +
drivers/usb/input/Makefile | 1
drivers/usb/input/appletouch.c | 461 ++++++++++++++++++++++++++++++++++++
4 files changed, 601 insertions(+), 0 deletions(-)
diff --git a/Documentation/input/appletouch.txt b/Documentation/input/appletouch.txt
new file mode 100644
--- /dev/null
+++ b/Documentation/input/appletouch.txt
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -259,3 +259,22 @@ config USB_ATI_REMOTE
To compile this driver as a module, choose M here: the module will be
called ati_remote.
+config USB_APPLETOUCH
+ tristate "Apple USB Touchpad support"
+ depends on USB && INPUT
+ ---help---
+ Say Y here if you want to use an Apple USB Touchpad.
+
+ These are the touchpads that can be found on post-February 2005
+ Apple Powerbooks (prior models have a Synaptics touchpad connected
+ to the ADB bus).
+
+ This driver provides a basic mouse driver but can be interfaced
+ with the synaptics X11 driver to provide acceleration and
+ scrolling in X11.
+
+ For further information, see
+ <file:Documentation/input/appletouch.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called appletouch.
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -39,3 +39,4 @@ obj-$(CONFIG_USB_POWERMATE) += powermate
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
obj-$(CONFIG_USB_XPAD) += xpad.o
+obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
new file mode 100644
--- /dev/null
+++ b/drivers/usb/input/appletouch.c
@@ -0,0 +1,461 @@
+/*
+/* Structure to hold all of our device specific stuff */
+struct atp {
+ struct usb_device * udev; /* usb device */
+ struct urb * urb; /* usb request block */
+ signed char * data; /* transferred data */
+ int open; /* non-zero if opened */
+ struct input_dev input; /* input dev */
+static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact)
+{
+{
+ if (debug > 1)
+ printk("appletouch: Xhw: %3d Yhw: %3d "
+ "Xsm: %3d Ysm: %3d\n",
+ x_hw, y_hw, x_hw, y_hw);
+
+ input_report_key(&dev->input, BTN_TOUCH, 1);
+ input_report_abs(&dev->input, ABS_X, x_hw);
+ input_report_abs(&dev->input, ABS_Y, y_hw);
+ input_report_abs(&dev->input, ABS_PRESSURE, 100);
+ input_report_key(&dev->input, BTN_TOOL_FINGER, 1);
+ } else if (!x_hw && !y_hw) {
+ input_report_key(&dev->input, BTN_TOUCH, 0);
+ input_report_abs(&dev->input, ABS_PRESSURE, 0);
+ input_report_key(&dev->input, BTN_TOOL_FINGER, 0);
+
+ /* reset the accumulator on release */
+ memset(xy_acc, 0, sizeof(xy_acc));
+ }
+
+ input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);
+
+ input_sync(&dev->input);
+
+exit:
+ retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+ if (retval) {
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, retval);
+ }
+}
+
+static int atp_open(struct input_dev *input)
+{
+ struct atp *dev = input->private;
+
+ if (usb_submit_urb(dev->urb, GFP_ATOMIC))
+ return -EIO;
+
+ dev->open = 1;
+ return 0;
+}
+
+static void atp_close(struct input_dev *input)
+{
+ struct atp *dev = input->private;
+
+ usb_kill_urb(dev->urb);
+ dev->open = 0;
+}
+
+ usb_kill_urb(dev->urb);
+ valid = 0;
+ return 0;
+}
+
+static int atp_resume(struct usb_interface *iface)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+ if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
+ return -EIO;
--
Peter Osterlund - pet...@telia.com
http://web.telia.com/~u89404340
It does indeed fix the problem.
I removed that section from the documentation, as I assume you will
integrate this patch in future synaptics releases (and it wasn't anyway
a big problem for users, just for developers).
>
> > +static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact) {
>
> I think this CodingStyle violation is quite annoying, because it
> prevents emacs from finding the beginning of the function. It should
> be written like this:
Indeed, that one slipped over, but this didn't prevent vim from finding
the beginning of the function :)
Thanks,
Stelian.
--
Stelian Pop <ste...@popies.net>
> I took the liberty to modify the patch myself, making these changes:
>
> * Removed the extra filtering.
> * Converted the "open" counter to an "open" flag. (It is still needed
> by the atp_resume() function.)
> * CodingStyle fixes.
>
> I have only compile tested this as I don't have access to the
> hardware, so I don't know how well this works in practice. It's
> possible that the "dev->h_count > 3" test in the old patch filtered
> out spikes in the input signal.
>
> Also, it might be a good idea to compute an ABS_PRESSURE value instead
> of hardcoding it to 100. I think the psum variable in
> atp_calculate_abs() can be used, possibly after rescaling.
Stelian, can you check the patch, and if everything is OK, add your
Signed-off-by: line?
> Signed-off-by: Peter Osterlund <pet...@telia.com>
> ---
>
> Documentation/input/appletouch.txt | 120 +++++++++
> drivers/usb/input/Kconfig | 19 +
> drivers/usb/input/Makefile | 1
> drivers/usb/input/appletouch.c | 461 ++++++++++++++++++++++++++++++++++++
> 4 files changed, 601 insertions(+), 0 deletions(-)
--
Vojtech Pavlik
SuSE Labs, SuSE CR
> +static inline int smooth_history(int x0, int x1, int x2, int x3)
> +{
> + return (x0 + x1 + x2 + x3) / 4;
> +}
I took Peter's approach here and changed the smoothing to use basic
floating average as above.
> > Using a function like
> >
> > return (x_old * 3 + x) / 4;
> >
> > eliminates the need for a FIFO, and has similar (if not better)
> > properties to floating average, because its coefficients are
> > [ .25 .18 .14 .10 ... ].
>
> Agreed.
Except that this does not work well enough.
There are two problems I encountered in this driver:
* fuzz problems (keeping the finger at the same place makes the pointer
dance around its position). This is solved by the input core's fuzz
treatment, as I already set the fuzz to 16 in the code.
* hickup problems (moving the finger generates non linear points,
something like 1 1 1 3 3 3 4 4 4 instead of 1 1 1 2 2 3 3 4 4). And here
the floating average approach works better than the input core's method.
(this could probably be solved also by changing the way the absolute
coordinate is calculated from the sensor array in atp_calculate_abs, but
I haven't been able to find a better linear function).
> I took the liberty to modify the patch myself, making these changes:
>
> * Removed the extra filtering.
> * Converted the "open" counter to an "open" flag. (It is still needed
> by the atp_resume() function.)
> * CodingStyle fixes.
>
> I have only compile tested this as I don't have access to the
> hardware, so I don't know how well this works in practice. It's
> possible that the "dev->h_count > 3" test in the old patch filtered
> out spikes in the input signal.
I would prefer to submit the patch myself, because as you say you cannot
test the code and those changes are rather sensitive. Without the
smoothing function, the driver is almost unusable when used without the
synaptics driver (as a standard mouse), positionning the pointer at
exact locations is quite difficult.
> Also, it might be a good idea to compute an ABS_PRESSURE value instead
> of hardcoding it to 100. I think the psum variable in
> atp_calculate_abs() can be used, possibly after rescaling.
I already thought about this, one problem is that the sensors do not
report the pressure but only the amount of surface touched. A person
with thick fingers will always generate higher pressures then one with
thin ones, no matter how hard they push on the touchpad.
I don't think this value is reliable enough to be reported to the
userspace as ABS_PRESSURE...
Anyway, here is the updated patch:
Signed-off-by: Stelian Pop <ste...@popies.net>
Documentation/input/appletouch.txt | 83 ++++++
drivers/usb/input/Kconfig | 19 +
drivers/usb/input/Makefile | 1
drivers/usb/input/appletouch.c | 509
+++++++++++++++++++++++++++++++++++++
4 files changed, 612 insertions(+)
Index: linux-2.6.git/drivers/usb/input/Makefile
===================================================================
--- linux-2.6.git.orig/drivers/usb/input/Makefile 2005-07-11
09:46:57.000000000 +0200
+++ linux-2.6.git/drivers/usb/input/Makefile 2005-07-11
09:48:23.000000000 +0200
@@ -39,3 +39,4 @@
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
obj-$(CONFIG_USB_XPAD) += xpad.o
+obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o
Index: linux-2.6.git/drivers/usb/input/Kconfig
===================================================================
--- linux-2.6.git.orig/drivers/usb/input/Kconfig 2005-07-11
09:46:57.000000000 +0200
+++ linux-2.6.git/drivers/usb/input/Kconfig 2005-07-11
09:48:23.000000000 +0200
@@ -259,3 +259,22 @@
To compile this driver as a module, choose M here: the module will
be
called ati_remote.
+config USB_APPLETOUCH
+ tristate "Apple USB Touchpad support"
+ depends on USB && INPUT
+ ---help---
+ Say Y here if you want to use an Apple USB Touchpad.
+
+ These are the touchpads that can be found on post-February 2005
+ Apple Powerbooks (prior models have a Synaptics touchpad connected
+ to the ADB bus).
+
+ This driver provides a basic mouse driver but can be interfaced
+ with the synaptics X11 driver to provide acceleration and
+ scrolling in X11.
+
+ For further information, see
+ <file:Documentation/input/appletouch.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called appletouch.
Index: linux-2.6.git/Documentation/input/appletouch.txt
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.git/Documentation/input/appletouch.txt 2005-07-11
11:57:41.000000000 +0200
@@ -0,0 +1,83 @@
+Links:
+------
+
+[1]: http://johannes.sipsolutions.net/PowerBook/touchpad/
+[2]: http://web.telia.com/~u89404340/touchpad/index.html
Index: linux-2.6.git/drivers/usb/input/appletouch.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.git/drivers/usb/input/appletouch.c 2005-07-11
11:48:25.000000000 +0200
@@ -0,0 +1,509 @@
+ * Size of the history for smoothing.
+ */
+#define ATP_HSIZE 5
+
+struct point {
+ unsigned int x;
+ unsigned int y;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct atp {
+ struct usb_device * udev; /* usb device */
+ struct urb * urb; /* usb request block */
+ signed char * data; /* transferred data */
+ int open; /* non-zero if opened */
+ struct input_dev input; /* input dev */
+ int h_count; /* history for smoothing */
+ struct point h[ATP_HSIZE];
+ unsigned int h_index;
+/*
+ * Smooth the data sequence by estimating the slope for the data
sequence
+ * [x3, x2, x1, x0] by using linear regression to fit a line to the
data and
+ * use the slope of the line. Taken from the synaptics X driver.
+ */
+
+#define HIST(a) (dev->h[((dev->h_index - (a) + ATP_HSIZE) %
ATP_HSIZE)])
+
+static inline void store_history(struct atp *atp, int x, int y)
+{
+ atp->h_index = (atp->h_index + 1) % ATP_HSIZE;
+ atp->h[atp->h_index].x = x;
+ atp->h[atp->h_index].y = y;
+ atp->h_count++;
+}
+
+static inline int smooth_history(int x0, int x1, int x2, int x3)
+{
+ return (x0 + x1 + x2 + x3 ) / 4;
+}
+ dev->h_count = 0;
+ /* need at least 3 points to smooth */
+ if (dev->h_count > 3) {
+ unsigned int x_sm, y_sm;
+ x_sm = smooth_history(x_hw, HIST(0).x,
+ HIST(1).x, HIST(2).x);
+ y_sm = smooth_history(y_hw, HIST(0).y,
+ HIST(1).y, HIST(2).y);
+
+ if (debug > 1)
+ printk("appletouch: Xhw: %3d Yhw: %3d "
+ "Xsm: %3d Ysm: %3d\n",
+ x_hw, y_hw, x_sm, y_sm);
+
+ input_report_key(&dev->input, BTN_TOUCH, 1);
+ input_report_abs(&dev->input, ABS_X, x_sm);
+ input_report_abs(&dev->input, ABS_Y, y_sm);
+ input_report_abs(&dev->input, ABS_PRESSURE, 100);
+ input_report_key(&dev->input, BTN_TOOL_FINGER, 1);
+ }
+ store_history(dev, x_hw, y_hw);
+ }
+ else if (!x_hw && !y_hw) {
+
+ dev->h_count = 0;
--
Stelian Pop <ste...@popies.net>
Oops, bad Evolution (even if I did use insert->text file for the patch).
Going back to mutt. Sorry about this.
Changelog:
* CodingStyle fixes
* open counter replaced by a binary flag
* udev hacks are no longer necessary with a patched
synaptics, update the documentation
I guess the quick motion compensation in input bites you. The above
equation should do even more smoothing than regular 4-point floating
average.
> There are two problems I encountered in this driver:
> * fuzz problems (keeping the finger at the same place makes the pointer
> dance around its position). This is solved by the input core's fuzz
> treatment, as I already set the fuzz to 16 in the code.
OK.
> * hickup problems (moving the finger generates non linear points,
> something like 1 1 1 3 3 3 4 4 4 instead of 1 1 1 2 2 3 3 4 4). And here
> the floating average approach works better than the input core's method.
> (this could probably be solved also by changing the way the absolute
> coordinate is calculated from the sensor array in atp_calculate_abs, but
> I haven't been able to find a better linear function).
I of course won't object to the floating average in the driver if you
say it's needed, I'm just wondering what happens here, because the input
core should smooth this out as well, and if it doesn't, there may be a
problem somewhere.
> > Also, it might be a good idea to compute an ABS_PRESSURE value instead
> > of hardcoding it to 100. I think the psum variable in
> > atp_calculate_abs() can be used, possibly after rescaling.
>
> I already thought about this, one problem is that the sensors do not
> report the pressure but only the amount of surface touched. A person
> with thick fingers will always generate higher pressures then one with
> thin ones, no matter how hard they push on the touchpad.
That's what all other touchpads do.
> I don't think this value is reliable enough to be reported to the
> userspace as ABS_PRESSURE...
I believe it'd still be more useful than a two-value (0 and 100) output.
> + /*
> + * in the future, we could add here code to search for
> + * a second finger...
> + * for now, scrolling using the synaptics X driver is
> + * much more simpler to achieve.
> + */
This could be quite useful, too, for right and middle button taps (2 and
3 fingers) - since the Macs lack these buttons.
--
Vojtech Pavlik
SuSE Labs, SuSE CR
Possible. The 'fuzz' parameter in input core serves too many usages
ihmo. Let me try removing the quick motion compensation and see...
> > I already thought about this, one problem is that the sensors do not
> > report the pressure but only the amount of surface touched. A person
> > with thick fingers will always generate higher pressures then one with
> > thin ones, no matter how hard they push on the touchpad.
>
> That's what all other touchpads do.
I thought the hardware is capable of calculating real pressure...
> > I don't think this value is reliable enough to be reported to the
> > userspace as ABS_PRESSURE...
>
> I believe it'd still be more useful than a two-value (0 and 100) output.
Ok, I'll do it.
> > + /*
> > + * in the future, we could add here code to search for
> > + * a second finger...
> > + * for now, scrolling using the synaptics X driver is
> > + * much more simpler to achieve.
> > + */
>
> This could be quite useful, too, for right and middle button taps (2 and
> 3 fingers) - since the Macs lack these buttons.
Indeed. But this can be a later improvement, let's make one finger work
for now :)
Stelian.
--
Stelian Pop <ste...@popies.net>
-
> Possible. The 'fuzz' parameter in input core serves too many usages
> ihmo. Let me try removing the quick motion compensation and see...
It was designed for joysticks and works very well for them. Usefulness
for other device types may vary. And I'll gladly accept patches to
improve it.
> > > I already thought about this, one problem is that the sensors do not
> > > report the pressure but only the amount of surface touched. A person
> > > with thick fingers will always generate higher pressures then one with
> > > thin ones, no matter how hard they push on the touchpad.
> >
> > That's what all other touchpads do.
>
> I thought the hardware is capable of calculating real pressure...
Since the sensor is just a multi-layer PCB with a clever trace layout,
it can't.
> > > I don't think this value is reliable enough to be reported to the
> > > userspace as ABS_PRESSURE...
> >
> > I believe it'd still be more useful than a two-value (0 and 100) output.
>
> Ok, I'll do it.
Thanks. Should I wait for that or apply the patch you just sent?
> > This could be quite useful, too, for right and middle button taps (2 and
> > 3 fingers) - since the Macs lack these buttons.
>
> Indeed. But this can be a later improvement, let's make one finger work
> for now :)
Agreed.
--
Vojtech Pavlik
SuSE Labs, SuSE CR
Ok, I understand now what is happenning, but I'm not sure how to solve
the problem. As I suspected, it is caused by 'fuzz' being a bit abused
by the input core.
The fuzz parameter in the input core is used today to say:
* any change in the -fuzz/2 / +fuzz/2 range is ignored
* any change in the -fuzz / +fuzz range is smoothed using x_old * 3 +
x) / 4;
* any change in the -fuzz*2 / +fuzz/2 range is smoothed using x_old
+x) / 2;
My driver needs to ignore changes in the -8 / +8 range (that's why I set
FUZZ to 16 in the first place), but it needs to smooth the movement when
much larger changes occur (I would need to set FUZZ to 64 for smoothing
to work correctly here).
How to make it work ? Obviously I could implement either fuzz
elimination or smoothing in the driver, and leave the other
transformation to the input core (today it is the smoothing which is in
the driver, but doing it the other way around would result in much less
code).
The other (proper ?) solution would be to change the input core and
separate fuzz and smoothing. This would however require an API addition,
and I'm not sure you want to do that. If you do, I could work on a patch
implementing an inputdev->abssmooth[] table, etc).
> > I thought the hardware is capable of calculating real pressure...
>
> Since the sensor is just a multi-layer PCB with a clever trace layout,
> it can't.
>
> > > > I don't think this value is reliable enough to be reported to the
> > > > userspace as ABS_PRESSURE...
> > >
> > > I believe it'd still be more useful than a two-value (0 and 100) output.
> >
> > Ok, I'll do it.
>
> Thanks. Should I wait for that or apply the patch you just sent?
Well, it depends on what we do with smoothing.
Stelian.
--
Stelian Pop <ste...@popies.net>
-
> How to make it work ? Obviously I could implement either fuzz
> elimination or smoothing in the driver, and leave the other
> transformation to the input core (today it is the smoothing which is in
> the driver, but doing it the other way around would result in much less
> code).
And of course it cannot be done without modifying input core in order to
prevent it throwing away the samples. The only way to manage the current
situation is to implement smoothing in the driver itself (but I used the
same algorithm as in the input core, thus removing the unneeded history)
> > > > > I don't think this value is reliable enough to be reported to the
> > > > > userspace as ABS_PRESSURE...
> > > >
> > > > I believe it'd still be more useful than a two-value (0 and 100) output.
> > >
> > > Ok, I'll do it.
Implemented too.
Here is the latest incarnation of the patch, please apply this one.
If Vojtech decides that it makes sense to modify the input core in order
to separate fuzz and smoothing, then the driver could be simplified a
bit more.
Thanks,
Stelian.
Changes:
* report ABS_PRESSURE events
* simplify smoothing by using the same technique as the input
core eliminating the need for a FIFO.
Signed-off-by: Stelian Pop <ste...@popies.net>
Documentation/input/appletouch.txt | 83 ++++++
drivers/usb/input/Kconfig | 19 +
drivers/usb/input/Makefile | 1
drivers/usb/input/appletouch.c | 480 +++++++++++++++++++++++++++++++++++++
4 files changed, 583 insertions(+)
+++ linux-2.6.git/Documentation/input/appletouch.txt 2005-07-11 15:02:51.000000000 +0200
+ Option "FingerLow" "0"
+ Option "FingerHigh" "30"
+++ linux-2.6.git/drivers/usb/input/appletouch.c 2005-07-11 15:18:29.000000000 +0200
@@ -0,0 +1,480 @@
+/* maximum pressure this driver will report */
+#define ATP_PRESSURE 300
+/*
+ * multiplication factor for the X and Y coordinates.
+ * We try to keep the touchpad aspect ratio while still doing only simple
+ * arithmetics.
+ * The factors below give coordinates like:
+ * 0 <= x < 960 on 12" and 15" Powerbooks
+ * 0 <= x < 1600 on 17" Powerbooks
+ * 0 <= y < 646
+ */
+#define ATP_XFACT 64
+#define ATP_YFACT 43
+
+/*
+ * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
+ * ignored.
+ */
+#define ATP_THRESHOLD 4
+
+/* Structure to hold all of our device specific stuff */
+struct atp {
+ struct usb_device * udev; /* usb device */
+ struct urb * urb; /* usb request block */
+ signed char * data; /* transferred data */
+ int open; /* non-zero if opened */
+ struct input_dev input; /* input dev */
+static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, int *z)
+{
+ int i;
+ /* values to calculate mean */
+ int pcum = 0, psum = 0;
+ /* indexes of the first and last triggered sensors */
+ int istart = -1, iend = -1;
+
+ for (i = 0; i < nb_sensors; i++) {
+ if (xy_sensors[i] > ATP_THRESHOLD && istart == -1)
+ istart = i;
+ if (xy_sensors[i] < ATP_THRESHOLD && istart != -1 && iend == -1)
+ iend = i;
+ if (xy_sensors[i] > ATP_THRESHOLD && iend != -1) {
+ /*
+ * in the future, we could add here code to search for
+ * a second finger...
+ * for now, scrolling using the synaptics X driver is
+ * much more simpler to achieve.
+ */
+ dprintk("appletouch: invalid sensor at %d"
+ " (2 fingers ?)\n", i);
+ return -1;
+ }
+ }
+
+ if (istart == -1)
+ return 0;
+
+ if (iend == -1)
+ iend = nb_sensors;
+
+ for (i = istart; i < iend; i++) {
+ pcum += xy_sensors[i] * i;
+ psum += xy_sensors[i];
+ }
+
+ *z = psum;
+
+ return pcum * fact / psum;
+}
+
+static void atp_complete(struct urb* urb, struct pt_regs* regs)
+{
+ static int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+ static signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
+ static signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
+ static int x_old, y_old;
+ int x, y, x_z, y_z;
+ int retval, i;
+ x_old = y_old = -1;
+ memcpy(xy_old, xy_cur, sizeof(xy_old));
+ goto exit;
+ }
+
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+ /* accumulate the change */
+ signed char change = xy_old[i] - xy_cur[i];
+ xy_acc[i] -= change;
+
+ /* prevent down drifting */
+ if (xy_acc[i] < 0)
+ xy_acc[i] = 0;
+ }
+
+ memcpy(xy_old, xy_cur, sizeof(xy_old));
+
+ dbg_dump("accumulator", xy_acc);
+
+ x = atp_calculate_abs(xy_acc, ATP_XSENSORS, ATP_XFACT,
+ &x_z);
+ y = atp_calculate_abs(xy_acc + ATP_XSENSORS, ATP_YSENSORS, ATP_YFACT,
+ &y_z);
+
+ if (x < 0 || y < 0) {
+ memset(xy_acc, 0, sizeof(xy_acc));
+ goto exit;
+ }
+
+ if (x && y) {
+ if (x_old != -1) {
+ x = (x_old * 3 + x) >> 2;
+ y = (y_old * 3 + y) >> 2;
+ x_old = x;
+ y_old = y;
+
+ if (debug > 1)
+ printk("appletouch: X: %3d Y: %3d "
+ "Xz: %3d Yz: %3d\n",
+ x, y, x_z, y_z);
+
+ input_report_key(&dev->input, BTN_TOUCH, 1);
+ input_report_abs(&dev->input, ABS_X, x);
+ input_report_abs(&dev->input, ABS_Y, y);
+ input_report_abs(&dev->input, ABS_PRESSURE,
+ min(ATP_PRESSURE, x_z + y_z));
+ input_report_key(&dev->input, BTN_TOOL_FINGER, 1);
+ }
+ x_old = x;
+ y_old = y;
+ }
+ else if (!x && !y) {
+
+ x_old = y_old = -1;
+ input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
--
> +/*
> + * Smooth the data sequence by estimating the slope for the data sequence
> + * [x3, x2, x1, x0] by using linear regression to fit a line to the data and
> + * use the slope of the line. Taken from the synaptics X driver.
> + */
This comment is not correct now that the code uses floating average
instead. Maybe just remove it. The floating average calculation is
much more obvious than the linear regression stuff.
--
Peter Osterlund - pet...@telia.com
http://web.telia.com/~u89404340
> Le lundi 11 juillet 2005 à 02:15 +0200, Peter Osterlund a écrit :
> > Vojtech Pavlik <voj...@suse.cz> writes:
> >
> > > Using a function like
> > >
> > > return (x_old * 3 + x) / 4;
> > >
> > > eliminates the need for a FIFO, and has similar (if not better)
> > > properties to floating average, because its coefficients are
> > > [ .25 .18 .14 .10 ... ].
> >
> > Agreed.
>
> Except that this does not work well enough.
>
> There are two problems I encountered in this driver:
> * fuzz problems (keeping the finger at the same place makes the pointer
> dance around its position). This is solved by the input core's fuzz
> treatment, as I already set the fuzz to 16 in the code.
>
> * hickup problems (moving the finger generates non linear points,
> something like 1 1 1 3 3 3 4 4 4 instead of 1 1 1 2 2 3 3 4 4). And here
> the floating average approach works better than the input core's method.
> (this could probably be solved also by changing the way the absolute
> coordinate is calculated from the sensor array in atp_calculate_abs, but
> I haven't been able to find a better linear function).
It would be interesting if you could generate some debug dumps using
the "sample" line:
+ dbg_dump("sample", xy_cur);
The "accumulator" dumps are not needed, the raw data should be
enough. Including timing information would be helpful though, like
this:
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -121,7 +121,7 @@ struct atp {
#define dbg_dump(msg, tab) \
if (debug > 1) { \
int i; \
- printk("appletouch: %s ", msg); \
+ printk("appletouch: %s %lld ", msg, (long long)jiffies);\
for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
printk("%02x ", tab[i]); \
printk("\n"); \
Debug dumps for the following actions would be interesting.
1. When not touching the touchpad.
2. When trying to hold a finger on the touchpad without moving it.
3. A single finger movement. (Touch, move finger, release.)
4. A single finger touch. First a light touch, then pressing harder
and harder, to see if a reliable pressure value can be computed
from the data.
5. A two-finger touch.
> I would prefer to submit the patch myself, because as you say you cannot
> test the code and those changes are rather sensitive.
No problem, I just needed a patch when I was playing around with StGIT
and thought I might as well use a real patch.
--
Peter Osterlund - pet...@telia.com
http://web.telia.com/~u89404340
There's no need to go back to mutt, Evolution is not broken. Before
doing 'Insert->Text File', you just have to change the text style at the
insertion point from 'Normal' to 'Preformat' to avoid word-wrapping the
patch.
Lee
Indeed, Alexander Nyberg already pointed this to me in private.
Thanks.
Stelian.
--
Stelian Pop <ste...@popies.net>
-
> > > This could be quite useful, too, for right and middle button taps (2 and
> > > 3 fingers) - since the Macs lack these buttons.
> >
> > Indeed. But this can be a later improvement, let's make one finger work
> > for now :)
Thanks to Peter Osterlund, I now have 2 and 3 finger tap working.
Please apply the attached patch.
Thanks,
Stelian.
Changes:
* implement detection of 2 and 3 finger tap (thanks to Peter Osterlund)
* moved the static variables into the atp device structure
* print the timestamp in debug messages
Signed-off-by: Stelian Pop <ste...@popies.net>
Documentation/input/appletouch.txt | 84 ++++++
drivers/usb/input/Kconfig | 19 +
drivers/usb/input/Makefile | 1
drivers/usb/input/appletouch.c | 471 +++++++++++++++++++++++++++++++++++++
4 files changed, 575 insertions(+)
Index: linux-2.6.git/drivers/usb/input/Makefile
===================================================================
--- linux-2.6.git.orig/drivers/usb/input/Makefile 2005-07-12 09:47:53.000000000 +0200
+++ linux-2.6.git/drivers/usb/input/Makefile 2005-07-12 09:49:17.000000000 +0200
@@ -39,3 +39,4 @@
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
obj-$(CONFIG_USB_XPAD) += xpad.o
+obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o
Index: linux-2.6.git/drivers/usb/input/Kconfig
===================================================================
--- linux-2.6.git.orig/drivers/usb/input/Kconfig 2005-07-12 09:47:53.000000000 +0200
+++ linux-2.6.git/drivers/usb/input/Kconfig 2005-07-12 09:49:17.000000000 +0200
+++ linux-2.6.git/Documentation/input/appletouch.txt 2005-07-12 10:22:23.000000000 +0200
@@ -0,0 +1,84 @@
+will give additional functionalities, like acceleration, scrolling, 2 finger
+tap for middle button mouse emulation, 3 finger tap for right button mouse
+emulation, etc. In order to do this, make sure you're using a recent version of
+the synaptics driver (tested with 0.14.2, available from [2]), and configure a
+new input device in your X11 configuration file (take a look below for an
+example). For additional configuration, see the synaptics driver documentation.
+
+ Section "InputDevice"
+ Identifier "Synaptics Touchpad"
+ Driver "synaptics"
+ Option "SendCoreEvents" "true"
+ Option "Device" "/dev/input/mice"
+ Option "Protocol" "auto-dev"
+ Option "LeftEdge" "0"
+ Option "RightEdge" "850"
+ Option "TopEdge" "0"
+ Option "BottomEdge" "645"
+ Option "MinSpeed" "0.4"
+ Option "MaxSpeed" "1"
+ Option "AccelFactor" "0.02"
+ Option "FingerLow" "0"
+ Option "FingerHigh" "30"
+++ linux-2.6.git/drivers/usb/input/appletouch.c 2005-07-12 10:44:56.000000000 +0200
@@ -0,0 +1,471 @@
+/*
+ * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (gr...@kroah.com)
+ * Copyright (C) 2005 Johannes Berg (joha...@sipsolutions.net)
+ * Copyright (C) 2005 Stelian Pop (ste...@popies.net)
+ * Copyright (C) 2005 Frank Arnold (fr...@scirocco-5v-turbo.de)
+ * Copyright (C) 2005 Peter Osterlund (pet...@telia.com)
+#define ATP_DRIVER_VERSION 0x0007 /* 00.07 */
+/* maximum pressure this driver will report */
+#define ATP_PRESSURE 300
+/*
+ * multiplication factor for the X and Y coordinates.
+ * We try to keep the touchpad aspect ratio while still doing only simple
+ * arithmetics.
+ * The factors below give coordinates like:
+ * 0 <= x < 960 on 12" and 15" Powerbooks
+ * 0 <= x < 1600 on 17" Powerbooks
+ * 0 <= y < 646
+ */
+#define ATP_XFACT 64
+#define ATP_YFACT 43
+
+/*
+ * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
+ * ignored.
+ */
+#define ATP_THRESHOLD 5
+
+/* Structure to hold all of our device specific stuff */
+struct atp {
+ struct usb_device * udev; /* usb device */
+ struct urb * urb; /* usb request block */
+ signed char * 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];
+ /* last value of the sensors */
+ signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
+ /* accumulated sensors */
+ int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+};
+
+#define dbg_dump(msg, tab) \
+ if (debug > 1) { \
+ int i; \
+ printk("appletouch: %s %lld", msg, (long long)jiffies); \
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
+ printk("%02x ", tab[i]); \
+ printk("\n"); \
+ }
+
+#define dprintk(format, a...) \
+ do { \
+ if (debug) printk(format, ##a); \
+ } while (0)
+
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
+MODULE_LICENSE("GPL");
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activate debugging output");
+
+static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
+ int *z, int *fingers)
+{
+ int i;
+ /* values to calculate mean */
+ int pcum = 0, psum = 0;
+
+ *fingers = 0;
+
+ for (i = 0; i < nb_sensors; i++) {
+ if (xy_sensors[i] < ATP_THRESHOLD)
+ continue;
+ if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
+ (*fingers)++;
+ pcum += xy_sensors[i] * i;
+ psum += xy_sensors[i];
+ }
+
+ if (psum > 0) {
+ *z = psum;
+ return pcum * fact / psum;
+ }
+
+ return 0;
+}
+
+static inline void atp_report_fingers(struct input_dev *input, int fingers)
+{
+ input_report_key(input, BTN_TOOL_FINGER, fingers == 1);
+ input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);
+ input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
+}
+
+static void atp_complete(struct urb* urb, struct pt_regs* regs)
+{
+ int x, y, x_z, y_z, x_f, y_f;
+ int retval, i;
+ dev->xy_cur[i ] = dev->data[5 * i + 2];
+ dev->xy_cur[i + 8] = dev->data[5 * i + 4];
+ dev->xy_cur[i + 16] = dev->data[5 * i + 42];
+ if (i < 2)
+ dev->xy_cur[i + 24] = dev->data[5 * i + 44];
+
+ /* Y values */
+ dev->xy_cur[i + 26] = dev->data[5 * i + 1];
+ dev->xy_cur[i + 34] = dev->data[5 * i + 3];
+ }
+
+ dbg_dump("sample", dev->xy_cur);
+
+ if (!dev->valid) {
+ /* first sample */
+ dev->valid = 1;
+ dev->x_old = dev->y_old = -1;
+ 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;
+
+ /* 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,
+ ATP_XFACT, &x_z, &x_f);
+ y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
+ ATP_YFACT, &y_z, &y_f);
+
+ if (x && y) {
+ if (dev->x_old != -1) {
+ x = (dev->x_old * 3 + x) >> 2;
+ y = (dev->y_old * 3 + y) >> 2;
+ dev->x_old = x;
+ dev->y_old = y;
+
+ if (debug > 1)
+ printk("appletouch: X: %3d Y: %3d "
+ "Xz: %3d Yz: %3d\n",
+ x, y, x_z, y_z);
+
+ input_report_key(&dev->input, BTN_TOUCH, 1);
+ input_report_abs(&dev->input, ABS_X, x);
+ input_report_abs(&dev->input, ABS_Y, y);
+ input_report_abs(&dev->input, ABS_PRESSURE,
+ min(ATP_PRESSURE, x_z + y_z));
+ atp_report_fingers(&dev->input, max(x_f, y_f));
+ }
+ dev->x_old = x;
+ dev->y_old = y;
+ }
+ else if (!x && !y) {
+
+ dev->x_old = dev->y_old = -1;
+ input_report_key(&dev->input, BTN_TOUCH, 0);
+ input_report_abs(&dev->input, ABS_PRESSURE, 0);
+ atp_report_fingers(&dev->input, 0);
+
+ /* reset the accumulator on release */
+ memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+ input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
+
+ set_bit(EV_KEY, dev->input.evbit);
+ set_bit(BTN_TOUCH, dev->input.keybit);
+ set_bit(BTN_TOOL_FINGER, dev->input.keybit);
+ set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit);
+ set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit);
+ dev->valid = 0;
--
Stelian Pop <ste...@popies.net>
-
On 7/12/05, Stelian Pop <ste...@popies.net> wrote:
>
> + dev->input.id.bustype = BUS_USB;
> + dev->input.id.vendor = id->idVendor;
> + dev->input.id.product = id->idProduct;
> + dev->input.id.version = ATP_DRIVER_VERSION;
> +
Why don't we do what most of the other input devices and get version
from the device too? Actually we have this in input tree:
static inline void
usb_to_input_id(const struct usb_device *dev, struct input_id *id)
{
id->bustype = BUS_USB;
id->vendor = le16_to_cpu(dev->descriptor.idVendor);
id->product = le16_to_cpu(dev->descriptor.idProduct);
id->version = le16_to_cpu(dev->descriptor.bcdDevice);
}
--
Dmitry
I guess we could, there is not much use for a local driver version
anyway.
> Actually we have this in input tree:
>
> static inline void
> usb_to_input_id(const struct usb_device *dev, struct input_id *id)
This cleans up a lot of code indeed. Too bad this is not upstream yet...
Stelian.
--
Stelian Pop <ste...@popies.net>
-
It is in -mm (it is coming from git-input patch).
--
Dmitry
--
Vojtech Pavlik
SuSE Labs, SuSE CR
> Stelian, can you please update the patch to use usb_to_input_id()? It'll
> go through -mm first, anyway, so there shouldn't be any issue with
> Linus's kernels not having that function yet.
Sure, here it comes.
Stelian.
Changes:
* removed local version number
* use usb_to_input_id() instead of manually setting the fields
Signed-off-by: Stelian Pop <ste...@popies.net>
Documentation/input/appletouch.txt | 84 ++++++
drivers/usb/input/Kconfig | 19 +
drivers/usb/input/Makefile | 1
drivers/usb/input/appletouch.c | 467 +++++++++++++++++++++++++++++++++++++
4 files changed, 571 insertions(+)
+++ linux-2.6.git/drivers/usb/input/appletouch.c 2005-07-12 21:15:25.000000000 +0200
@@ -0,0 +1,467 @@
+#include <linux/usb_input.h>
+
+/* Apple has powerbooks which have the keyboard with different Product IDs */
+#define APPLE_VENDOR_ID 0x05AC
+#define ATP_12INCH_ID1 0x030A
+#define ATP_15INCH_ID1 0x020E
+#define ATP_15INCH_ID2 0x020F
+#define ATP_17INCH_ID1 0xFFFF /* XXX need a tester !!! */
+
+ usb_to_input_id(dev->udev, &dev->input.id);
--
Stelian Pop <ste...@popies.net>
-