The attached patch tries to resolve the 'appletouch runs amok' problem,
which accured *for me* after using the mbp for a couple of hours/days
with the power-saving [PATCH] Make appletouch shut up when it has
nothing to say from Matthew Garrett.

I am using it for 3 days now without ever running in trouble. So I think
it is ready for wider testing.

@Matthew, this patch differs only in also reporting the key/input_sync
when the idlecount is reached:

           if (dev->idlecount == 10) {
+               if (dev->data[dev->datalen-1] != 20) 
+                   input_report_key(dev->input, BTN_LEFT,
+                           !!dev->data[dev->datalen - 1]);
+
+               input_sync(dev->input);
                schedule_work (&dev->work);

                goto exit;

Soeren.
--- 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,51 @@ static inline int atp_is_geyser_3(struct atp *dev)
 		(productId == GEYSER4_JIS_PRODUCT_ID);
 }
 
+static int atp_geyser3_init(struct usb_device *udev)
+{
+	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)");
+		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) {
+		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)
 {
@@ -441,7 +488,6 @@ static void atp_complete(struct urb* urb)
 		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);
@@ -449,10 +495,33 @@ static void atp_complete(struct urb* urb)
 
 		/* reset the accumulator on release */
 		memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+
+		/* Geyser 3 will continue to send packets continually after
+		   the first touch unless reinitialised. Do so if it's been
+		   idle for a while in order to avoid waking the kernel up
+		   several hundred times a second */
+		if (atp_is_geyser_3(dev)) {
+			dev->idlecount++;
+			if (dev->idlecount == 10) {
+				if (dev->data[dev->datalen-1] != 20) 
+					input_report_key(dev->input, BTN_LEFT,
+							!!dev->data[dev->datalen - 1]);
+
+				input_sync(dev->input);
+				schedule_work (&dev->work);
+
+				goto exit;
+			}
+		}
 	}
 
-	input_report_key(dev->input, BTN_LEFT,
-			 !!dev->data[dev->datalen - 1]);
+	if (dev->data[dev->datalen-1] != 20) 
+		input_report_key(dev->input, BTN_LEFT,
+				 !!dev->data[dev->datalen - 1]);
 
 	input_sync(dev->input);
 
@@ -466,7 +535,7 @@ exit:
 
 static int atp_open(struct input_dev *input)
 {
-	struct atp *dev = input_get_drvdata(input);
+	struct atp *dev = input->private;
 
 	if (usb_submit_urb(dev->urb, GFP_ATOMIC))
 		return -EIO;
@@ -477,7 +546,7 @@ static int atp_open(struct input_dev *input)
 
 static void atp_close(struct input_dev *input)
 {
-	struct atp *dev = input_get_drvdata(input);
+	struct atp *dev = input->private;
 
 	usb_kill_urb(dev->urb);
 	dev->open = 0;
@@ -491,7 +560,8 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	int int_in_endpointAddr = 0;
-	int i, error = -ENOMEM;
+	int i, retval = -ENOMEM;
+
 
 	/* set up the endpoint information */
 	/* use only the first interrupt-in endpoint */
@@ -533,50 +603,28 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
 		 * 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)");
+		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");
 	}
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->urb)
+	if (!dev->urb) {
+		retval = -ENOMEM;
 		goto err_free_devs;
+	}
 
 	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
-	if (!dev->data)
+	if (!dev->data) {
+		retval = -ENOMEM;
 		goto err_free_urb;
+	}
 
 	usb_fill_int_urb(dev->urb, udev,
 			 usb_rcvintpipe(udev, int_in_endpointAddr),
-			 dev->data, dev->datalen, atp_complete, dev, 1);
+			 dev->data, dev->datalen, atp_complete, dev, 2);
 
 	usb_make_path(udev, dev->phys, sizeof(dev->phys));
 	strlcat(dev->phys, "/input0", sizeof(dev->phys));
@@ -584,10 +632,9 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
 	input_dev->name = "appletouch";
 	input_dev->phys = dev->phys;
 	usb_to_input_id(dev->udev, &input_dev->id);
-	input_dev->dev.parent = &iface->dev;
-
-	input_set_drvdata(input_dev, dev);
+	input_dev->cdev.dev = &iface->dev;
 
+	input_dev->private = dev;
 	input_dev->open = atp_open;
 	input_dev->close = atp_close;
 
@@ -629,25 +676,22 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
 	set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
 	set_bit(BTN_LEFT, input_dev->keybit);
 
-	error = input_register_device(dev->input);
-	if (error)
-		goto err_free_buffer;
+	input_register_device(dev->input);
 
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(iface, dev);
 
+	INIT_WORK(&dev->work, atp_reinit);
+
 	return 0;
 
- err_free_buffer:
-	usb_buffer_free(dev->udev, dev->datalen,
-			dev->data, dev->urb->transfer_dma);
  err_free_urb:
 	usb_free_urb(dev->urb);
  err_free_devs:
 	usb_set_intfdata(iface, NULL);
 	kfree(dev);
 	input_free_device(input_dev);
-	return error;
+	return retval;
 }
 
 static void atp_disconnect(struct usb_interface *iface)
-------------------------------------------------------------------------
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