* Re: PowerBook5,8 - TrackPad update
       [not found] <111520052143.16540.437A5680000BE8A60000409C220076369200009A9B9CD3040A029D0A05@comcast.net>
@ 2005-11-21 23:57 ` Parag Warudkar
  2005-11-22  0:08   ` Parag Warudkar
                     ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Parag Warudkar @ 2005-11-21 23:57 UTC (permalink / raw)
  To: Parag Warudkar; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1833 bytes --]
On Nov 15, 2005, at 4:43 PM, Parag Warudkar wrote:
> Just a heads up - After some lame hacking I finally have got the  
> trackpad on the PB5,8  (15" Late Oct 2005) to work.
>
> Ok, here is the current definition of working - mouse moves but for  
> that you have to roll over on the trackpad ;)!
>
> Currently negotiating with it so that it's happy with the fingers!! :D
>
> Will post the modified source once for appletouch once it starts  
> working acceptably.
>
Ok, the format interpretation of the trackpad data is taking up more  
of my time and brain than I was happy with! :)
If someone wants to take this up, here is something small to begin  
with -
So far the three simple changes that are required for the original  
appletouch.c in order to get it to produce _some_ wayward mouse  
movements and reliable button clicks at the least are
1) #define ATP_DATASIZE 81 - This needs to be made a module parameter  
and if not specified should be detected and set in code - to 81 if  
the machine_is_compatible() with the older powerbooks and 256 if the  
machine_is_compatible() with newer (Oct 05) PowerBooks
2) Convert the appletouch.c to use input_allocate_device()
3) Change the code to lookup either the 80th or 255th byte for button  
press depending upon it's old or new trackpad
Attached is the code which takes care of above 3 - tested but it  
should be considered half baked for obvious reasons and in addition I  
added some relayfs write calls so the received data can be sampled by  
writing a user space client for reading the relayfs file. The code  
might break the existing (old) trackpads as the detection might not  
be correct.
Needless to say the complete logic of interpreting the data and  
determining pressure and movement needs  to be changed such that it  
works for old as well as new.
[-- Attachment #2: appletouch.c --]
[-- Type: application/octet-stream, Size: 14729 bytes --]
/*
 * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
 *
 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
 * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
 * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
 * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
 * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
 * Copyright (C) 2005      Parag Warudkar (parag.warudkar@gmail.com)
 *
 * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
 * Nov 2005 - Parag Warudkar 
 * 	o Added support for Oct 2005 Powerbooks
 * 	o Converted to use input_device_allocate()
 * 	o Added ability to export data via debugfs
 *
 * 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>
#include <linux/usb_input.h>
#include <linux/debugfs.h>
#include <linux/relayfs_fs.h>
#if !defined(PPC) && !defined(POWERPC)
#error "Module intended for PowerPC based PowerBooks!"
#endif
/* Apple has powerbooks which have the keyboard with different Product IDs */
#define APPLE_VENDOR_ID		0x05AC
#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(0x020E) },
	{ ATP_DEVICE(0x020F) },
	{ ATP_DEVICE(0x030A) },
	{ ATP_DEVICE(0x030B) },
	{ ATP_DEVICE(0x0214) },			/* PowerBooks Late Oct 2005 */
	{ }					/* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, atp_table);
struct rchan* rch=NULL;
struct rchan_callbacks* rcb =NULL;
/* Debugfs data */
struct atp_dbg_data {
};
/*
 * 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.
 */
#define ATP_MAX_XSENSORS	26
#define ATP_MAX_YSENSORS	16
/* amount of fuzz this touchpad generates */
#define ATP_FUZZ	16
/* 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
typedef enum PB_MAC_TYPE {
	PowerBook54,
	PowerBook56,
	PowerBook58,
	PowerBook59,
	Unknown
}PB_MAC_TYPE;
/* 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_MAX_XSENSORS + ATP_MAX_YSENSORS];
						/* last value of the sensors */
	signed char		xy_old[ATP_MAX_XSENSORS + ATP_MAX_YSENSORS];
						/* accumulated sensors */
	int			xy_acc[ATP_MAX_XSENSORS + ATP_MAX_YSENSORS];
	PB_MAC_TYPE		mtype;
};
#define dbg_dump(msg, tab) \
	if (debug > 1) {						\
		int i;							\
		printk("appletouch: %s %lld", msg, (long long)jiffies); \
		for (i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_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, Parag Warudkar");
MODULE_DESCRIPTION("Apple Al PowerBook USB touchpad driver");
MODULE_LICENSE("GPL");
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
/* USB URB buffer length - 81 works on Feb 05 models.
 * Oct 05 models fail with EOVERFLOW, detected and corrected 
 * separately.
 */
static int data_len = 81;
module_param(data_len, int, 0644);
MODULE_PARM_DESC(data_len, "Specify USB URB buffer length (auto-detected normally)");
PB_MAC_TYPE atp_machine_detect()
{
	if(machine_is_compatible("PowerBook5,9"))
		return PowerBook59;
	if(machine_is_compatible("PowerBook5,8"))
		return PowerBook58;
	if(machine_is_compatible("PowerBook5,6"))
		return PowerBook56;
	if (machine_is_compatible("PowerBook5,4"))
		return PowerBook54;
	return Unknown;
}
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;
	struct atp *dev = urb->context;
	static int ctr=1;
	switch (urb->status) {
	case 0:
		/* success */
		break;
	case -EOVERFLOW:
		if(ctr){
			printk("appletouch: OVERFLOW with data length %d\n", data_len);
			ctr=0;
		}
	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:
		goto exit;
	}
	/* drop incomplete datasets */
	if (dev->urb->actual_length != data_len) {
		printk(KERN_WARNING "appletouch: incomplete data package length %d\n", dev->urb->actual_length);
		goto exit;
	}
	if ( dev->data ) {
		relay_write(rch, dev->data, dev->urb->actual_length);
	}
	/* reorder the sensors values */
	for (i = 0; i < 8; i++) {
		/* X values */
		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));
		/* 17" Powerbooks have 10 extra X sensors */
		for (i = 16; i < ATP_MAX_XSENSORS; i++)
			if (dev->xy_cur[i]) {
				printk("appletouch: 17\" model detected.\n");
				input_set_abs_params(dev->input, ABS_X, 0,
				     		     (ATP_MAX_XSENSORS - 1) *
						     ATP_XFACT - 1,
						     ATP_FUZZ, 0);
				break;
			}
		goto exit;
	}
	for (i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_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_MAX_XSENSORS,
			      ATP_XFACT, &x_z, &x_f);
	y = atp_calculate_abs(dev->xy_acc + ATP_MAX_XSENSORS, ATP_MAX_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_report_key(dev->input, BTN_LEFT, !!dev->data[data_len-1]);
	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)) {
		printk("atp: usb_submit_urb Error\n");
		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;
}
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;
	int regret=0;
	printk(KERN_INFO "AppleTouch: Inside atp_probe\n");
	
	/* 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->mtype = atp_machine_detect();
	if(dev->mtype == Unknown)
	{
		printk(KERN_INFO "appletouch: Unknown machine type!\n");
		return -ENODEV;
	}
	if(dev->mtype > 1)
	{
		if(data_len < 256)
		{
			printk(KERN_INFO "appletouch: Setting URB buffer length to 256\n");
			data_len=256;
		}
	}
	dev->udev = interface_to_usbdev(iface);
	printk("appletouch: Machine type is: %d\n", dev->mtype);
	/* 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;
			printk(KERN_INFO "AppleTouch:atp_probe Found interrupt in endpoint: %d\n", int_in_endpointAddr);
			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, data_len, 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, data_len, atp_complete, dev, 1);
	dev->input = input_allocate_device();
	dev->input->name = "appletouch";
	dev->input->dev = &iface->dev;
	dev->input->private = dev;
	dev->input->open = atp_open;
	dev->input->close = atp_close;
	usb_to_input_id(dev->udev, &dev->input->id);
	set_bit(EV_ABS, dev->input->evbit);
	/*
	 * 12" and 15" Powerbooks only have 16 x sensors,
	 * 17" models are detected later.
	 */
	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_MAX_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
	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);
	set_bit(BTN_LEFT, dev->input->keybit
			
			);
	regret = input_register_device(dev->input);
	printk(KERN_INFO "input: appletouch connected, Reg code :%d\n", regret);
	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, data_len,
				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);
	usb_kill_urb(dev->urb);
	dev->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;
	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)
{
	rcb  = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
	rcb->subbuf_start = NULL;
	rcb->buf_mapped = NULL;
	rcb->buf_unmapped = NULL;
	rch = relay_open("atpdata", NULL, 256, 256, NULL);
	if (!rch) return -ENOMEM;
	return usb_register(&atp_driver);
}
static void __exit atp_exit(void)
{
	relay_close(rch);
	kfree(rcb);
	usb_deregister(&atp_driver);
}
module_init(atp_init);
module_exit(atp_exit);
[-- Attachment #3: Type: text/plain, Size: 10 bytes --]
Parag
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-21 23:57 ` PowerBook5,8 - TrackPad update Parag Warudkar
@ 2005-11-22  0:08   ` Parag Warudkar
  2005-11-22 12:51   ` Johannes Berg
  2005-11-29  0:06   ` Michael Hanselmann
  2 siblings, 0 replies; 24+ messages in thread
From: Parag Warudkar @ 2005-11-22  0:08 UTC (permalink / raw)
  To: Parag Warudkar; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 328 bytes --]
On Nov 21, 2005, at 6:57 PM, Parag Warudkar wrote:
> <appletouch.c>
Oops  - originally attached file has wrong comment, this one has  
fixed comments - other wise the code is same.
Also, one more change required was to add ATP_DEVICE(0x0214) into the  
usb_device_id table which I forgot
to mention in the last mail.
Parag
[-- Attachment #2: appletouch.c --]
[-- Type: application/octet-stream, Size: 14771 bytes --]
/*
 * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
 *
 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
 * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
 * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
 * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
 * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
 * Copyright (C) 2005      Parag Warudkar (parag.warudkar@gmail.com)
 *
 * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
 * Nov 2005 - Parag Warudkar 
 * 	o Add preliminary support for Oct 2005 Powerbooks 
 * 	  (Doesn't work fully yet)
 * 	o Converted to use input_device_allocate()
 * 	o Added ability to export data via relayfs
 *
 * 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>
#include <linux/usb_input.h>
#include <linux/debugfs.h>
#include <linux/relayfs_fs.h>
#if !defined(PPC) && !defined(POWERPC)
#error "Module intended for PowerPC based PowerBooks!"
#endif
/* Apple has powerbooks which have the keyboard with different Product IDs */
#define APPLE_VENDOR_ID		0x05AC
#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(0x020E) },
	{ ATP_DEVICE(0x020F) },
	{ ATP_DEVICE(0x030A) },
	{ ATP_DEVICE(0x030B) },
	{ ATP_DEVICE(0x0214) },			/* PowerBooks Late Oct 2005 */
	{ }					/* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, atp_table);
struct rchan* rch=NULL;
struct rchan_callbacks* rcb =NULL;
/* Debugfs data */
struct atp_dbg_data {
};
/*
 * 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.
 */
#define ATP_MAX_XSENSORS	26
#define ATP_MAX_YSENSORS	16
/* amount of fuzz this touchpad generates */
#define ATP_FUZZ	16
/* 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
typedef enum PB_MAC_TYPE {
	PowerBook54,
	PowerBook56,
	PowerBook58,
	PowerBook59,
	Unknown
}PB_MAC_TYPE;
/* 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_MAX_XSENSORS + ATP_MAX_YSENSORS];
						/* last value of the sensors */
	signed char		xy_old[ATP_MAX_XSENSORS + ATP_MAX_YSENSORS];
						/* accumulated sensors */
	int			xy_acc[ATP_MAX_XSENSORS + ATP_MAX_YSENSORS];
	PB_MAC_TYPE		mtype;
};
#define dbg_dump(msg, tab) \
	if (debug > 1) {						\
		int i;							\
		printk("appletouch: %s %lld", msg, (long long)jiffies); \
		for (i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_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, Parag Warudkar");
MODULE_DESCRIPTION("Apple Al PowerBook USB touchpad driver");
MODULE_LICENSE("GPL");
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
/* USB URB buffer length - 81 works on Feb 05 models.
 * Oct 05 models fail with EOVERFLOW, detected and corrected 
 * separately.
 */
static int data_len = 81;
module_param(data_len, int, 0644);
MODULE_PARM_DESC(data_len, "Specify USB URB buffer length (auto-detected normally)");
PB_MAC_TYPE atp_machine_detect()
{
	if(machine_is_compatible("PowerBook5,9"))
		return PowerBook59;
	if(machine_is_compatible("PowerBook5,8"))
		return PowerBook58;
	if(machine_is_compatible("PowerBook5,6"))
		return PowerBook56;
	if (machine_is_compatible("PowerBook5,4"))
		return PowerBook54;
	return Unknown;
}
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;
	struct atp *dev = urb->context;
	static int ctr=1;
	switch (urb->status) {
	case 0:
		/* success */
		break;
	case -EOVERFLOW:
		if(ctr){
			printk("appletouch: OVERFLOW with data length %d\n", data_len);
			ctr=0;
		}
	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:
		goto exit;
	}
	/* drop incomplete datasets */
	if (dev->urb->actual_length != data_len) {
		printk(KERN_WARNING "appletouch: incomplete data package length %d\n", dev->urb->actual_length);
		goto exit;
	}
	if ( dev->data ) {
		relay_write(rch, dev->data, dev->urb->actual_length);
	}
	/* reorder the sensors values */
	for (i = 0; i < 8; i++) {
		/* X values */
		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));
		/* 17" Powerbooks have 10 extra X sensors */
		for (i = 16; i < ATP_MAX_XSENSORS; i++)
			if (dev->xy_cur[i]) {
				printk("appletouch: 17\" model detected.\n");
				input_set_abs_params(dev->input, ABS_X, 0,
				     		     (ATP_MAX_XSENSORS - 1) *
						     ATP_XFACT - 1,
						     ATP_FUZZ, 0);
				break;
			}
		goto exit;
	}
	for (i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_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_MAX_XSENSORS,
			      ATP_XFACT, &x_z, &x_f);
	y = atp_calculate_abs(dev->xy_acc + ATP_MAX_XSENSORS, ATP_MAX_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_report_key(dev->input, BTN_LEFT, !!dev->data[data_len-1]);
	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)) {
		printk("atp: usb_submit_urb Error\n");
		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;
}
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;
	int regret=0;
	printk(KERN_INFO "AppleTouch: Inside atp_probe\n");
	
	/* 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->mtype = atp_machine_detect();
	if(dev->mtype == Unknown)
	{
		printk(KERN_INFO "appletouch: Unknown machine type!\n");
		return -ENODEV;
	}
	if(dev->mtype > 1)
	{
		if(data_len < 256)
		{
			printk(KERN_INFO "appletouch: Setting URB buffer length to 256\n");
			data_len=256;
		}
	}
	dev->udev = interface_to_usbdev(iface);
	printk("appletouch: Machine type is: %d\n", dev->mtype);
	/* 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;
			printk(KERN_INFO "AppleTouch:atp_probe Found interrupt in endpoint: %d\n", int_in_endpointAddr);
			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, data_len, 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, data_len, atp_complete, dev, 1);
	dev->input = input_allocate_device();
	dev->input->name = "appletouch";
	dev->input->dev = &iface->dev;
	dev->input->private = dev;
	dev->input->open = atp_open;
	dev->input->close = atp_close;
	usb_to_input_id(dev->udev, &dev->input->id);
	set_bit(EV_ABS, dev->input->evbit);
	/*
	 * 12" and 15" Powerbooks only have 16 x sensors,
	 * 17" models are detected later.
	 */
	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_MAX_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
	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);
	set_bit(BTN_LEFT, dev->input->keybit
			
			);
	regret = input_register_device(dev->input);
	printk(KERN_INFO "input: appletouch connected, Reg code :%d\n", regret);
	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, data_len,
				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);
	usb_kill_urb(dev->urb);
	dev->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;
	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)
{
	rcb  = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
	rcb->subbuf_start = NULL;
	rcb->buf_mapped = NULL;
	rcb->buf_unmapped = NULL;
	rch = relay_open("atpdata", NULL, 256, 256, NULL);
	if (!rch) return -ENOMEM;
	return usb_register(&atp_driver);
}
static void __exit atp_exit(void)
{
	relay_close(rch);
	kfree(rcb);
	usb_deregister(&atp_driver);
}
module_init(atp_init);
module_exit(atp_exit);
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-21 23:57 ` PowerBook5,8 - TrackPad update Parag Warudkar
  2005-11-22  0:08   ` Parag Warudkar
@ 2005-11-22 12:51   ` Johannes Berg
  2005-11-29  0:06   ` Michael Hanselmann
  2 siblings, 0 replies; 24+ messages in thread
From: Johannes Berg @ 2005-11-22 12:51 UTC (permalink / raw)
  To: Parag Warudkar; +Cc: linuxppc-dev, debian-powerpc, linux-kernel, Parag Warudkar
Parag Warudkar wrote:
> Ok, the format interpretation of the trackpad data is taking up more
> of my time and brain than I was happy with! :)
Thanks for sending the data to me, I'll take a look later.
I have doubts, however, about using the appletouch driver, if the format
changed significantly then the code will be largely different.
johannes
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-21 23:57 ` PowerBook5,8 - TrackPad update Parag Warudkar
  2005-11-22  0:08   ` Parag Warudkar
  2005-11-22 12:51   ` Johannes Berg
@ 2005-11-29  0:06   ` Michael Hanselmann
  2005-11-29  6:11     ` Parag Warudkar
  2005-11-30 22:39     ` Michael Hanselmann
  2 siblings, 2 replies; 24+ messages in thread
From: Michael Hanselmann @ 2005-11-29  0:06 UTC (permalink / raw)
  To: Parag Warudkar; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
[-- Attachment #1.1: Type: text/plain, Size: 988 bytes --]
Hello Parag
> Attached is the code which takes care of above 3 - tested but it
> should be considered half baked for obvious reasons and
I hacked your code some more to make it work on my October 2005
PowerBook 1.67 GHz. The product ID I have, 0x0215, was in none of the
available drivers and the data format is somewhat different.
You find my hacked version attached -- be aware that in its current form
it will not work with any touchpad except 0x0215.
> in addition I added some relayfs write calls [...]
I wrapped them into #if's, so one is not required to have relayfs in the
kernel to use the driver.
> The code might break the existing (old) trackpads as the detection
> might not  be correct.
My changes do that definitively, but it's only a hack.
As far as I see it, all methods can be built into one driver. Is there
already someone working on combining them?
Greets,
Michael
-- 
Gentoo Linux Developer using m0n0wall | http://hansmi.ch/
[-- Attachment #1.2: appletouch.c --]
[-- Type: text/x-csrc, Size: 16927 bytes --]
/*
 * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
 *
 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
 * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
 * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
 * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
 * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
 * Copyright (C) 2005      Parag Warudkar (parag.warudkar@gmail.com)
 *
 * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
 * Nov 2005 - Parag Warudkar 
 * 	o Add preliminary support for Oct 2005 Powerbooks 
 * 	  (Doesn't work fully yet)
 * 	o Converted to use input_device_allocate()
 * 	o Added ability to export data via relayfs
 *
 * 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>
#include <linux/usb_input.h>
#include <linux/debugfs.h>
#include <asm/prom.h>
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
#include <linux/relayfs_fs.h>
#endif
#if !defined(PPC) && !defined(POWERPC)
#error "Module intended for PowerPC based PowerBooks!"
#endif
/* Apple has powerbooks which have the keyboard with different Product IDs */
#define APPLE_VENDOR_ID		0x05AC
#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 [] = {
	/* Earlier PowerBooks */
	{ ATP_DEVICE(0x020E) },
	{ ATP_DEVICE(0x020F) },
	{ ATP_DEVICE(0x030A) },
	{ ATP_DEVICE(0x030B) },
	/* PowerBooks Late Oct 2005 */
	{ ATP_DEVICE(0x0214) },
	{ ATP_DEVICE(0x0215) },
	/* Terminating entry */
	{ }
};
MODULE_DEVICE_TABLE (usb, atp_table);
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
struct rchan* rch = NULL;
struct rchan_callbacks* rcb = NULL;
#endif
/*
 * 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.
 */
#define ATP_MAX_XSENSORS	15
#define ATP_MAX_YSENSORS	7
/* amount of fuzz this touchpad generates */
#define ATP_FUZZ	16
/* 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
typedef enum PB_MAC_TYPE {
	PowerBook54,
	PowerBook56,
	PowerBook58,
	PowerBook59,
	Unknown
} PB_MAC_TYPE;
/* 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_MAX_XSENSORS + ATP_MAX_YSENSORS];
						/* last value of the sensors */
	signed char		xy_old[ATP_MAX_XSENSORS + ATP_MAX_YSENSORS];
						/* accumulated sensors */
	int			xy_acc[ATP_MAX_XSENSORS + ATP_MAX_YSENSORS];
	PB_MAC_TYPE		mtype;
};
#define dbg_dump(msg, tab) \
	if (debug > 1) {						\
		int i;							\
		printk("appletouch: %s %lld", msg, (long long)jiffies); \
		for (i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_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, Parag Warudkar");
MODULE_DESCRIPTION("Apple Al PowerBook USB touchpad driver");
MODULE_LICENSE("GPL");
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
/* USB URB buffer length - 81 works on Feb 05 models.
 * Oct 05 models fail with EOVERFLOW, detected and corrected 
 * separately.
 */
//static int data_len = 81;
static int data_len = 80;
module_param(data_len, int, 0644);
MODULE_PARM_DESC(data_len, "Specify USB URB buffer length (auto-detected normally)");
PB_MAC_TYPE atp_machine_detect(void)
{
	if(machine_is_compatible("PowerBook5,9"))
		return PowerBook59;
	if(machine_is_compatible("PowerBook5,8"))
		return PowerBook58;
	if(machine_is_compatible("PowerBook5,6"))
		return PowerBook56;
	if (machine_is_compatible("PowerBook5,4"))
		return PowerBook54;
	return Unknown;
}
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;
	struct atp *dev = urb->context;
	static int ctr = 1;
	switch (urb->status) {
	case 0:
		/* success */
		break;
	case -EOVERFLOW:
		if(ctr){
			printk("appletouch: OVERFLOW with data length %d\n", data_len);
			ctr = 0;
		}
	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:
		goto exit;
	}
	/* drop incomplete datasets */
	if (dev->urb->actual_length != data_len) {
		printk(KERN_WARNING "appletouch: incomplete data package length %d\n", dev->urb->actual_length);
		goto exit;
	}
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
	if ( dev->data ) {
		relay_write(rch, dev->data, dev->urb->actual_length);
	}
#endif
        dev->xy_cur[0] = dev->data[19];
        dev->xy_cur[1] = dev->data[20];
        dev->xy_cur[2] = dev->data[22];
        dev->xy_cur[3] = dev->data[23];
        dev->xy_cur[4] = dev->data[25];
        dev->xy_cur[5] = dev->data[26];
        dev->xy_cur[6] = dev->data[28];
        dev->xy_cur[7] = dev->data[29];
        dev->xy_cur[8] = dev->data[31];
        dev->xy_cur[9] = dev->data[32];
        dev->xy_cur[10] = dev->data[34];
        dev->xy_cur[11] = dev->data[35];
        dev->xy_cur[12] = dev->data[37];
        dev->xy_cur[13] = dev->data[38];
        dev->xy_cur[14] = dev->data[40];
        dev->xy_cur[15] = dev->data[1];
        dev->xy_cur[16] = dev->data[2];
        dev->xy_cur[17] = dev->data[4];
        dev->xy_cur[18] = dev->data[5];
        dev->xy_cur[19] = dev->data[7];
        dev->xy_cur[20] = dev->data[8];
        dev->xy_cur[21] = dev->data[10];
        /*
        for(i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_YSENSORS; i++) {
            printk("%2x ", dev->xy_cur[i]);
        }
        printk("\n");
        */
	/* reorder the sensors values */
	//for (i = 0; i < 8; i++) {
		/* X values */
		/*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));
		/* 17" Powerbooks have 10 extra X sensors */
		/*for (i = 16; i < ATP_MAX_XSENSORS; i++)
			if (dev->xy_cur[i]) {
				printk("appletouch: 17\" model detected.\n");
				input_set_abs_params(dev->input, ABS_X, 0,
				     		     ((ATP_MAX_XSENSORS - 1) * ATP_XFACT) - 1,
						     ATP_FUZZ, 0);
				break;
			}*/
		goto exit;
	}
	for (i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_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_MAX_XSENSORS,
			      ATP_XFACT, &x_z, &x_f);
	y = atp_calculate_abs(dev->xy_acc + ATP_MAX_XSENSORS, ATP_MAX_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_report_key(dev->input, BTN_LEFT, !!dev->data[data_len-1]);
	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)) {
		printk("atp: usb_submit_urb Error\n");
		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;
}
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;
	int regret=0;
	printk(KERN_INFO "AppleTouch: Inside atp_probe\n");
	
	/* 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->mtype = atp_machine_detect();
	if(dev->mtype == Unknown)
	{
		printk(KERN_INFO "appletouch: Unknown machine type!\n");
		return -ENODEV;
	}
	if(dev->mtype > 1)
	{
		if(data_len < 256)
		{
			printk(KERN_INFO "appletouch: Setting URB buffer length to 256\n");
			data_len = 256;
		}
	}
	printk("appletouch: Machine type is: %d\n", dev->mtype);
	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;
			printk(KERN_INFO "AppleTouch: atp_probe found interrupt in endpoint: %d\n", int_in_endpointAddr);
			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, data_len, 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, data_len, atp_complete, dev, 1);
	dev->input = input_allocate_device();
	dev->input->name = "appletouch";
	dev->input->dev = &iface->dev;
	dev->input->private = dev;
	dev->input->open = atp_open;
	dev->input->close = atp_close;
	usb_to_input_id(dev->udev, &dev->input->id);
	set_bit(EV_ABS, dev->input->evbit);
	/*
	 * 12" and 15" Powerbooks only have 16 x sensors,
	 * 17" models are detected later.
	 */
	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_MAX_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
	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);
	set_bit(BTN_LEFT, dev->input->keybit);
	regret = input_register_device(dev->input);
	printk(KERN_INFO "input: appletouch connected, Reg code: %d\n", regret);
	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, data_len,
				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);
	usb_kill_urb(dev->urb);
	dev->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;
	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)
{
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
	rcb  = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
	rcb->subbuf_start = NULL;
	rcb->buf_mapped = NULL;
	rcb->buf_unmapped = NULL;
	rch = relay_open("atpdata", NULL, 256, 256, NULL);
	if (!rch) return -ENOMEM;
	printk("appletouch: Relayfs enabled.\n");
#endif
	return usb_register(&atp_driver);
}
static void __exit atp_exit(void)
{
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
	relay_close(rch);
	kfree(rcb);
#endif
	usb_deregister(&atp_driver);
}
module_init(atp_init);
module_exit(atp_exit);
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-29  0:06   ` Michael Hanselmann
@ 2005-11-29  6:11     ` Parag Warudkar
  2005-11-29  7:50       ` Michael Hanselmann
  2005-11-30 22:39     ` Michael Hanselmann
  1 sibling, 1 reply; 24+ messages in thread
From: Parag Warudkar @ 2005-11-29  6:11 UTC (permalink / raw)
  To: Michael Hanselmann; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1055 bytes --]
On Nov 28, 2005, at 7:06 PM, Michael Hanselmann wrote:
> The product ID I have, 0x0215, was in none of the
> available drivers and the data format is somewhat different
Hi Michael
Is yours the 15" model or the 17"? Mine is 15" and the product id is  
0x0214.
> You find my hacked version attached -- be aware that in its current  
> form
> it will not work with any touchpad except 0x0215.
I haven't looked at your changes completely yet but are you saying it  
works? Meaning mouse
moves properly?
Also I find it strange that your model requires 80 bytes ATP_DATASIZE  
- mine isn't happy
at all with anything less than 256. The less number of sensors you  
defined is again a puzzle.
> As far as I see it, all methods can be built into one driver. Is there
> already someone working on combining them?
If the format of the data is same (which looks like it is with your  
model) then yes, but in my case
the data arrives is 64 byte blocks - there are 4 of them in one  
transfer, each a reading on it's own.
Hmm. More confusion.
Thanks
Parag
[-- Attachment #2: Type: text/html, Size: 2386 bytes --]
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-29  6:11     ` Parag Warudkar
@ 2005-11-29  7:50       ` Michael Hanselmann
  2005-11-29 10:38         ` Johannes Berg
  2005-11-29 16:11         ` Parag Warudkar
  0 siblings, 2 replies; 24+ messages in thread
From: Michael Hanselmann @ 2005-11-29  7:50 UTC (permalink / raw)
  To: Parag Warudkar; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1184 bytes --]
Hello Parag
On Tue, Nov 29, 2005 at 01:11:00AM -0500, Parag Warudkar wrote:
> Is yours the 15" model or the 17"? Mine is 15" and the product id is  
> 0x0214.
It's the 15" one.
> I haven't looked at your changes completely yet but are you saying it
> works? Meaning mouse moves properly?
The mouse moves, but slowly. Maybe something isn't correct yet, but it
works basically.
> Also I find it strange that your model requires 80 bytes ATP_DATASIZE
> - mine isn't happy at all with anything less than 256. The less number
> of sensors you  defined is again a puzzle.
That are points I need to investigate further.
> If the format of the data is same (which looks like it is with your
> model) then yes, but in my case the data arrives is 64 byte blocks -
> there are 4 of them in one  transfer, each a reading on it's own.
I get 256 bytes in each transfer as well, but didn't look at the bytes
behind 40. Maybe that'll help to make it more responsive.
> Hmm. More confusion.
Oh yes. Why does Apple ship the basically same PowerBook with different
Touchpads?
Greets,
Michael
-- 
Gentoo Linux Developer using m0n0wall | http://hansmi.ch/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-29  7:50       ` Michael Hanselmann
@ 2005-11-29 10:38         ` Johannes Berg
  2005-11-29 16:11         ` Parag Warudkar
  1 sibling, 0 replies; 24+ messages in thread
From: Johannes Berg @ 2005-11-29 10:38 UTC (permalink / raw)
  To: Michael Hanselmann
  Cc: linuxppc-dev, debian-powerpc, linux-kernel, Parag Warudkar
Michael Hanselmann wrote:
>> I haven't looked at your changes completely yet but are you saying it
>> works? Meaning mouse moves properly?
>
> The mouse moves, but slowly. Maybe something isn't correct yet, but it
> works basically.
All this sounds almost like your touchpad is much more similar to the old
one. I'll most likely have access to a new powerbook within the next two
weeks, so I'll be able to take a look.
johannes
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-29  7:50       ` Michael Hanselmann
  2005-11-29 10:38         ` Johannes Berg
@ 2005-11-29 16:11         ` Parag Warudkar
  2005-11-30 11:17           ` Johannes Berg
  1 sibling, 1 reply; 24+ messages in thread
From: Parag Warudkar @ 2005-11-29 16:11 UTC (permalink / raw)
  To: Michael Hanselmann; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
On Nov 29, 2005, at 2:50 AM, Michael Hanselmann wrote:
> The mouse moves, but slowly. Maybe something isn't correct yet, but it
> works basically.
Yeah, mine works like that too - but sometimes it will go left->right  
when you moved the finger
right->left and vice versa.
> I get 256 bytes in each transfer as well, but didn't look at the bytes
> behind 40. Maybe that'll help to make it more responsive.
Nope, if yours works with 80 bytes, it only sends 80. It will still  
work with anything > 80 but that's superfluous data.
(E,g, Mine works even with 1024 - anything above 256 seems junk, but  
with < 256 it dies with EOVERFLOW )
Right now I have detected that byte # 13 increases when moving finger  
along the bottom from left corner to right,
and byte #11 changes when moved from bottom left corner to top left.  
Gotta figure out the rest of the movement patterns
along with how many total sensors X and Y are there and how to relate  
the data to something to report to the input device!
Hopefully Johannes will have a PowerBook with either of the 0x0214 or  
0x0215 touchpads
and we will make some headway!
Parag
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-29 16:11         ` Parag Warudkar
@ 2005-11-30 11:17           ` Johannes Berg
  0 siblings, 0 replies; 24+ messages in thread
From: Johannes Berg @ 2005-11-30 11:17 UTC (permalink / raw)
  To: Parag Warudkar; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
Parag Warudkar wrote:
> Hopefully Johannes will have a PowerBook with either of the 0x0214 or
> 0x0215 touchpads and we will make some headway!
If anyone is in the area of Paderborn (Germany) who has such a touchpad,
it may be faster if I just look at that one :) If not, well, we can sort
of hope that the one my brother's ordering will have that touchpad.
johannes
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-29  0:06   ` Michael Hanselmann
  2005-11-29  6:11     ` Parag Warudkar
@ 2005-11-30 22:39     ` Michael Hanselmann
  2005-11-30 23:46       ` Michael Hanselmann
  1 sibling, 1 reply; 24+ messages in thread
From: Michael Hanselmann @ 2005-11-30 22:39 UTC (permalink / raw)
  To: Parag Warudkar; +Cc: linuxppc-dev, johannes, debian-powerpc, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 521 bytes --]
> My changes do that definitively, but it's only a hack.
I now integrated support for the 0x0215 device into the driver of
2.6.15-rc3, in addition to the relayfs functions.
It would be great to get some feedback from people who have touchpads
handled by appletouch.c other than 0x0215.
The patch is attached for easier use. If nobody speaks up, I'll submit
this one, as it's simply required for the touchpad on the new Oct 2005
PowerBooks (at least 15").
-- 
Gentoo Linux Developer using m0n0wall | http://hansmi.ch/
[-- Attachment #2: linux-2.6.15-rc3-appletouch-relayfs-0x0215.diff --]
[-- Type: text/plain, Size: 10045 bytes --]
--- linux-2.6.15-rc3/drivers/usb/input/appletouch.c.orig	2005-11-29 21:30:37.000000000 +0100
+++ linux-2.6.15-rc3/drivers/usb/input/appletouch.c	2005-11-30 23:23:26.000000000 +0100
@@ -6,9 +6,19 @@
  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
+ * Copyright (C) 2005      Parag Warudkar (parag.warudkar@gmail.com)
+ * Copyright (C) 2005      Michael hanselmann (linux-kernel@hansmi.ch)
  *
  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
  *
+ * Nov 2005 - Parag Warudkar 
+ *  o Added ability to export data via relayfs
+ *
+ * Nov 2005 - Michael Hanselmann
+ *  o Compile relayfs support only if enabled in the kernel
+ *  o Enable relayfs only if requested by the user
+ *  o Added support for new October 2005 PowerBooks (0x0215)
+ *
  * 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
@@ -35,6 +45,10 @@
 #include <linux/input.h>
 #include <linux/usb_input.h>
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)                                                    
+#include <linux/relayfs_fs.h>
+#endif
+
 /* Apple has powerbooks which have the keyboard with different Product IDs */
 #define APPLE_VENDOR_ID		0x05AC
 
@@ -51,14 +65,17 @@
 static struct usb_device_id atp_table [] = {
 	{ ATP_DEVICE(0x020E) },
 	{ ATP_DEVICE(0x020F) },
+	{ ATP_DEVICE(0x0215) },	/* PowerBook 1.67 GHz, Oct 2005, PowerBook5,8 */
 	{ ATP_DEVICE(0x030A) },
 	{ ATP_DEVICE(0x030B) },
 	{ }					/* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, atp_table);
 
-/* size of a USB urb transfer */
-#define ATP_DATASIZE	81
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+struct rchan* rch = NULL;
+struct rchan_callbacks* rcb = NULL;
+#endif
 
 /*
  * number of sensors. Note that only 16 instead of 26 X (horizontal)
@@ -108,6 +125,9 @@
 	signed char		xy_old[ATP_XSENSORS + ATP_YSENSORS];
 						/* accumulated sensors */
 	int			xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+	int			is0215;		/* is the device a 0x0215? */
+	int			overflowwarn;	/* overflow warning printed? */
+	int			datalen;	/* size of a USB urb transfer */
 };
 
 #define dbg_dump(msg, tab) \
@@ -132,6 +152,10 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activate debugging output");
 
+static int relayfs = 0;
+module_param(relayfs, int, 0644);
+MODULE_PARM_DESC(relayfs, "Activate relayfs support");
+
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
 			     int *z, int *fingers)
 {
@@ -175,6 +199,13 @@
 	case 0:
 		/* success */
 		break;
+	case -EOVERFLOW:
+		if(!dev->overflowwarn) {
+			printk("appletouch: OVERFLOW with data "
+				"length %d, actual length is %d\n",
+				dev->datalen, dev->urb->actual_length);
+			dev->overflowwarn = 1;
+		}
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
@@ -189,23 +220,84 @@
 	}
 
 	/* drop incomplete datasets */
-	if (dev->urb->actual_length != ATP_DATASIZE) {
+	if (dev->urb->actual_length != dev->datalen) {
 		dprintk("appletouch: incomplete data package.\n");
 		goto exit;
 	}
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs && dev->data) {
+		relay_write(rch, dev->data, dev->urb->actual_length);
+	}
+#endif
+
 	/* reorder the sensors values */
-	for (i = 0; i < 8; i++) {
-		/* X values */
-		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];
+	if (dev->is0215) {
+		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+
+		// Read the X values
+		i = 0;
+		dev->xy_cur[i++] = dev->data[19];
+		dev->xy_cur[i++] = dev->data[20];
+		dev->xy_cur[i++] = dev->data[22];
+		dev->xy_cur[i++] = dev->data[23];
+		dev->xy_cur[i++] = dev->data[25];
+		dev->xy_cur[i++] = dev->data[26];
+		dev->xy_cur[i++] = dev->data[28];
+		dev->xy_cur[i++] = dev->data[29];
+		dev->xy_cur[i++] = dev->data[31];
+		dev->xy_cur[i++] = dev->data[32];
+		dev->xy_cur[i++] = dev->data[34];
+		dev->xy_cur[i++] = dev->data[35];
+		dev->xy_cur[i++] = dev->data[37];
+		dev->xy_cur[i++] = dev->data[38];
+		dev->xy_cur[i++] = dev->data[40];
+
+		// Read the Y values
+		i = ATP_XSENSORS;
+		dev->xy_cur[i++] = dev->data[1];
+		dev->xy_cur[i++] = dev->data[2];
+		dev->xy_cur[i++] = dev->data[4];
+		dev->xy_cur[i++] = dev->data[5];
+		dev->xy_cur[i++] = dev->data[7];
+		dev->xy_cur[i++] = dev->data[8];
+		dev->xy_cur[i++] = dev->data[10];
+		dev->xy_cur[i++] = dev->data[11];
+		dev->xy_cur[i++] = dev->data[13];
+
+#if 0
+		/* Some debug code */
+		for (i = 0; i < dev->urb->actual_length; i++) {
+			printk("%2x,", (unsigned char)dev->data[i]);
+		}
+		printk("\n");
+#endif
+
+		/* Prints the read values */
+		if (debug > 1) {
+			printk("appletouch: X=");
+			for (i = 0; i < 15; i++) {
+				printk("%2x,", (unsigned char)dev->xy_cur[i]);
+			}
+			printk("  Y=");
+			for (i = ATP_XSENSORS; i < (ATP_XSENSORS + (9 - 1)); i++) {
+				printk("%2x,", (unsigned char)dev->xy_cur[i]);
+			}
+			printk("\n");
+		}
+	} else {
+		for (i = 0; i < 8; i++) {
+			/* X values */
+			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);
@@ -216,16 +308,18 @@
 		dev->x_old = dev->y_old = -1;
 		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
-		/* 17" Powerbooks have 10 extra X sensors */
-		for (i = 16; i < ATP_XSENSORS; i++)
-			if (dev->xy_cur[i]) {
-				printk("appletouch: 17\" model detected.\n");
-				input_set_abs_params(dev->input, ABS_X, 0,
-						     (ATP_XSENSORS - 1) *
-						     ATP_XFACT - 1,
-						     ATP_FUZZ, 0);
-				break;
-			}
+		if (!dev->is0215) {
+			/* 17" Powerbooks have 10 extra X sensors */
+			for (i = 16; i < ATP_XSENSORS; i++)
+				if (dev->xy_cur[i]) {
+					printk("appletouch: 17\" model detected.\n");
+					input_set_abs_params(dev->input, ABS_X, 0,
+							     (ATP_XSENSORS - 1) *
+							     ATP_XFACT - 1,
+							     ATP_FUZZ, 0);
+					break;
+				}
+		}
 
 		goto exit;
 	}
@@ -323,7 +417,6 @@
 	int int_in_endpointAddr = 0;
 	int i, retval = -ENOMEM;
 
-
 	/* set up the endpoint information */
 	/* use only the first interrupt-in endpoint */
 	iface_desc = iface->cur_altsetting;
@@ -335,6 +428,8 @@
 					== USB_ENDPOINT_XFER_INT)) {
 			/* we found an interrupt in endpoint */
 			int_in_endpointAddr = endpoint->bEndpointAddress;
+			printk(KERN_INFO "appletouch: atp_probe found interrupt "
+			       "in endpoint: %d\n", int_in_endpointAddr);
 			break;
 		}
 	}
@@ -353,6 +448,13 @@
 
 	dev->udev = udev;
 	dev->input = input_dev;
+	dev->is0215 = (le16_to_cpu(dev->udev->descriptor.idProduct) == 0x0215);
+	dev->overflowwarn = 0;
+	if (dev->is0215) {
+		dev->datalen = 64;
+	} else {
+		dev->datalen = 81;
+	}
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->urb) {
@@ -360,7 +462,7 @@
 		goto err_free_devs;
 	}
 
-	dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
 	if (!dev->data) {
 		retval = -ENOMEM;
@@ -369,7 +471,7 @@
 
 	usb_fill_int_urb(dev->urb, udev,
 			 usb_rcvintpipe(udev, int_in_endpointAddr),
-			 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+			 dev->data, dev->datalen, atp_complete, dev, 1);
 
 	usb_make_path(udev, dev->phys, sizeof(dev->phys));
 	strlcat(dev->phys, "/input0", sizeof(dev->phys));
@@ -385,14 +487,21 @@
 
 	set_bit(EV_ABS, input_dev->evbit);
 
-	/*
-	 * 12" and 15" Powerbooks only have 16 x sensors,
-	 * 17" models are detected later.
-	 */
-	input_set_abs_params(input_dev, ABS_X, 0,
-			     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0,
-			     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	if (dev->is0215) {
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+	} else {
+		/*
+		 * 12" and 15" Powerbooks only have 16 x sensors,
+		 * 17" models are detected later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	}
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
 	set_bit(EV_KEY, input_dev->evbit);
@@ -427,7 +536,7 @@
 		usb_kill_urb(dev->urb);
 		input_unregister_device(dev->input);
 		usb_free_urb(dev->urb);
-		usb_buffer_free(dev->udev, ATP_DATASIZE,
+		usb_buffer_free(dev->udev, dev->datalen,
 				dev->data, dev->urb->transfer_dma);
 		kfree(dev);
 	}
@@ -463,11 +572,30 @@
 
 static int __init atp_init(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs) {
+		rcb = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
+		rcb->subbuf_start = NULL;
+		rcb->buf_mapped = NULL;
+		rcb->buf_unmapped = NULL;
+		rch = relay_open("atpdata", NULL, 256, 256, NULL);
+		if (!rch) return -ENOMEM;
+		printk("appletouch: Relayfs enabled.\n");
+	} else {
+		printk("appletouch: Relayfs disabled.\n");
+	}
+#endif
 	return usb_register(&atp_driver);
 }
 
 static void __exit atp_exit(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs) {
+		relay_close(rch);
+		kfree(rcb);
+	}
+#endif
 	usb_deregister(&atp_driver);
 }
 
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-30 22:39     ` Michael Hanselmann
@ 2005-11-30 23:46       ` Michael Hanselmann
  2005-12-02 14:28         ` Stelian Pop
  0 siblings, 1 reply; 24+ messages in thread
From: Michael Hanselmann @ 2005-11-30 23:46 UTC (permalink / raw)
  To: Parag Warudkar; +Cc: linuxppc-dev, johannes, debian-powerpc, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 213 bytes --]
On Wed, Nov 30, 2005 at 11:39:17PM +0100, Michael Hanselmann wrote:
> The patch is attached for easier use.
There was a mistake in it due to which the mouse button wouldn't work.
Fixed in the now attached patch.
[-- Attachment #2: linux-2.6.15-rc3-appletouch-relayfs-0x0215.diff --]
[-- Type: text/plain, Size: 9993 bytes --]
--- linux-2.6.15-rc3/drivers/usb/input/appletouch.c.orig	2005-11-29 21:30:37.000000000 +0100
+++ linux-2.6.15-rc3/drivers/usb/input/appletouch.c	2005-11-30 23:40:19.000000000 +0100
@@ -6,9 +6,19 @@
  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
+ * Copyright (C) 2005      Parag Warudkar (parag.warudkar@gmail.com)
+ * Copyright (C) 2005      Michael hanselmann (linux-kernel@hansmi.ch)
  *
  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
  *
+ * Nov 2005 - Parag Warudkar 
+ *  o Added ability to export data via relayfs
+ *
+ * Nov 2005 - Michael Hanselmann
+ *  o Compile relayfs support only if enabled in the kernel
+ *  o Enable relayfs only if requested by the user
+ *  o Added support for new October 2005 PowerBooks (0x0215)
+ *
  * 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
@@ -35,6 +45,10 @@
 #include <linux/input.h>
 #include <linux/usb_input.h>
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+#include <linux/relayfs_fs.h>
+#endif
+
 /* Apple has powerbooks which have the keyboard with different Product IDs */
 #define APPLE_VENDOR_ID		0x05AC
 
@@ -51,14 +65,17 @@
 static struct usb_device_id atp_table [] = {
 	{ ATP_DEVICE(0x020E) },
 	{ ATP_DEVICE(0x020F) },
+	{ ATP_DEVICE(0x0215) },	/* PowerBook 1.67 GHz, Oct 2005, PowerBook5,8 */
 	{ ATP_DEVICE(0x030A) },
 	{ ATP_DEVICE(0x030B) },
 	{ }					/* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, atp_table);
 
-/* size of a USB urb transfer */
-#define ATP_DATASIZE	81
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+struct rchan* rch = NULL;
+struct rchan_callbacks* rcb = NULL;
+#endif
 
 /*
  * number of sensors. Note that only 16 instead of 26 X (horizontal)
@@ -108,6 +125,9 @@
 	signed char		xy_old[ATP_XSENSORS + ATP_YSENSORS];
 						/* accumulated sensors */
 	int			xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+	int			is0215;		/* is the device a 0x0215? */
+	int			overflowwarn;	/* overflow warning printed? */
+	int			datalen;	/* size of a USB urb transfer */
 };
 
 #define dbg_dump(msg, tab) \
@@ -132,6 +152,10 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activate debugging output");
 
+static int relayfs = 0;
+module_param(relayfs, int, 0644);
+MODULE_PARM_DESC(relayfs, "Activate relayfs support");
+
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
 			     int *z, int *fingers)
 {
@@ -175,6 +199,13 @@
 	case 0:
 		/* success */
 		break;
+	case -EOVERFLOW:
+		if(!dev->overflowwarn) {
+			printk("appletouch: OVERFLOW with data "
+				"length %d, actual length is %d\n",
+				dev->datalen, dev->urb->actual_length);
+			dev->overflowwarn = 1;
+		}
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
@@ -189,23 +220,84 @@
 	}
 
 	/* drop incomplete datasets */
-	if (dev->urb->actual_length != ATP_DATASIZE) {
+	if (dev->urb->actual_length != dev->datalen) {
 		dprintk("appletouch: incomplete data package.\n");
 		goto exit;
 	}
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs && dev->data) {
+		relay_write(rch, dev->data, dev->urb->actual_length);
+	}
+#endif
+
 	/* reorder the sensors values */
-	for (i = 0; i < 8; i++) {
-		/* X values */
-		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];
+	if (dev->is0215) {
+		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+
+		// Read the X values
+		i = 0;
+		dev->xy_cur[i++] = dev->data[19];
+		dev->xy_cur[i++] = dev->data[20];
+		dev->xy_cur[i++] = dev->data[22];
+		dev->xy_cur[i++] = dev->data[23];
+		dev->xy_cur[i++] = dev->data[25];
+		dev->xy_cur[i++] = dev->data[26];
+		dev->xy_cur[i++] = dev->data[28];
+		dev->xy_cur[i++] = dev->data[29];
+		dev->xy_cur[i++] = dev->data[31];
+		dev->xy_cur[i++] = dev->data[32];
+		dev->xy_cur[i++] = dev->data[34];
+		dev->xy_cur[i++] = dev->data[35];
+		dev->xy_cur[i++] = dev->data[37];
+		dev->xy_cur[i++] = dev->data[38];
+		dev->xy_cur[i++] = dev->data[40];
+
+		// Read the Y values
+		i = ATP_XSENSORS;
+		dev->xy_cur[i++] = dev->data[1];
+		dev->xy_cur[i++] = dev->data[2];
+		dev->xy_cur[i++] = dev->data[4];
+		dev->xy_cur[i++] = dev->data[5];
+		dev->xy_cur[i++] = dev->data[7];
+		dev->xy_cur[i++] = dev->data[8];
+		dev->xy_cur[i++] = dev->data[10];
+		dev->xy_cur[i++] = dev->data[11];
+		dev->xy_cur[i++] = dev->data[13];
+
+#if 0
+		/* Some debug code */
+		for (i = 0; i < dev->urb->actual_length; i++) {
+			printk("%2x,", (unsigned char)dev->data[i]);
+		}
+		printk("\n");
+#endif
+
+		/* Prints the read values */
+		if (debug > 1) {
+			printk("appletouch: X=");
+			for (i = 0; i < 15; i++) {
+				printk("%2x,", (unsigned char)dev->xy_cur[i]);
+			}
+			printk("  Y=");
+			for (i = ATP_XSENSORS; i < (ATP_XSENSORS + (9 - 1)); i++) {
+				printk("%2x,", (unsigned char)dev->xy_cur[i]);
+			}
+			printk("\n");
+		}
+	} else {
+		for (i = 0; i < 8; i++) {
+			/* X values */
+			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);
@@ -216,16 +308,18 @@
 		dev->x_old = dev->y_old = -1;
 		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
-		/* 17" Powerbooks have 10 extra X sensors */
-		for (i = 16; i < ATP_XSENSORS; i++)
-			if (dev->xy_cur[i]) {
-				printk("appletouch: 17\" model detected.\n");
-				input_set_abs_params(dev->input, ABS_X, 0,
-						     (ATP_XSENSORS - 1) *
-						     ATP_XFACT - 1,
-						     ATP_FUZZ, 0);
-				break;
-			}
+		if (!dev->is0215) {
+			/* 17" Powerbooks have 10 extra X sensors */
+			for (i = 16; i < ATP_XSENSORS; i++)
+				if (dev->xy_cur[i]) {
+					printk("appletouch: 17\" model detected.\n");
+					input_set_abs_params(dev->input, ABS_X, 0,
+							     (ATP_XSENSORS - 1) *
+							     ATP_XFACT - 1,
+							     ATP_FUZZ, 0);
+					break;
+				}
+		}
 
 		goto exit;
 	}
@@ -323,7 +417,6 @@
 	int int_in_endpointAddr = 0;
 	int i, retval = -ENOMEM;
 
-
 	/* set up the endpoint information */
 	/* use only the first interrupt-in endpoint */
 	iface_desc = iface->cur_altsetting;
@@ -335,6 +428,8 @@
 					== USB_ENDPOINT_XFER_INT)) {
 			/* we found an interrupt in endpoint */
 			int_in_endpointAddr = endpoint->bEndpointAddress;
+			printk(KERN_INFO "appletouch: atp_probe found interrupt "
+			       "in endpoint: %d\n", int_in_endpointAddr);
 			break;
 		}
 	}
@@ -353,6 +448,13 @@
 
 	dev->udev = udev;
 	dev->input = input_dev;
+	dev->is0215 = (le16_to_cpu(dev->udev->descriptor.idProduct) == 0x0215);
+	dev->overflowwarn = 0;
+	if (dev->is0215) {
+		dev->datalen = 64;
+	} else {
+		dev->datalen = 81;
+	}
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->urb) {
@@ -360,7 +462,7 @@
 		goto err_free_devs;
 	}
 
-	dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
 	if (!dev->data) {
 		retval = -ENOMEM;
@@ -369,7 +471,7 @@
 
 	usb_fill_int_urb(dev->urb, udev,
 			 usb_rcvintpipe(udev, int_in_endpointAddr),
-			 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+			 dev->data, dev->datalen, atp_complete, dev, 1);
 
 	usb_make_path(udev, dev->phys, sizeof(dev->phys));
 	strlcat(dev->phys, "/input0", sizeof(dev->phys));
@@ -385,14 +487,21 @@
 
 	set_bit(EV_ABS, input_dev->evbit);
 
-	/*
-	 * 12" and 15" Powerbooks only have 16 x sensors,
-	 * 17" models are detected later.
-	 */
-	input_set_abs_params(input_dev, ABS_X, 0,
-			     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0,
-			     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	if (dev->is0215) {
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+	} else {
+		/*
+		 * 12" and 15" Powerbooks only have 16 x sensors,
+		 * 17" models are detected later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	}
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
 	set_bit(EV_KEY, input_dev->evbit);
@@ -427,7 +536,7 @@
 		usb_kill_urb(dev->urb);
 		input_unregister_device(dev->input);
 		usb_free_urb(dev->urb);
-		usb_buffer_free(dev->udev, ATP_DATASIZE,
+		usb_buffer_free(dev->udev, dev->datalen,
 				dev->data, dev->urb->transfer_dma);
 		kfree(dev);
 	}
@@ -463,11 +572,30 @@
 
 static int __init atp_init(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs) {
+		rcb = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
+		rcb->subbuf_start = NULL;
+		rcb->buf_mapped = NULL;
+		rcb->buf_unmapped = NULL;
+		rch = relay_open("atpdata", NULL, 256, 256, NULL);
+		if (!rch) return -ENOMEM;
+		printk("appletouch: Relayfs enabled.\n");
+	} else {
+		printk("appletouch: Relayfs disabled.\n");
+	}
+#endif
 	return usb_register(&atp_driver);
 }
 
 static void __exit atp_exit(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs) {
+		relay_close(rch);
+		kfree(rcb);
+	}
+#endif
 	usb_deregister(&atp_driver);
 }
 
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-11-30 23:46       ` Michael Hanselmann
@ 2005-12-02 14:28         ` Stelian Pop
  2005-12-04 22:42           ` Michael Hanselmann
  0 siblings, 1 reply; 24+ messages in thread
From: Stelian Pop @ 2005-12-02 14:28 UTC (permalink / raw)
  To: Michael Hanselmann
  Cc: linuxppc-dev, johannes, debian-powerpc, linux-kernel,
	Parag Warudkar
Le jeudi 01 décembre 2005 à 00:46 +0100, Michael Hanselmann a écrit :
> On Wed, Nov 30, 2005 at 11:39:17PM +0100, Michael Hanselmann wrote:
> > The patch is attached for easier use.
> 
> There was a mistake in it due to which the mouse button wouldn't work.
> Fixed in the now attached patch.
Is this version really working well on the new Powerbooks ? From what
I've seen in this thread there are still issues and it's still a work in
progress, so it may be too early to integrate the changes in the kernel.
Also, some other comments on the code itself:
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)                                                    
+#include <linux/relayfs_fs.h>
+#endif
While the relayfs code is ok for debugging, I'm wondering if it should be left in the final version at all.
+       int                     is0215;         /* is the device a 0x0215? */
No need for that, just use udev->descriptor.idProduct == 0x0215 (in a macro perhaps)
+       int                     overflowwarn;   /* overflow warning printed? */
I would use a static variable in the case -OVERFLOW: block here.
+               dev->xy_cur[i++] = dev->data[19];
+               dev->xy_cur[i++] = dev->data[20];
+               dev->xy_cur[i++] = dev->data[22];
+               dev->xy_cur[i++] = dev->data[23];
There is obviously a pattern here:
	for (i = 0; i < 15; i++)
		dev->xy_cur[i] = dev->data[ 19 + (i * 3) / 2 ]
I'm wondering if the same formula doesn't apply for more X and Y sensors (like 16 X
and 16 Y sensors on the old Powerbooks, 26 for the 17" models)
+#if 0
+               /* Some debug code */
+               for (i = 0; i < dev->urb->actual_length; i++) {
+                       printk("%2x,", (unsigned char)dev->data[i]);
+               }
+               printk("\n");
+#endif
Please dump that.
+               /* Prints the read values */
+               if (debug > 1) {
+                       printk("appletouch: X=");
+                       for (i = 0; i < 15; i++) {
+                               printk("%2x,", (unsigned char)dev->xy_cur[i]);
+                       }
+                       printk("  Y=");
+                       for (i = ATP_XSENSORS; i < (ATP_XSENSORS + (9 - 1)); i++) {
+                               printk("%2x,", (unsigned char)dev->xy_cur[i]);
+                       }
+                       printk("\n");
+               }
What is the point in doing this since the dbg_dump is called a few lines
later ? Best is to modify dbg_dump to know about the new number of
sensors...
+                       printk(KERN_INFO "appletouch: atp_probe found interrupt "
+                              "in endpoint: %d\n", int_in_endpointAddr);
Why is this useful to know ?
+       if (dev->is0215) {
+               dev->datalen = 64;
+       } else {
+               dev->datalen = 81;
+       }
Braces are not needed here.
PS: please inline the patch instead of attaching it to the mail, it's
much more easy to quote it that way.
Stelian.
-- 
Stelian Pop <stelian@popies.net>
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
@ 2005-12-02 17:02 Parag Warudkar
  0 siblings, 0 replies; 24+ messages in thread
From: Parag Warudkar @ 2005-12-02 17:02 UTC (permalink / raw)
  To: Stelian Pop, Michael Hanselmann
  Cc: linuxppc-dev, johannes, debian-powerpc, linux-kernel
My original patch is still work in progress and was intended as a starting point if someone was already adept with the trackpad stuff and was willing to help. 
(Basically it was a call for help - nothing for end users ;)
Things that remained to be done -
Either
1) Support for all PowerBooks in one code base (> Feb 2005)
Or
1) Create different versions for each one or two of them
Depending upon whether or not widely varying algorithms are needed for each variety.
2) Major part - reliably working code for finger movement detection for all Oct 2005 PowerBooks (15" itself seems to come with trackpads having entirely different characteristics.) 
3) Possibly Dual Finger Detection for scrolling - this is optional but would be good to have.
I am working on it as time and urges permit and it will speed up only if Johannes doesn't get his PowerBook or the one he gets is 0x0216 !!
Parag
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-02 14:28         ` Stelian Pop
@ 2005-12-04 22:42           ` Michael Hanselmann
  2005-12-06  3:38             ` Andy Botting
  2005-12-23 23:59             ` Benjamin Herrenschmidt
  0 siblings, 2 replies; 24+ messages in thread
From: Michael Hanselmann @ 2005-12-04 22:42 UTC (permalink / raw)
  To: Stelian Pop
  Cc: linuxppc-dev, johannes, debian-powerpc, linux-kernel,
	Parag Warudkar
On Fri, Dec 02, 2005 at 03:28:31PM +0100, Stelian Pop wrote:
> Is this version really working well on the new Powerbooks ? From what
> I've seen in this thread there are still issues and it's still a work
> in progress, so it may be too early to integrate the changes in the
> kernel.
It works fine for the 15" PowerBooks (Oct 2005) and has been tested by
at least three people. 17" should work too, but I can't test that until
later this week.
> +#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
> +#include <linux/relayfs_fs.h>
> +#endif
> While the relayfs code is ok for debugging, I'm wondering if it should
> be left in the final version at all.
It doesn't hurt as it's not much code, it makes updating the driver for
newer devices easier and it's only enabled if requested. Because of
that, I would leave it in. However, I can split it into a separate patch
if wanted.
> +       int                     overflowwarn;   /* overflow warning printed? */
> I would use a static variable in the case -OVERFLOW: block here.
As there could be, due to whatever reason, multiple devices using the
same driver, one could overflow while another doesn't. Therefore, it
should be device specific.
> +               dev->xy_cur[i++] = dev->data[19];
> +               dev->xy_cur[i++] = dev->data[20];
> +               dev->xy_cur[i++] = dev->data[22];
> +               dev->xy_cur[i++] = dev->data[23];
> There is obviously a pattern here:
> 	for (i = 0; i < 15; i++)
> 		dev->xy_cur[i] = dev->data[ 19 + (i * 3) / 2 ]
It's not that easy. This code wouldn't work as it should.
I wrote a working loop into the patch below, but as the code's called
about 1'000 times a second I unrolled the loop myself. A friend of mine
calculated that the code would take at least twice the time to run when
written using a loop.
> I'm wondering if the same formula doesn't apply for more X and Y
> sensors (like 16 X and 16 Y sensors on the old Powerbooks, 26 for the
> 17" models)
It does and is addressed in the new patch below.
> What is the point in doing this since the dbg_dump is called a few lines
> later ?
Those were some leftovers from my debugging and would have been deleted
before submitting. I just didn't want to take everything out if someone
else wants to do some extensive debugging or so.
Here's an updated patch including support for the 17" PowerBooks (Oct
2005). The informations about the 17" one are from Alex Harper.
---
--- linux-2.6.15-rc5/drivers/usb/input/appletouch.c.orig	2005-12-04 20:25:21.000000000 +0100
+++ linux-2.6.15-rc5/drivers/usb/input/appletouch.c	2005-12-04 23:37:29.000000000 +0100
@@ -6,9 +6,19 @@
  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
+ * Copyright (C) 2005      Parag Warudkar (parag.warudkar@gmail.com)
+ * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
  *
  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
  *
+ * Nov 2005 - Parag Warudkar 
+ *  o Added ability to export data via relayfs
+ *
+ * Nov 2005 - Michael Hanselmann
+ *  o Compile relayfs support only if enabled in the kernel
+ *  o Enable relayfs only if requested by the user
+ *  o Added support for new October 2005 PowerBooks (Geyser 2)
+ *
  * 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
@@ -35,8 +45,13 @@
 #include <linux/input.h>
 #include <linux/usb_input.h>
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+#include <linux/relayfs_fs.h>
+#endif
+
 /* Apple has powerbooks which have the keyboard with different Product IDs */
 #define APPLE_VENDOR_ID		0x05AC
+#define GEYSER_2_PRODUCT_ID	0x0215
 
 #define ATP_DEVICE(prod)					\
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |		\
@@ -51,14 +66,17 @@
 static struct usb_device_id atp_table [] = {
 	{ ATP_DEVICE(0x020E) },
 	{ ATP_DEVICE(0x020F) },
+	{ ATP_DEVICE(GEYSER_2_PRODUCT_ID) },	/* PowerBooks Oct 2005 */
 	{ ATP_DEVICE(0x030A) },
 	{ ATP_DEVICE(0x030B) },
 	{ }					/* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, atp_table);
 
-/* size of a USB urb transfer */
-#define ATP_DATASIZE	81
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+struct rchan* rch = NULL;
+struct rchan_callbacks* rcb = NULL;
+#endif
 
 /*
  * number of sensors. Note that only 16 instead of 26 X (horizontal)
@@ -73,6 +91,7 @@
 
 /* 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
@@ -108,6 +127,8 @@
 	signed char		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 */
 };
 
 #define dbg_dump(msg, tab) \
@@ -124,7 +145,11 @@
 		if (debug) printk(format, ##a);				\
 	} while (0)
 
-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+/* Checks if the device a Geyser 2 */
+#define IS_GEYSER_2(dev) \
+	(le16_to_cpu(dev->udev->descriptor.idProduct) == GEYSER_2_PRODUCT_ID)
+
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Parag Warudkar, Michael Hanselmann");
 MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
 MODULE_LICENSE("GPL");
 
@@ -132,6 +157,10 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activate debugging output");
 
+static int relayfs = 0;
+module_param(relayfs, int, 0644);
+MODULE_PARM_DESC(relayfs, "Activate relayfs support");
+
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
 			     int *z, int *fingers)
 {
@@ -175,6 +204,13 @@
 	case 0:
 		/* success */
 		break;
+	case -EOVERFLOW:
+		if(!dev->overflowwarn) {
+			printk("appletouch: OVERFLOW with data "
+				"length %d, actual length is %d\n",
+				dev->datalen, dev->urb->actual_length);
+			dev->overflowwarn = 1;
+		}
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
@@ -189,23 +225,83 @@
 	}
 
 	/* drop incomplete datasets */
-	if (dev->urb->actual_length != ATP_DATASIZE) {
+	if (dev->urb->actual_length != dev->datalen) {
 		dprintk("appletouch: incomplete data package.\n");
 		goto exit;
 	}
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs && dev->data) {
+		relay_write(rch, dev->data, dev->urb->actual_length);
+	}
+#endif
+
 	/* reorder the sensors values */
-	for (i = 0; i < 8; i++) {
+	if (IS_GEYSER_2(dev)) {
+		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+
+		/*
+		 * The values are laid out like this:
+		 * Y1, Y2, -, Y3, Y4, -, ...
+		 * '-' is an unused value.
+		 *
+		 * The logic in a loop:
+		 * for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+		 *	dev->xy_cur[i] = dev->data[j];
+		 *	dev->xy_cur[i + 1] = dev->data[j + 1];
+		 * }
+		 *
+		 * This code is called about 1'000 times per second for each
+		 * interrupt from the touchpad. Therefore it should be as fast
+		 * as possible. Writing the following code in a loop would take
+		 * about twice the time to run if not more.
+		 */
+
 		/* X values */
-		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];
+		dev->xy_cur[0] = dev->data[19];
+		dev->xy_cur[1] = dev->data[20];
+		dev->xy_cur[2] = dev->data[22];
+		dev->xy_cur[3] = dev->data[23];
+		dev->xy_cur[4] = dev->data[25];
+		dev->xy_cur[5] = dev->data[26];
+		dev->xy_cur[6] = dev->data[28];
+		dev->xy_cur[7] = dev->data[29];
+		dev->xy_cur[8] = dev->data[31];
+		dev->xy_cur[9] = dev->data[32];
+		dev->xy_cur[10] = dev->data[34];
+		dev->xy_cur[11] = dev->data[35];
+		dev->xy_cur[12] = dev->data[37];
+		dev->xy_cur[13] = dev->data[38];
+		dev->xy_cur[14] = dev->data[40];
+		dev->xy_cur[15] = dev->data[41];
+		dev->xy_cur[16] = dev->data[43];
+		dev->xy_cur[17] = dev->data[44];
+		dev->xy_cur[18] = dev->data[46];
+		dev->xy_cur[19] = dev->data[47];
 
 		/* Y values */
-		dev->xy_cur[i + 26] = dev->data[5 * i +  1];
-		dev->xy_cur[i + 34] = dev->data[5 * i +  3];
+		dev->xy_cur[ATP_XSENSORS + 0] = dev->data[1];
+		dev->xy_cur[ATP_XSENSORS + 1] = dev->data[2];
+		dev->xy_cur[ATP_XSENSORS + 2] = dev->data[4];
+		dev->xy_cur[ATP_XSENSORS + 3] = dev->data[5];
+		dev->xy_cur[ATP_XSENSORS + 4] = dev->data[7];
+		dev->xy_cur[ATP_XSENSORS + 5] = dev->data[8];
+		dev->xy_cur[ATP_XSENSORS + 6] = dev->data[10];
+		dev->xy_cur[ATP_XSENSORS + 7] = dev->data[11];
+		dev->xy_cur[ATP_XSENSORS + 8] = dev->data[13];
+	} else {
+		for (i = 0; i < 8; i++) {
+			/* X values */
+			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);
@@ -216,16 +312,23 @@
 		dev->x_old = dev->y_old = -1;
 		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
-		/* 17" Powerbooks have 10 extra X sensors */
-		for (i = 16; i < ATP_XSENSORS; i++)
-			if (dev->xy_cur[i]) {
-				printk("appletouch: 17\" model detected.\n");
+		/* 17" Powerbooks have extra X sensors */
+		for (i = (IS_GEYSER_2(dev)?15:16); i < ATP_XSENSORS; i++) {
+			if (!dev->xy_cur[i]) continue;
+
+			printk("appletouch: 17\" model detected.\n");
+			if(IS_GEYSER_2(dev))
+				input_set_abs_params(dev->input, ABS_X, 0,
+						     (20 - 1) *
+						     ATP_XFACT - 1,
+						     ATP_FUZZ, 0);
+			else
 				input_set_abs_params(dev->input, ABS_X, 0,
 						     (ATP_XSENSORS - 1) *
 						     ATP_XFACT - 1,
 						     ATP_FUZZ, 0);
-				break;
-			}
+			break;
+		}
 
 		goto exit;
 	}
@@ -282,7 +385,8 @@
 		memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
 	}
 
-	input_report_key(dev->input, BTN_LEFT, !!dev->data[80]);
+	input_report_key(dev->input, BTN_LEFT,
+			 !!dev->data[dev->datalen - 1]);
 
 	input_sync(dev->input);
 
@@ -323,7 +427,6 @@
 	int int_in_endpointAddr = 0;
 	int i, retval = -ENOMEM;
 
-
 	/* set up the endpoint information */
 	/* use only the first interrupt-in endpoint */
 	iface_desc = iface->cur_altsetting;
@@ -353,6 +456,8 @@
 
 	dev->udev = udev;
 	dev->input = input_dev;
+	dev->overflowwarn = 0;
+	dev->datalen = (IS_GEYSER_2(dev)?64:81);
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->urb) {
@@ -360,7 +465,7 @@
 		goto err_free_devs;
 	}
 
-	dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
 	if (!dev->data) {
 		retval = -ENOMEM;
@@ -369,7 +474,7 @@
 
 	usb_fill_int_urb(dev->urb, udev,
 			 usb_rcvintpipe(udev, int_in_endpointAddr),
-			 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+			 dev->data, dev->datalen, atp_complete, dev, 1);
 
 	usb_make_path(udev, dev->phys, sizeof(dev->phys));
 	strlcat(dev->phys, "/input0", sizeof(dev->phys));
@@ -385,14 +490,25 @@
 
 	set_bit(EV_ABS, input_dev->evbit);
 
-	/*
-	 * 12" and 15" Powerbooks only have 16 x sensors,
-	 * 17" models are detected later.
-	 */
-	input_set_abs_params(input_dev, ABS_X, 0,
-			     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0,
-			     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	if (IS_GEYSER_2(dev)) {
+		/*
+		 * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
+		 * later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+	} else {
+		/*
+		 * 12" and 15" Powerbooks only have 16 x sensors,
+		 * 17" models are detected later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	}
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
 	set_bit(EV_KEY, input_dev->evbit);
@@ -427,7 +543,7 @@
 		usb_kill_urb(dev->urb);
 		input_unregister_device(dev->input);
 		usb_free_urb(dev->urb);
-		usb_buffer_free(dev->udev, ATP_DATASIZE,
+		usb_buffer_free(dev->udev, dev->datalen,
 				dev->data, dev->urb->transfer_dma);
 		kfree(dev);
 	}
@@ -463,11 +579,30 @@
 
 static int __init atp_init(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs) {
+		rcb = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
+		rcb->subbuf_start = NULL;
+		rcb->buf_mapped = NULL;
+		rcb->buf_unmapped = NULL;
+		rch = relay_open("atpdata", NULL, 256, 256, NULL);
+		if (!rch) return -ENOMEM;
+		printk("appletouch: Relayfs enabled.\n");
+	} else {
+		printk("appletouch: Relayfs disabled.\n");
+	}
+#endif
 	return usb_register(&atp_driver);
 }
 
 static void __exit atp_exit(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs) {
+		relay_close(rch);
+		kfree(rcb);
+	}
+#endif
 	usb_deregister(&atp_driver);
 }
 
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-04 22:42           ` Michael Hanselmann
@ 2005-12-06  3:38             ` Andy Botting
  2005-12-06 21:12               ` Michael Hanselmann
  2005-12-09 23:33               ` Michael Hanselmann
  2005-12-23 23:59             ` Benjamin Herrenschmidt
  1 sibling, 2 replies; 24+ messages in thread
From: Andy Botting @ 2005-12-06  3:38 UTC (permalink / raw)
  To: Michael Hanselmann
  Cc: Stelian Pop, Parag Warudkar, linux-kernel, linuxppc-dev,
	debian-powerpc, johannes
I managed to get this working on my 15" PowerBook, but the USB id for my
Keyboard/Trackpad is 0x0214 as opposed to the 0x0215 you have in the
patch. Are you going to add 0x0214 (and any others?) to this patch
before sending it off?
Also, I found that the patch didn't apply cleanly on my kernel
2.6.15-rc5 kernel. I think many of the line numbers were out, so I ended
up patching the file manually. 
cheers,
-Andy 
On Sun, 2005-12-04 at 23:42 +0100, Michael Hanselmann wrote:
> On Fri, Dec 02, 2005 at 03:28:31PM +0100, Stelian Pop wrote:
> > Is this version really working well on the new Powerbooks ? From what
> > I've seen in this thread there are still issues and it's still a work
> > in progress, so it may be too early to integrate the changes in the
> > kernel.
> 
> It works fine for the 15" PowerBooks (Oct 2005) and has been tested by
> at least three people. 17" should work too, but I can't test that until
> later this week.
> 
> > +#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
> > +#include <linux/relayfs_fs.h>
> > +#endif
> 
> > While the relayfs code is ok for debugging, I'm wondering if it should
> > be left in the final version at all.
> 
> It doesn't hurt as it's not much code, it makes updating the driver for
> newer devices easier and it's only enabled if requested. Because of
> that, I would leave it in. However, I can split it into a separate patch
> if wanted.
> 
> > +       int                     overflowwarn;   /* overflow warning printed? */
> 
> > I would use a static variable in the case -OVERFLOW: block here.
> 
> As there could be, due to whatever reason, multiple devices using the
> same driver, one could overflow while another doesn't. Therefore, it
> should be device specific.
> 
> > +               dev->xy_cur[i++] = dev->data[19];
> > +               dev->xy_cur[i++] = dev->data[20];
> > +               dev->xy_cur[i++] = dev->data[22];
> > +               dev->xy_cur[i++] = dev->data[23];
> 
> > There is obviously a pattern here:
> 
> > 	for (i = 0; i < 15; i++)
> > 		dev->xy_cur[i] = dev->data[ 19 + (i * 3) / 2 ]
> 
> It's not that easy. This code wouldn't work as it should.
> 
> I wrote a working loop into the patch below, but as the code's called
> about 1'000 times a second I unrolled the loop myself. A friend of mine
> calculated that the code would take at least twice the time to run when
> written using a loop.
> 
> > I'm wondering if the same formula doesn't apply for more X and Y
> > sensors (like 16 X and 16 Y sensors on the old Powerbooks, 26 for the
> > 17" models)
> 
> It does and is addressed in the new patch below.
> 
> > What is the point in doing this since the dbg_dump is called a few lines
> > later ?
> 
> Those were some leftovers from my debugging and would have been deleted
> before submitting. I just didn't want to take everything out if someone
> else wants to do some extensive debugging or so.
> 
> Here's an updated patch including support for the 17" PowerBooks (Oct
> 2005). The informations about the 17" one are from Alex Harper.
> 
> ---
> --- linux-2.6.15-rc5/drivers/usb/input/appletouch.c.orig	2005-12-04 20:25:21.000000000 +0100
> +++ linux-2.6.15-rc5/drivers/usb/input/appletouch.c	2005-12-04 23:37:29.000000000 +0100
> @@ -6,9 +6,19 @@
>   * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
>   * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
>   * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
> + * Copyright (C) 2005      Parag Warudkar (parag.warudkar@gmail.com)
> + * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
>   *
>   * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
>   *
> + * Nov 2005 - Parag Warudkar 
> + *  o Added ability to export data via relayfs
> + *
> + * Nov 2005 - Michael Hanselmann
> + *  o Compile relayfs support only if enabled in the kernel
> + *  o Enable relayfs only if requested by the user
> + *  o Added support for new October 2005 PowerBooks (Geyser 2)
> + *
>   * 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
> @@ -35,8 +45,13 @@
>  #include <linux/input.h>
>  #include <linux/usb_input.h>
>  
> +#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
> +#include <linux/relayfs_fs.h>
> +#endif
> +
>  /* Apple has powerbooks which have the keyboard with different Product IDs */
>  #define APPLE_VENDOR_ID		0x05AC
> +#define GEYSER_2_PRODUCT_ID	0x0215
>  
>  #define ATP_DEVICE(prod)					\
>  	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |		\
> @@ -51,14 +66,17 @@
>  static struct usb_device_id atp_table [] = {
>  	{ ATP_DEVICE(0x020E) },
>  	{ ATP_DEVICE(0x020F) },
> +	{ ATP_DEVICE(GEYSER_2_PRODUCT_ID) },	/* PowerBooks Oct 2005 */
>  	{ ATP_DEVICE(0x030A) },
>  	{ ATP_DEVICE(0x030B) },
>  	{ }					/* Terminating entry */
>  };
>  MODULE_DEVICE_TABLE (usb, atp_table);
>  
> -/* size of a USB urb transfer */
> -#define ATP_DATASIZE	81
> +#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
> +struct rchan* rch = NULL;
> +struct rchan_callbacks* rcb = NULL;
> +#endif
>  
>  /*
>   * number of sensors. Note that only 16 instead of 26 X (horizontal)
> @@ -73,6 +91,7 @@
>  
>  /* 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
> @@ -108,6 +127,8 @@
>  	signed char		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 */
>  };
>  
>  #define dbg_dump(msg, tab) \
> @@ -124,7 +145,11 @@
>  		if (debug) printk(format, ##a);				\
>  	} while (0)
>  
> -MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
> +/* Checks if the device a Geyser 2 */
> +#define IS_GEYSER_2(dev) \
> +	(le16_to_cpu(dev->udev->descriptor.idProduct) == GEYSER_2_PRODUCT_ID)
> +
> +MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Parag Warudkar, Michael Hanselmann");
>  MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
>  MODULE_LICENSE("GPL");
>  
> @@ -132,6 +157,10 @@
>  module_param(debug, int, 0644);
>  MODULE_PARM_DESC(debug, "Activate debugging output");
>  
> +static int relayfs = 0;
> +module_param(relayfs, int, 0644);
> +MODULE_PARM_DESC(relayfs, "Activate relayfs support");
> +
>  static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
>  			     int *z, int *fingers)
>  {
> @@ -175,6 +204,13 @@
>  	case 0:
>  		/* success */
>  		break;
> +	case -EOVERFLOW:
> +		if(!dev->overflowwarn) {
> +			printk("appletouch: OVERFLOW with data "
> +				"length %d, actual length is %d\n",
> +				dev->datalen, dev->urb->actual_length);
> +			dev->overflowwarn = 1;
> +		}
>  	case -ECONNRESET:
>  	case -ENOENT:
>  	case -ESHUTDOWN:
> @@ -189,23 +225,83 @@
>  	}
>  
>  	/* drop incomplete datasets */
> -	if (dev->urb->actual_length != ATP_DATASIZE) {
> +	if (dev->urb->actual_length != dev->datalen) {
>  		dprintk("appletouch: incomplete data package.\n");
>  		goto exit;
>  	}
>  
> +#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
> +	if (relayfs && dev->data) {
> +		relay_write(rch, dev->data, dev->urb->actual_length);
> +	}
> +#endif
> +
>  	/* reorder the sensors values */
> -	for (i = 0; i < 8; i++) {
> +	if (IS_GEYSER_2(dev)) {
> +		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
> +
> +		/*
> +		 * The values are laid out like this:
> +		 * Y1, Y2, -, Y3, Y4, -, ...
> +		 * '-' is an unused value.
> +		 *
> +		 * The logic in a loop:
> +		 * for (i = 0, j = 19; i < 20; i += 2, j += 3) {
> +		 *	dev->xy_cur[i] = dev->data[j];
> +		 *	dev->xy_cur[i + 1] = dev->data[j + 1];
> +		 * }
> +		 *
> +		 * This code is called about 1'000 times per second for each
> +		 * interrupt from the touchpad. Therefore it should be as fast
> +		 * as possible. Writing the following code in a loop would take
> +		 * about twice the time to run if not more.
> +		 */
> +
>  		/* X values */
> -		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];
> +		dev->xy_cur[0] = dev->data[19];
> +		dev->xy_cur[1] = dev->data[20];
> +		dev->xy_cur[2] = dev->data[22];
> +		dev->xy_cur[3] = dev->data[23];
> +		dev->xy_cur[4] = dev->data[25];
> +		dev->xy_cur[5] = dev->data[26];
> +		dev->xy_cur[6] = dev->data[28];
> +		dev->xy_cur[7] = dev->data[29];
> +		dev->xy_cur[8] = dev->data[31];
> +		dev->xy_cur[9] = dev->data[32];
> +		dev->xy_cur[10] = dev->data[34];
> +		dev->xy_cur[11] = dev->data[35];
> +		dev->xy_cur[12] = dev->data[37];
> +		dev->xy_cur[13] = dev->data[38];
> +		dev->xy_cur[14] = dev->data[40];
> +		dev->xy_cur[15] = dev->data[41];
> +		dev->xy_cur[16] = dev->data[43];
> +		dev->xy_cur[17] = dev->data[44];
> +		dev->xy_cur[18] = dev->data[46];
> +		dev->xy_cur[19] = dev->data[47];
>  
>  		/* Y values */
> -		dev->xy_cur[i + 26] = dev->data[5 * i +  1];
> -		dev->xy_cur[i + 34] = dev->data[5 * i +  3];
> +		dev->xy_cur[ATP_XSENSORS + 0] = dev->data[1];
> +		dev->xy_cur[ATP_XSENSORS + 1] = dev->data[2];
> +		dev->xy_cur[ATP_XSENSORS + 2] = dev->data[4];
> +		dev->xy_cur[ATP_XSENSORS + 3] = dev->data[5];
> +		dev->xy_cur[ATP_XSENSORS + 4] = dev->data[7];
> +		dev->xy_cur[ATP_XSENSORS + 5] = dev->data[8];
> +		dev->xy_cur[ATP_XSENSORS + 6] = dev->data[10];
> +		dev->xy_cur[ATP_XSENSORS + 7] = dev->data[11];
> +		dev->xy_cur[ATP_XSENSORS + 8] = dev->data[13];
> +	} else {
> +		for (i = 0; i < 8; i++) {
> +			/* X values */
> +			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);
> @@ -216,16 +312,23 @@
>  		dev->x_old = dev->y_old = -1;
>  		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
>  
> -		/* 17" Powerbooks have 10 extra X sensors */
> -		for (i = 16; i < ATP_XSENSORS; i++)
> -			if (dev->xy_cur[i]) {
> -				printk("appletouch: 17\" model detected.\n");
> +		/* 17" Powerbooks have extra X sensors */
> +		for (i = (IS_GEYSER_2(dev)?15:16); i < ATP_XSENSORS; i++) {
> +			if (!dev->xy_cur[i]) continue;
> +
> +			printk("appletouch: 17\" model detected.\n");
> +			if(IS_GEYSER_2(dev))
> +				input_set_abs_params(dev->input, ABS_X, 0,
> +						     (20 - 1) *
> +						     ATP_XFACT - 1,
> +						     ATP_FUZZ, 0);
> +			else
>  				input_set_abs_params(dev->input, ABS_X, 0,
>  						     (ATP_XSENSORS - 1) *
>  						     ATP_XFACT - 1,
>  						     ATP_FUZZ, 0);
> -				break;
> -			}
> +			break;
> +		}
>  
>  		goto exit;
>  	}
> @@ -282,7 +385,8 @@
>  		memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
>  	}
>  
> -	input_report_key(dev->input, BTN_LEFT, !!dev->data[80]);
> +	input_report_key(dev->input, BTN_LEFT,
> +			 !!dev->data[dev->datalen - 1]);
>  
>  	input_sync(dev->input);
>  
> @@ -323,7 +427,6 @@
>  	int int_in_endpointAddr = 0;
>  	int i, retval = -ENOMEM;
>  
> -
>  	/* set up the endpoint information */
>  	/* use only the first interrupt-in endpoint */
>  	iface_desc = iface->cur_altsetting;
> @@ -353,6 +456,8 @@
>  
>  	dev->udev = udev;
>  	dev->input = input_dev;
> +	dev->overflowwarn = 0;
> +	dev->datalen = (IS_GEYSER_2(dev)?64:81);
>  
>  	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
>  	if (!dev->urb) {
> @@ -360,7 +465,7 @@
>  		goto err_free_devs;
>  	}
>  
> -	dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
> +	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
>  				     &dev->urb->transfer_dma);
>  	if (!dev->data) {
>  		retval = -ENOMEM;
> @@ -369,7 +474,7 @@
>  
>  	usb_fill_int_urb(dev->urb, udev,
>  			 usb_rcvintpipe(udev, int_in_endpointAddr),
> -			 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
> +			 dev->data, dev->datalen, atp_complete, dev, 1);
>  
>  	usb_make_path(udev, dev->phys, sizeof(dev->phys));
>  	strlcat(dev->phys, "/input0", sizeof(dev->phys));
> @@ -385,14 +490,25 @@
>  
>  	set_bit(EV_ABS, input_dev->evbit);
>  
> -	/*
> -	 * 12" and 15" Powerbooks only have 16 x sensors,
> -	 * 17" models are detected later.
> -	 */
> -	input_set_abs_params(input_dev, ABS_X, 0,
> -			     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
> -	input_set_abs_params(input_dev, ABS_Y, 0,
> -			     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
> +	if (IS_GEYSER_2(dev)) {
> +		/*
> +		 * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
> +		 * later.
> +		 */
> +		input_set_abs_params(input_dev, ABS_X, 0,
> +				     ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
> +		input_set_abs_params(input_dev, ABS_Y, 0,
> +				     ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
> +	} else {
> +		/*
> +		 * 12" and 15" Powerbooks only have 16 x sensors,
> +		 * 17" models are detected later.
> +		 */
> +		input_set_abs_params(input_dev, ABS_X, 0,
> +				     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
> +		input_set_abs_params(input_dev, ABS_Y, 0,
> +				     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
> +	}
>  	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
>  
>  	set_bit(EV_KEY, input_dev->evbit);
> @@ -427,7 +543,7 @@
>  		usb_kill_urb(dev->urb);
>  		input_unregister_device(dev->input);
>  		usb_free_urb(dev->urb);
> -		usb_buffer_free(dev->udev, ATP_DATASIZE,
> +		usb_buffer_free(dev->udev, dev->datalen,
>  				dev->data, dev->urb->transfer_dma);
>  		kfree(dev);
>  	}
> @@ -463,11 +579,30 @@
>  
>  static int __init atp_init(void)
>  {
> +#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
> +	if (relayfs) {
> +		rcb = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
> +		rcb->subbuf_start = NULL;
> +		rcb->buf_mapped = NULL;
> +		rcb->buf_unmapped = NULL;
> +		rch = relay_open("atpdata", NULL, 256, 256, NULL);
> +		if (!rch) return -ENOMEM;
> +		printk("appletouch: Relayfs enabled.\n");
> +	} else {
> +		printk("appletouch: Relayfs disabled.\n");
> +	}
> +#endif
>  	return usb_register(&atp_driver);
>  }
>  
>  static void __exit atp_exit(void)
>  {
> +#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
> +	if (relayfs) {
> +		relay_close(rch);
> +		kfree(rcb);
> +	}
> +#endif
>  	usb_deregister(&atp_driver);
>  }
>  
> 
> 
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-06  3:38             ` Andy Botting
@ 2005-12-06 21:12               ` Michael Hanselmann
  2005-12-09 23:33               ` Michael Hanselmann
  1 sibling, 0 replies; 24+ messages in thread
From: Michael Hanselmann @ 2005-12-06 21:12 UTC (permalink / raw)
  To: Andy Botting
  Cc: Stelian Pop, Parag Warudkar, linux-kernel, linuxppc-dev,
	debian-powerpc, johannes
Hello Andy
On Tue, Dec 06, 2005 at 02:38:36PM +1100, Andy Botting wrote:
> I managed to get this working on my 15" PowerBook, but the USB id for my
Thanks for testing.
> Keyboard/Trackpad is 0x0214 as opposed to the 0x0215 you have in the
> patch. Are you going to add 0x0214 (and any others?) to this patch
> before sending it off?
Yes, I can add that one. I don't know about any other IDs that will work
with this patch, so I can't add them.
> Also, I found that the patch didn't apply cleanly on my kernel
> 2.6.15-rc5 kernel. I think many of the line numbers were out, so I ended
> up patching the file manually. 
A friend of mine tested it today with a fresh unpacked 2.6.15-rc15 and
it applied cleanly.
Greets,
Michael
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-06  3:38             ` Andy Botting
  2005-12-06 21:12               ` Michael Hanselmann
@ 2005-12-09 23:33               ` Michael Hanselmann
  1 sibling, 0 replies; 24+ messages in thread
From: Michael Hanselmann @ 2005-12-09 23:33 UTC (permalink / raw)
  To: Andy Botting
  Cc: Stelian Pop, Parag Warudkar, linux-kernel, linuxppc-dev,
	debian-powerpc, johannes
> I managed to get this working on my 15" PowerBook, but the USB id for my
> Keyboard/Trackpad is 0x0214 as opposed to the 0x0215 you have in the
> patch. Are you going to add 0x0214 (and any others?) to this patch
> before sending it off?
This patch adds support for 0x0214 and 0x0216 in addition to 0x0215. I
found those IDs in the Info.plist of Mac OS X (see comment in the patch).
It applies cleanly to 2.6.15-rc5 (vanilla).
---
--- linux-2.6.15-rc5/drivers/usb/input/appletouch.c.orig	2005-12-04 20:25:21.000000000 +0100
+++ linux-2.6.15-rc5/drivers/usb/input/appletouch.c	2005-12-09 21:02:55.000000000 +0100
@@ -6,9 +6,19 @@
  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
+ * Copyright (C) 2005      Parag Warudkar (parag.warudkar@gmail.com)
+ * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
  *
  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
  *
+ * Nov 2005 - Parag Warudkar 
+ *  o Added ability to export data via relayfs
+ *
+ * Nov 2005 - Michael Hanselmann
+ *  o Compile relayfs support only if enabled in the kernel
+ *  o Enable relayfs only if requested by the user
+ *  o Added support for new October 2005 PowerBooks (Geyser 2)
+ *
  * 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
@@ -35,9 +45,18 @@
 #include <linux/input.h>
 #include <linux/usb_input.h>
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+#include <linux/relayfs_fs.h>
+#endif
+
 /* Apple has powerbooks which have the keyboard with different Product IDs */
 #define APPLE_VENDOR_ID		0x05AC
 
+/* These names come from Info.plist in AppleUSBTrackpad.kext */
+#define GEYSER_ANSI_PRODUCT_ID	0x0214
+#define GEYSER_ISO_PRODUCT_ID	0x0215
+#define GEYSER_JIS_PRODUCT_ID	0x0216
+
 #define ATP_DEVICE(prod)					\
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |		\
 		       USB_DEVICE_ID_MATCH_INT_CLASS |		\
@@ -53,12 +72,21 @@
 	{ ATP_DEVICE(0x020F) },
 	{ ATP_DEVICE(0x030A) },
 	{ ATP_DEVICE(0x030B) },
-	{ }					/* Terminating entry */
+
+	/* PowerBooks Oct 2005 */
+	{ ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
+	{ ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
+	{ ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+
+	/* Terminating entry */
+	{ }
 };
 MODULE_DEVICE_TABLE (usb, atp_table);
 
-/* size of a USB urb transfer */
-#define ATP_DATASIZE	81
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+struct rchan* rch = NULL;
+struct rchan_callbacks* rcb = NULL;
+#endif
 
 /*
  * number of sensors. Note that only 16 instead of 26 X (horizontal)
@@ -73,6 +101,7 @@
 
 /* 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
@@ -108,6 +137,8 @@
 	signed char		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 */
 };
 
 #define dbg_dump(msg, tab) \
@@ -124,7 +155,7 @@
 		if (debug) printk(format, ##a);				\
 	} while (0)
 
-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Parag Warudkar, Michael Hanselmann");
 MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
 MODULE_LICENSE("GPL");
 
@@ -132,6 +163,20 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activate debugging output");
 
+static int relayfs = 0;
+module_param(relayfs, int, 0644);
+MODULE_PARM_DESC(relayfs, "Activate relayfs support");
+
+/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
+static inline int atp_is_geyser_2(struct atp *dev)
+{
+	int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+	return (productId == GEYSER_ANSI_PRODUCT_ID) ||
+		(productId == GEYSER_ISO_PRODUCT_ID) ||
+		(productId == GEYSER_JIS_PRODUCT_ID);
+}
+
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
 			     int *z, int *fingers)
 {
@@ -175,6 +220,13 @@
 	case 0:
 		/* success */
 		break;
+	case -EOVERFLOW:
+		if(!dev->overflowwarn) {
+			printk("appletouch: OVERFLOW with data "
+				"length %d, actual length is %d\n",
+				dev->datalen, dev->urb->actual_length);
+			dev->overflowwarn = 1;
+		}
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
@@ -189,23 +241,83 @@
 	}
 
 	/* drop incomplete datasets */
-	if (dev->urb->actual_length != ATP_DATASIZE) {
+	if (dev->urb->actual_length != dev->datalen) {
 		dprintk("appletouch: incomplete data package.\n");
 		goto exit;
 	}
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs && dev->data) {
+		relay_write(rch, dev->data, dev->urb->actual_length);
+	}
+#endif
+
 	/* reorder the sensors values */
-	for (i = 0; i < 8; i++) {
+	if (atp_is_geyser_2(dev)) {
+		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+
+		/*
+		 * The values are laid out like this:
+		 * Y1, Y2, -, Y3, Y4, -, ...
+		 * '-' is an unused value.
+		 *
+		 * The logic in a loop:
+		 * for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+		 *	dev->xy_cur[i] = dev->data[j];
+		 *	dev->xy_cur[i + 1] = dev->data[j + 1];
+		 * }
+		 *
+		 * This code is called about 100 times per second for each
+		 * interrupt from the touchpad. Therefore it should be as fast
+		 * as possible. Writing the following code in a loop would take
+		 * about twice the time to run if not more.
+		 */
+
 		/* X values */
-		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];
+		dev->xy_cur[0] = dev->data[19];
+		dev->xy_cur[1] = dev->data[20];
+		dev->xy_cur[2] = dev->data[22];
+		dev->xy_cur[3] = dev->data[23];
+		dev->xy_cur[4] = dev->data[25];
+		dev->xy_cur[5] = dev->data[26];
+		dev->xy_cur[6] = dev->data[28];
+		dev->xy_cur[7] = dev->data[29];
+		dev->xy_cur[8] = dev->data[31];
+		dev->xy_cur[9] = dev->data[32];
+		dev->xy_cur[10] = dev->data[34];
+		dev->xy_cur[11] = dev->data[35];
+		dev->xy_cur[12] = dev->data[37];
+		dev->xy_cur[13] = dev->data[38];
+		dev->xy_cur[14] = dev->data[40];
+		dev->xy_cur[15] = dev->data[41];
+		dev->xy_cur[16] = dev->data[43];
+		dev->xy_cur[17] = dev->data[44];
+		dev->xy_cur[18] = dev->data[46];
+		dev->xy_cur[19] = dev->data[47];
 
 		/* Y values */
-		dev->xy_cur[i + 26] = dev->data[5 * i +  1];
-		dev->xy_cur[i + 34] = dev->data[5 * i +  3];
+		dev->xy_cur[ATP_XSENSORS + 0] = dev->data[1];
+		dev->xy_cur[ATP_XSENSORS + 1] = dev->data[2];
+		dev->xy_cur[ATP_XSENSORS + 2] = dev->data[4];
+		dev->xy_cur[ATP_XSENSORS + 3] = dev->data[5];
+		dev->xy_cur[ATP_XSENSORS + 4] = dev->data[7];
+		dev->xy_cur[ATP_XSENSORS + 5] = dev->data[8];
+		dev->xy_cur[ATP_XSENSORS + 6] = dev->data[10];
+		dev->xy_cur[ATP_XSENSORS + 7] = dev->data[11];
+		dev->xy_cur[ATP_XSENSORS + 8] = dev->data[13];
+	} else {
+		for (i = 0; i < 8; i++) {
+			/* X values */
+			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);
@@ -216,16 +328,23 @@
 		dev->x_old = dev->y_old = -1;
 		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
-		/* 17" Powerbooks have 10 extra X sensors */
-		for (i = 16; i < ATP_XSENSORS; i++)
-			if (dev->xy_cur[i]) {
-				printk("appletouch: 17\" model detected.\n");
+		/* 17" Powerbooks have extra X sensors */
+		for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
+			if (!dev->xy_cur[i]) continue;
+
+			printk("appletouch: 17\" model detected.\n");
+			if(atp_is_geyser_2(dev))
+				input_set_abs_params(dev->input, ABS_X, 0,
+						     (20 - 1) *
+						     ATP_XFACT - 1,
+						     ATP_FUZZ, 0);
+			else
 				input_set_abs_params(dev->input, ABS_X, 0,
 						     (ATP_XSENSORS - 1) *
 						     ATP_XFACT - 1,
 						     ATP_FUZZ, 0);
-				break;
-			}
+			break;
+		}
 
 		goto exit;
 	}
@@ -282,7 +401,8 @@
 		memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
 	}
 
-	input_report_key(dev->input, BTN_LEFT, !!dev->data[80]);
+	input_report_key(dev->input, BTN_LEFT,
+			 !!dev->data[dev->datalen - 1]);
 
 	input_sync(dev->input);
 
@@ -323,7 +443,6 @@
 	int int_in_endpointAddr = 0;
 	int i, retval = -ENOMEM;
 
-
 	/* set up the endpoint information */
 	/* use only the first interrupt-in endpoint */
 	iface_desc = iface->cur_altsetting;
@@ -353,6 +472,8 @@
 
 	dev->udev = udev;
 	dev->input = input_dev;
+	dev->overflowwarn = 0;
+	dev->datalen = (atp_is_geyser_2(dev)?64:81);
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->urb) {
@@ -360,7 +481,7 @@
 		goto err_free_devs;
 	}
 
-	dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
 	if (!dev->data) {
 		retval = -ENOMEM;
@@ -369,7 +490,7 @@
 
 	usb_fill_int_urb(dev->urb, udev,
 			 usb_rcvintpipe(udev, int_in_endpointAddr),
-			 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+			 dev->data, dev->datalen, atp_complete, dev, 1);
 
 	usb_make_path(udev, dev->phys, sizeof(dev->phys));
 	strlcat(dev->phys, "/input0", sizeof(dev->phys));
@@ -385,14 +506,25 @@
 
 	set_bit(EV_ABS, input_dev->evbit);
 
-	/*
-	 * 12" and 15" Powerbooks only have 16 x sensors,
-	 * 17" models are detected later.
-	 */
-	input_set_abs_params(input_dev, ABS_X, 0,
-			     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0,
-			     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	if (atp_is_geyser_2(dev)) {
+		/*
+		 * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
+		 * later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+	} else {
+		/*
+		 * 12" and 15" Powerbooks only have 16 x sensors,
+		 * 17" models are detected later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	}
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
 	set_bit(EV_KEY, input_dev->evbit);
@@ -427,7 +559,7 @@
 		usb_kill_urb(dev->urb);
 		input_unregister_device(dev->input);
 		usb_free_urb(dev->urb);
-		usb_buffer_free(dev->udev, ATP_DATASIZE,
+		usb_buffer_free(dev->udev, dev->datalen,
 				dev->data, dev->urb->transfer_dma);
 		kfree(dev);
 	}
@@ -463,11 +595,30 @@
 
 static int __init atp_init(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs) {
+		rcb = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
+		rcb->subbuf_start = NULL;
+		rcb->buf_mapped = NULL;
+		rcb->buf_unmapped = NULL;
+		rch = relay_open("atpdata", NULL, 256, 256, NULL);
+		if (!rch) return -ENOMEM;
+		printk("appletouch: Relayfs enabled.\n");
+	} else {
+		printk("appletouch: Relayfs disabled.\n");
+	}
+#endif
 	return usb_register(&atp_driver);
 }
 
 static void __exit atp_exit(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if (relayfs) {
+		relay_close(rch);
+		kfree(rcb);
+	}
+#endif
 	usb_deregister(&atp_driver);
 }
 
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-04 22:42           ` Michael Hanselmann
  2005-12-06  3:38             ` Andy Botting
@ 2005-12-23 23:59             ` Benjamin Herrenschmidt
  2005-12-24 11:52               ` René Nussbaumer
  2005-12-24 20:17               ` Pavel Machek
  1 sibling, 2 replies; 24+ messages in thread
From: Benjamin Herrenschmidt @ 2005-12-23 23:59 UTC (permalink / raw)
  To: Michael Hanselmann
  Cc: Parag Warudkar, linux-kernel, linuxppc-dev, debian-powerpc
Ok, I finally received my new laptop (PowerBook5,8 15"). I tried the
latest patch you posted, and while the kernel driver seem to work ok
(though you can feel the lack of a proper acceleration curve), the
synaptics driver in X doesn't work in any useable way. I updated the one
that comes with breezy to whatever was the latest on the author web site
(.44 I think) and while it detected the tracpkad, the result was soooooo
slooooow that it was totally unseable. I've tried the config tool that
comes with KDE for it but couldn't "boost" it to anything useful. Is
that expected or is there still issues to be resolved in the driver ?
I'm tempted to add some minimum support for a proper acceleration curve
in the kernel driver in fact...
Ben.
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-23 23:59             ` Benjamin Herrenschmidt
@ 2005-12-24 11:52               ` René Nussbaumer
  2005-12-24 20:17               ` Pavel Machek
  1 sibling, 0 replies; 24+ messages in thread
From: René Nussbaumer @ 2005-12-24 11:52 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linux-kernel, linuxppc-dev, debian-powerpc, Parag Warudkar
[-- Attachment #1: Type: text/plain, Size: 709 bytes --]
Hello
On Sat, Dec 24, 2005 at 10:59:44AM +1100, Benjamin Herrenschmidt wrote:
[...]
> comes with KDE for it but couldn't "boost" it to anything useful. Is
> that expected or is there still issues to be resolved in the driver ?
> I'm tempted to add some minimum support for a proper acceleration curve
> in the kernel driver in fact...
I'd the same problem. A quick look into Xorg.0.log tells me, that the
event device was missing. I created it manually and the acceleration and
other feautres are working now. Maybe you've still the same problem?
René
-- 
Written on a Gentoo Linux-system by René
http://www.forkbomb.ch
«Das Leben ist hart. Forkbomb ist härter.», (c) 2004 by Frank.
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-23 23:59             ` Benjamin Herrenschmidt
  2005-12-24 11:52               ` René Nussbaumer
@ 2005-12-24 20:17               ` Pavel Machek
  2005-12-24 22:27                 ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 24+ messages in thread
From: Pavel Machek @ 2005-12-24 20:17 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linux-kernel, linuxppc-dev, debian-powerpc, Parag Warudkar
Hi!
> Ok, I finally received my new laptop (PowerBook5,8 15"). I tried the
> latest patch you posted, and while the kernel driver seem to work ok
> (though you can feel the lack of a proper acceleration curve), the
> synaptics driver in X doesn't work in any useable way. I updated the one
> that comes with breezy to whatever was the latest on the author web site
> (.44 I think) and while it detected the tracpkad, the result was soooooo
> slooooow that it was totally unseable. I've tried the config tool that
> comes with KDE for it but couldn't "boost" it to anything useful. Is
> that expected or is there still issues to be resolved in the driver ?
> I'm tempted to add some minimum support for a proper acceleration curve
> in the kernel driver in fact...
I do not think you should add it inside *kernel*. Proper acceleration
support really belongs to X...
								Pavel
-- 
Thanks, Sharp!
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-24 20:17               ` Pavel Machek
@ 2005-12-24 22:27                 ` Benjamin Herrenschmidt
  2005-12-24 23:19                   ` Pavel Machek
  0 siblings, 1 reply; 24+ messages in thread
From: Benjamin Herrenschmidt @ 2005-12-24 22:27 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel, linuxppc-dev, debian-powerpc, Parag Warudkar
On Sat, 2005-12-24 at 21:17 +0100, Pavel Machek wrote:
> Hi!
> 
> > Ok, I finally received my new laptop (PowerBook5,8 15"). I tried the
> > latest patch you posted, and while the kernel driver seem to work ok
> > (though you can feel the lack of a proper acceleration curve), the
> > synaptics driver in X doesn't work in any useable way. I updated the one
> > that comes with breezy to whatever was the latest on the author web site
> > (.44 I think) and while it detected the tracpkad, the result was soooooo
> > slooooow that it was totally unseable. I've tried the config tool that
> > comes with KDE for it but couldn't "boost" it to anything useful. Is
> > that expected or is there still issues to be resolved in the driver ?
> > I'm tempted to add some minimum support for a proper acceleration curve
> > in the kernel driver in fact...
> 
> I do not think you should add it inside *kernel*. Proper acceleration
> support really belongs to X...
X, fbdev apps, gpm ... acceleration curves are typically done in HW,
thus it makes sense in this case to have it in the kernel driver
(besides, it should be fairly simple anyway) when it's in normal mode.
When it's in raw mode for use by the synaptics X driver, if course, it's
expected that those things are to be done by that driver.
Ben.
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-24 22:27                 ` Benjamin Herrenschmidt
@ 2005-12-24 23:19                   ` Pavel Machek
  2005-12-25  0:33                     ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 24+ messages in thread
From: Pavel Machek @ 2005-12-24 23:19 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linux-kernel, linuxppc-dev, debian-powerpc, Parag Warudkar
On Ne 25-12-05 09:27:51, Benjamin Herrenschmidt wrote:
> On Sat, 2005-12-24 at 21:17 +0100, Pavel Machek wrote:
> > Hi!
> > 
> > > Ok, I finally received my new laptop (PowerBook5,8 15"). I tried the
> > > latest patch you posted, and while the kernel driver seem to work ok
> > > (though you can feel the lack of a proper acceleration curve), the
> > > synaptics driver in X doesn't work in any useable way. I updated the one
> > > that comes with breezy to whatever was the latest on the author web site
> > > (.44 I think) and while it detected the tracpkad, the result was soooooo
> > > slooooow that it was totally unseable. I've tried the config tool that
> > > comes with KDE for it but couldn't "boost" it to anything useful. Is
> > > that expected or is there still issues to be resolved in the driver ?
> > > I'm tempted to add some minimum support for a proper acceleration curve
> > > in the kernel driver in fact...
> > 
> > I do not think you should add it inside *kernel*. Proper acceleration
> > support really belongs to X...
> 
> X, fbdev apps, gpm ... acceleration curves are typically done in HW,
> thus it makes sense in this case to have it in the kernel driver
> (besides, it should be fairly simple anyway) when it's in normal
> mode.
It should be doable once in gpm, all other apps can use gpm's repeater
mode...
> When it's in raw mode for use by the synaptics X driver, if course, it's
> expected that those things are to be done by that driver.
...but you are right, doing it in /dev/input/mice emulation layer
makes some sense. OTOH I thought we were moving away from
/dev/input/mice... Its Dmitry's call I guess.
								Pavel
-- 
Thanks, Sharp!
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-24 23:19                   ` Pavel Machek
@ 2005-12-25  0:33                     ` Benjamin Herrenschmidt
  2005-12-25  0:52                       ` Dmitry Torokhov
  0 siblings, 1 reply; 24+ messages in thread
From: Benjamin Herrenschmidt @ 2005-12-25  0:33 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel, linuxppc-dev, debian-powerpc, Parag Warudkar
> It should be doable once in gpm, all other apps can use gpm's repeater
> mode...
> 
> > When it's in raw mode for use by the synaptics X driver, if course, it's
> > expected that those things are to be done by that driver.
> 
> ...but you are right, doing it in /dev/input/mice emulation layer
> makes some sense. OTOH I thought we were moving away from
> /dev/input/mice... Its Dmitry's call I guess.
Heh, yes, it is. No hurry anyway, I finally got synaptics working
properly in X ...
Why would we move away from the mouse mux ? It's proven to be very
useful to me at least :)
Ben
^ permalink raw reply	[flat|nested] 24+ messages in thread
* Re: PowerBook5,8 - TrackPad update
  2005-12-25  0:33                     ` Benjamin Herrenschmidt
@ 2005-12-25  0:52                       ` Dmitry Torokhov
  0 siblings, 0 replies; 24+ messages in thread
From: Dmitry Torokhov @ 2005-12-25  0:52 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Parag Warudkar, linux-kernel, linuxppc-dev, debian-powerpc,
	Pavel Machek
On Saturday 24 December 2005 19:33, Benjamin Herrenschmidt wrote:
> 
> > It should be doable once in gpm, all other apps can use gpm's repeater
> > mode...
> > 
> > > When it's in raw mode for use by the synaptics X driver, if course, it's
> > > expected that those things are to be done by that driver.
> > 
> > ...but you are right, doing it in /dev/input/mice emulation layer
> > makes some sense. OTOH I thought we were moving away from
> > /dev/input/mice... Its Dmitry's call I guess.
> 
> Heh, yes, it is. No hurry anyway, I finally got synaptics working
> properly in X ...
> 
> Why would we move away from the mouse mux ? It's proven to be very
> useful to me at least :)
>
It is very limited - number of buttons, wheels, etc. Once X supports
hotplugging mouse multipexor outgrows its usefullness (GPM can simply
be restarted every time we detect new input device).
-- 
Dmitry
^ permalink raw reply	[flat|nested] 24+ messages in thread
end of thread, other threads:[~2005-12-25  0:52 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <111520052143.16540.437A5680000BE8A60000409C220076369200009A9B9CD3040A029D0A05@comcast.net>
2005-11-21 23:57 ` PowerBook5,8 - TrackPad update Parag Warudkar
2005-11-22  0:08   ` Parag Warudkar
2005-11-22 12:51   ` Johannes Berg
2005-11-29  0:06   ` Michael Hanselmann
2005-11-29  6:11     ` Parag Warudkar
2005-11-29  7:50       ` Michael Hanselmann
2005-11-29 10:38         ` Johannes Berg
2005-11-29 16:11         ` Parag Warudkar
2005-11-30 11:17           ` Johannes Berg
2005-11-30 22:39     ` Michael Hanselmann
2005-11-30 23:46       ` Michael Hanselmann
2005-12-02 14:28         ` Stelian Pop
2005-12-04 22:42           ` Michael Hanselmann
2005-12-06  3:38             ` Andy Botting
2005-12-06 21:12               ` Michael Hanselmann
2005-12-09 23:33               ` Michael Hanselmann
2005-12-23 23:59             ` Benjamin Herrenschmidt
2005-12-24 11:52               ` René Nussbaumer
2005-12-24 20:17               ` Pavel Machek
2005-12-24 22:27                 ` Benjamin Herrenschmidt
2005-12-24 23:19                   ` Pavel Machek
2005-12-25  0:33                     ` Benjamin Herrenschmidt
2005-12-25  0:52                       ` Dmitry Torokhov
2005-12-02 17:02 Parag Warudkar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).