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