On Mon, 2007-07-16 at 10:32 +1000, Daniel M. Newman wrote:
> Using kernel 2.6.22 and the mactel-linux revision 133 patch set from svn
> on a Macbook Pro 15in, there seem to be a couple of peculiarities in the
> trackpad behaviour.

please try the attached kernel patch and make sure that you are using a
new X synaptics driver (e.g. 0.14.7~git20070517 )...

> 1. During boot-up, the appletouch module always loads normally. 
> However, as X (using the fglrx driver 8.38.6) starts up I sometimes
> (about one time in five) get an error that the core pointer is
> unavailable.  When this happens, the following shows up in syslog:
> 
> kernel: BUG: scheduling while atomic: Xorg/0x00000001/2826
> kernel:  [schedule+1267/2448] schedule+0x4f3/0x990
> kernel:  [_spin_unlock+13/48] _spin_unlock+0xd/0x30
> kernel:  [__wake_up_common+57/112] __wake_up_common+0x39/0x70
> kernel:  [__wake_up+56/80] __wake_up+0x38/0x50
> kernel:  [<f89d8f81>] irqmgr_wrap_shutdown+0xe1/0x150 [fglrx]
> kernel:  [<f89c9f45>] firegl_takedown+0x625/0xc50 [fglrx]
> kernel:  [proc_delete_inode+0/96] proc_delete_inode+0x0/0x60
> kernel:  [<f89c900f>] firegl_release+0x12f/0x190 [fglrx]
> kernel:  [<f89bd44f>] ip_firegl_release+0xf/0x20 [fglrx]
> kernel:  [__fput+151/368] __fput+0x97/0x170
> kernel:  [filp_close+73/128] filp_close+0x49/0x80
> kernel:  [put_files_struct+156/192] put_files_struct+0x9c/0xc0
> kernel:  [do_exit+314/2016] do_exit+0x13a/0x7e0
> kernel:  [<f8a14be9>] IRQMGR_WorkerThreadRoutine+0x29/0x30 [fglrx]
> kernel:  [<f89bab90>] kasThreadRoutineHelper+0x0/0x20 [fglrx]
> kernel:  [<f89bab90>] kasThreadRoutineHelper+0x0/0x20 [fglrx]
> kernel:  [<f89d8d2e>] IRQMGR_CallbackWrapper+0xe/0x20 [fglrx]
> kernel:  [<f89bab90>] kasThreadRoutineHelper+0x0/0x20 [fglrx]
> kernel:  [kernel_thread_helper+13/20] kernel_thread_helper+0xd/0x14
> 
> Removing and re-inserting appletouch generally fixes this, although
> sometimes I have to do the remove and reinsert twice.

this sounds more like a bug in fglrx... but I've yet to see this to
happen...

> 2. I have my screen set to blank after a period of non-usage.  When
> waking up after this happens, the trackpad cursor no longer follows
> finger movements reliably.  Removing and re-inserting the appletouch
> module fixes this, but does not re-enable response to two- and three-
> finger taps.  Restarting gdm fixes both problems.

that should be fixed by the patch.

> 3.  Trackpad button presses sometimes do not generate an immediate
> response.  However, if the trackpad button is pressed and no response
> happens, a small movement of the cursor will cause the response to
> occur.  It seems that the button press input is being queued, but the
> queue is not checked until trackpad motion is detected.  I thought this
> might be due to my xorg.conf settings, but these seem to be in
> accordance with the various recommendations (see below).

strange... 

Please report back whether it still happens with the attached patch and
a newer synaptics xorg driver...

Thanks,
Soeren
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index e321526..0426054 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -155,6 +155,8 @@ struct atp {
 	int			xy_acc[ATP_XSENSORS + ATP_YSENSORS];
 	int			overflowwarn;	/* overflow warning printed? */
 	int			datalen;	/* size of an USB urb transfer */
+	int                     idlecount;      /* number of empty packets */
+	struct work_struct      work;
 };
 
 #define dbg_dump(msg, tab) \
@@ -208,6 +210,64 @@ static inline int atp_is_geyser_3(struct atp *dev)
 		(productId == GEYSER4_JIS_PRODUCT_ID);
 }
 
+/*
+ * By default Geyser 3 device sends standard USB HID mouse
+ * packets (Report ID 2). This code changes device mode, so it
+ * sends raw sensor reports (Report ID 5).
+ */
+static int atp_geyser3_init(struct usb_device *udev)
+{
+	char data[8];
+	int size;
+	int i;
+
+	size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+			       ATP_GEYSER3_MODE_READ_REQUEST_ID,
+			       USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			       ATP_GEYSER3_MODE_REQUEST_VALUE,
+			       ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+
+
+	if (size != 8) {
+		printk("appletouch atp_geyser3_init READ error\n");
+		for (i=0; i<8; i++)
+			printk("appletouch[%d]: %d\n", i, (int) data[i]);
+
+		err("Could not do mode read request from device"
+		    " (Geyser 3 mode)");
+		return -EIO;
+	}
+
+	/* Apply the mode switch */
+	data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE;
+
+	size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			       ATP_GEYSER3_MODE_WRITE_REQUEST_ID,
+			       USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			       ATP_GEYSER3_MODE_REQUEST_VALUE,
+			       ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+	
+	if (size != 8) {
+		printk("appletouch atp_geyser3_init WRITE error\n");
+		for (i=0; i<8; i++)
+			printk("appletouch[%d]: %d\n", i, (int) data[i]);
+		err("Could not do mode write request to device"
+		    " (Geyser 3 mode)");
+		return -EIO;
+	}
+	return 0;
+}
+
+/* Reinitialise the device if it's a geyser 3 */
+static void atp_reinit(struct work_struct *work)
+{
+	struct atp *dev = container_of(work, struct atp, work);
+	struct usb_device *udev = dev->udev;
+
+	dev->idlecount = 0;
+	atp_geyser3_init(udev);
+}
+
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
 			     int *z, int *fingers)
 {
@@ -418,6 +478,8 @@ static void atp_complete(struct urb* urb)
 	y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
 			      ATP_YFACT, &y_z, &y_f);
 
+	input_report_key(dev->input, BTN_LEFT, dev->data[dev->datalen-1] & 1);
+
 	if (x && y) {
 		if (dev->x_old != -1) {
 			x = (dev->x_old * 3 + x) >> 2;
@@ -449,10 +511,19 @@ static void atp_complete(struct urb* urb)
 
 		/* reset the accumulator on release */
 		memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
-	}
 
-	input_report_key(dev->input, BTN_LEFT,
-			 !!dev->data[dev->datalen - 1]);
+		/* Geyser 3 will continue to send packets continually after
+		   the first touch unless reinitialised. Do so if it's been
+		   idle for a while in order to avoid waking the kernel up
+		   several hundred times a second */
+		if (atp_is_geyser_3(dev)) {
+			dev->idlecount++;
+			if (dev->idlecount == 10) {
+				dev->valid=0;
+				schedule_work (&dev->work);
+			}
+		}
+	}
 
 	input_sync(dev->input);
 
@@ -528,40 +599,10 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
 		dev->datalen = 81;
 
 	if (atp_is_geyser_3(dev)) {
-		/*
-		 * By default Geyser 3 device sends standard USB HID mouse
-		 * packets (Report ID 2). This code changes device mode, so it
-		 * sends raw sensor reports (Report ID 5).
-		 */
-		char data[8];
-		int size;
-
-		size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-			ATP_GEYSER3_MODE_READ_REQUEST_ID,
-			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-			ATP_GEYSER3_MODE_REQUEST_VALUE,
-			ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
-
-		if (size != 8) {
-			err("Could not do mode read request from device"
-							" (Geyser 3 mode)");
+		/* switch to raw sensor mode */
+		if (atp_geyser3_init(udev))
 			goto err_free_devs;
-		}
-
-		/* Apply the mode switch */
-		data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE;
 
-		size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-			ATP_GEYSER3_MODE_WRITE_REQUEST_ID,
-			USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-			ATP_GEYSER3_MODE_REQUEST_VALUE,
-			ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
-
-		if (size != 8) {
-			err("Could not do mode write request to device"
-							" (Geyser 3 mode)");
-			goto err_free_devs;
-		}
 		printk("appletouch Geyser 3 inited.\n");
 	}
 
@@ -636,6 +677,8 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(iface, dev);
 
+	INIT_WORK(&dev->work, atp_reinit);
+
 	return 0;
 
  err_free_buffer:
@@ -656,6 +699,7 @@ static void atp_disconnect(struct usb_interface *iface)
 
 	usb_set_intfdata(iface, NULL);
 	if (dev) {
+		cancel_work_sync(&dev->work);
 		usb_kill_urb(dev->urb);
 		input_unregister_device(dev->input);
 		usb_buffer_free(dev->udev, dev->datalen,
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Mactel-linux-devel mailing list
Mactel-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mactel-linux-devel

Reply via email to