diff options
Diffstat (limited to 'drivers/input/mouse/appletouch.c')
-rw-r--r-- | drivers/input/mouse/appletouch.c | 299 |
1 files changed, 138 insertions, 161 deletions
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index ce6fdec19e1..1f41ae94f26 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -2,12 +2,13 @@ * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver * * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) + * Copyright (C) 2005-2008 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 Michael Hanselmann (linux-kernel@hansmi.ch) * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) + * Copyright (C) 2007-2008 Sven Anders (anders@anduras.de) * * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. * @@ -34,77 +35,64 @@ #include <linux/module.h> #include <linux/usb/input.h> -/* 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 FOUNTAIN_ANSI_PRODUCT_ID 0x020E -#define FOUNTAIN_ISO_PRODUCT_ID 0x020F - -#define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A - -#define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B - -#define GEYSER_ANSI_PRODUCT_ID 0x0214 -#define GEYSER_ISO_PRODUCT_ID 0x0215 -#define GEYSER_JIS_PRODUCT_ID 0x0216 - -/* MacBook devices */ -#define GEYSER3_ANSI_PRODUCT_ID 0x0217 -#define GEYSER3_ISO_PRODUCT_ID 0x0218 -#define GEYSER3_JIS_PRODUCT_ID 0x0219 - -/* - * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext - * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables - */ -#define GEYSER4_ANSI_PRODUCT_ID 0x021A -#define GEYSER4_ISO_PRODUCT_ID 0x021B -#define GEYSER4_JIS_PRODUCT_ID 0x021C - -#define GEYSER4_HF_ANSI_PRODUCT_ID 0x0229 -#define GEYSER4_HF_ISO_PRODUCT_ID 0x022A -#define GEYSER4_HF_JIS_PRODUCT_ID 0x022B +/* Type of touchpad */ +enum atp_touchpad_type { + ATP_FOUNTAIN, + ATP_GEYSER1, + ATP_GEYSER2, + ATP_GEYSER3, + ATP_GEYSER4 +}; -#define ATP_DEVICE(prod) \ +#define ATP_DEVICE(prod, type) \ +{ \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ USB_DEVICE_ID_MATCH_INT_CLASS | \ USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ - .idVendor = APPLE_VENDOR_ID, \ + .idVendor = 0x05ac, /* Apple */ \ .idProduct = (prod), \ .bInterfaceClass = 0x03, \ - .bInterfaceProtocol = 0x02 + .bInterfaceProtocol = 0x02, \ + .driver_info = ATP_ ## type, \ +} + +/* + * Table of devices (Product IDs) that work with this driver. + * (The names come from Info.plist in AppleUSBTrackpad.kext, + * According to Info.plist Geyser IV is the same as Geyser III.) + */ -/* table of devices that work with this driver */ static struct usb_device_id atp_table [] = { - { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) }, - { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) }, - { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) }, + /* PowerBooks Feb 2005, iBooks G4 */ + ATP_DEVICE(0x020e, FOUNTAIN), /* FOUNTAIN ANSI */ + ATP_DEVICE(0x020f, FOUNTAIN), /* FOUNTAIN ISO */ + ATP_DEVICE(0x030a, FOUNTAIN), /* FOUNTAIN TP ONLY */ + ATP_DEVICE(0x030b, GEYSER1), /* GEYSER 1 TP ONLY */ /* PowerBooks Oct 2005 */ - { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, + ATP_DEVICE(0x0214, GEYSER2), /* GEYSER 2 ANSI */ + ATP_DEVICE(0x0215, GEYSER2), /* GEYSER 2 ISO */ + ATP_DEVICE(0x0216, GEYSER2), /* GEYSER 2 JIS */ /* Core Duo MacBook & MacBook Pro */ - { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) }, + ATP_DEVICE(0x0217, GEYSER3), /* GEYSER 3 ANSI */ + ATP_DEVICE(0x0218, GEYSER3), /* GEYSER 3 ISO */ + ATP_DEVICE(0x0219, GEYSER3), /* GEYSER 3 JIS */ /* Core2 Duo MacBook & MacBook Pro */ - { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) }, + ATP_DEVICE(0x021a, GEYSER4), /* GEYSER 4 ANSI */ + ATP_DEVICE(0x021b, GEYSER4), /* GEYSER 4 ISO */ + ATP_DEVICE(0x021c, GEYSER4), /* GEYSER 4 JIS */ - { ATP_DEVICE(GEYSER4_HF_ANSI_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER4_HF_ISO_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER4_HF_JIS_PRODUCT_ID) }, + /* Core2 Duo MacBook3,1 */ + ATP_DEVICE(0x0229, GEYSER4), /* GEYSER 4 HF ANSI */ + ATP_DEVICE(0x022a, GEYSER4), /* GEYSER 4 HF ISO */ + ATP_DEVICE(0x022b, GEYSER4), /* GEYSER 4 HF JIS */ /* Terminating entry */ { } }; -MODULE_DEVICE_TABLE (usb, atp_table); +MODULE_DEVICE_TABLE(usb, atp_table); /* * number of sensors. Note that only 16 instead of 26 X (horizontal) @@ -124,9 +112,13 @@ MODULE_DEVICE_TABLE (usb, atp_table); * 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 + * + * 0 <= x < 960 on 12" and 15" Powerbooks + * 0 <= x < 1600 on 17" Powerbooks and 17" MacBook Pro + * 0 <= x < 1216 on MacBooks and 15" MacBook Pro + * + * 0 <= y < 646 on all Powerbooks + * 0 <= y < 774 on all MacBooks */ #define ATP_XFACT 64 #define ATP_YFACT 43 @@ -147,43 +139,46 @@ MODULE_DEVICE_TABLE (usb, atp_table); /* Structure to hold all of our device specific stuff */ struct atp { char phys[64]; - struct usb_device * udev; /* usb device */ - struct urb * urb; /* usb request block */ - signed char * data; /* transferred data */ - struct input_dev * input; /* input dev */ - unsigned char open; /* non-zero if opened */ - unsigned char valid; /* are the sensors valid ? */ - unsigned char size_detect_done; - unsigned char overflowwarn; /* overflow warning printed? */ + struct usb_device *udev; /* usb device */ + struct urb *urb; /* usb request block */ + signed char *data; /* transferred data */ + struct input_dev *input; /* input dev */ + enum atp_touchpad_type type; /* type of touchpad */ + bool open; + bool valid; /* are the samples valid? */ + bool size_detect_done; + bool overflow_warned; int x_old; /* last reported x/y, */ int y_old; /* used for smoothing */ - /* current value of the sensors */ signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; - /* last value of the sensors */ signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; - /* accumulated sensors */ int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; - int datalen; /* size of an USB urb transfer */ - int idlecount; /* number of empty packets */ - struct work_struct work; + int datalen; /* size of USB transfer */ + int idlecount; /* number of empty packets */ + struct work_struct work; }; #define dbg_dump(msg, tab) \ if (debug > 1) { \ - int i; \ - printk("appletouch: %s %lld", msg, (long long)jiffies); \ - for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \ - printk(" %02x", tab[i]); \ + int __i; \ + printk(KERN_DEBUG "appletouch: %s", msg); \ + for (__i = 0; __i < ATP_XSENSORS + ATP_YSENSORS; __i++) \ + printk(" %02x", tab[__i]); \ printk("\n"); \ } #define dprintk(format, a...) \ do { \ - if (debug) printk(KERN_DEBUG format, ##a); \ + if (debug) \ + printk(KERN_DEBUG format, ##a); \ } while (0) -MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); -MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver"); +MODULE_AUTHOR("Johannes Berg"); +MODULE_AUTHOR("Stelian Pop"); +MODULE_AUTHOR("Frank Arnold"); +MODULE_AUTHOR("Michael Hanselmann"); +MODULE_AUTHOR("Sven Anders"); +MODULE_DESCRIPTION("Apple PowerBook and MacBook USB touchpad driver"); MODULE_LICENSE("GPL"); /* @@ -191,46 +186,14 @@ MODULE_LICENSE("GPL"); */ static int threshold = ATP_THRESHOLD; module_param(threshold, int, 0644); -MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value"); +MODULE_PARM_DESC(threshold, "Discard any change in data from a sensor" + " (the trackpad has many of these sensors)" + " less than this value."); -static int debug = 1; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activate debugging output"); -static inline int atp_is_fountain(struct atp *dev) -{ - u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); - - return productId == FOUNTAIN_ANSI_PRODUCT_ID || - productId == FOUNTAIN_ISO_PRODUCT_ID || - productId == FOUNTAIN_TP_ONLY_PRODUCT_ID; -} - -/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ -static inline int atp_is_geyser_2(struct atp *dev) -{ - u16 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 inline int atp_is_geyser_3(struct atp *dev) -{ - u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); - - return (productId == GEYSER3_ANSI_PRODUCT_ID) || - (productId == GEYSER3_ISO_PRODUCT_ID) || - (productId == GEYSER3_JIS_PRODUCT_ID) || - (productId == GEYSER4_ANSI_PRODUCT_ID) || - (productId == GEYSER4_ISO_PRODUCT_ID) || - (productId == GEYSER4_JIS_PRODUCT_ID) || - (productId == GEYSER4_HF_ANSI_PRODUCT_ID) || - (productId == GEYSER4_HF_ISO_PRODUCT_ID) || - (productId == GEYSER4_HF_JIS_PRODUCT_ID); -} - /* * By default newer Geyser devices send standard USB HID mouse * packets (Report ID 2). This code changes device mode, so it @@ -240,6 +203,7 @@ static int atp_geyser_init(struct usb_device *udev) { char data[8]; int size; + int i; size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ATP_GEYSER_MODE_READ_REQUEST_ID, @@ -248,8 +212,11 @@ static int atp_geyser_init(struct usb_device *udev) ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); if (size != 8) { - err("Could not do mode read request from device" - " (Geyser Raw mode)"); + dprintk("atp_geyser_init: read error\n"); + for (i = 0; i < 8; i++) + dprintk("appletouch[%d]: %d\n", i, data[i]); + + err("Failed to read mode from device."); return -EIO; } @@ -263,8 +230,11 @@ static int atp_geyser_init(struct usb_device *udev) ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); if (size != 8) { - err("Could not do mode write request to device" - " (Geyser Raw mode)"); + dprintk("atp_geyser_init: write error\n"); + for (i = 0; i < 8; i++) + dprintk("appletouch[%d]: %d\n", i, data[i]); + + err("Failed to request geyser raw mode"); return -EIO; } return 0; @@ -280,15 +250,15 @@ static void atp_reinit(struct work_struct *work) struct usb_device *udev = dev->udev; int retval; + dprintk("appletouch: putting appletouch to sleep (reinit)\n"); dev->idlecount = 0; atp_geyser_init(udev); retval = usb_submit_urb(dev->urb, GFP_ATOMIC); - if (retval) { - err("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); - } + if (retval) + err("atp_reinit: usb_submit_urb failed with error %d", + retval); } static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, @@ -323,7 +293,8 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, * * - Jason Parekh <jasonparekh@gmail.com> */ - if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { + if (i < 1 || + (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { (*fingers)++; is_increasing = 1; } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) { @@ -331,11 +302,11 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, } /* - * Subtracts threshold so a high sensor that just passes the threshold - * won't skew the calculated absolute coordinate. Fixes an issue - * where slowly moving the mouse would occassionaly jump a number of - * pixels (let me restate--slowly moving the mouse makes this issue - * most apparent). + * Subtracts threshold so a high sensor that just passes the + * threshold won't skew the calculated absolute coordinate. + * Fixes an issue where slowly moving the mouse would + * occasionally jump a number of pixels (slowly moving the + * finger makes this issue most apparent.) */ pcum += (xy_sensors[i] - threshold) * i; psum += (xy_sensors[i] - threshold); @@ -356,7 +327,7 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers) input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); } -static void atp_complete(struct urb* urb) +static void atp_complete(struct urb *urb) { int x, y, x_z, y_z, x_f, y_f; int retval, i, j; @@ -368,22 +339,22 @@ static void atp_complete(struct urb* urb) /* success */ break; case -EOVERFLOW: - if(!dev->overflowwarn) { + if (!dev->overflow_warned) { printk(KERN_WARNING "appletouch: OVERFLOW with data " "length %d, actual length is %d\n", dev->datalen, dev->urb->actual_length); - dev->overflowwarn = 1; + dev->overflow_warned = true; } case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* This urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __FUNCTION__, urb->status); + dbg("atp_complete: urb shutting down with status: %d", + urb->status); return; default: - dbg("%s - nonzero urb status received: %d", - __FUNCTION__, urb->status); + dbg("atp_complete: nonzero urb status received: %d", + urb->status); goto exit; } @@ -396,7 +367,7 @@ static void atp_complete(struct urb* urb) } /* reorder the sensors values */ - if (atp_is_geyser_3(dev)) { + if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) { memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); /* @@ -415,7 +386,7 @@ static void atp_complete(struct urb* urb) dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; } - } else if (atp_is_geyser_2(dev)) { + } else if (dev->type == ATP_GEYSER2) { memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); /* @@ -438,7 +409,7 @@ static void atp_complete(struct urb* urb) } else { for (i = 0; i < 8; i++) { /* X values */ - dev->xy_cur[i ] = dev->data[5 * i + 2]; + dev->xy_cur[i + 0] = 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) @@ -454,21 +425,22 @@ static void atp_complete(struct urb* urb) if (!dev->valid) { /* first sample */ - dev->valid = 1; + dev->valid = true; dev->x_old = dev->y_old = -1; memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); if (dev->size_detect_done || - atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ + dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */ goto exit; /* 17" Powerbooks have extra X sensors */ - for (i = (atp_is_geyser_2(dev) ? 15 : 16); i < ATP_XSENSORS; i++) { + for (i = (dev->type == ATP_GEYSER2 ? 15 : 16); + i < ATP_XSENSORS; i++) { if (!dev->xy_cur[i]) continue; printk(KERN_INFO "appletouch: 17\" model detected.\n"); - if (atp_is_geyser_2(dev)) + if (dev->type == ATP_GEYSER2) input_set_abs_params(dev->input, ABS_X, 0, (20 - 1) * ATP_XFACT - 1, @@ -548,11 +520,15 @@ static void atp_complete(struct urb* urb) * several hundred times a second. Re-initialization does not * work on Fountain touchpads. */ - if (!atp_is_fountain(dev)) { + if (dev->type != ATP_FOUNTAIN) { + /* + * Button must not be pressed when entering suspend, + * otherwise we will never release the button. + */ if (!x && !y && !key) { dev->idlecount++; if (dev->idlecount == 10) { - dev->valid = 0; + dev->valid = false; schedule_work(&dev->work); /* Don't resubmit urb here, wait for reinit */ return; @@ -561,12 +537,11 @@ static void atp_complete(struct urb* urb) dev->idlecount = 0; } -exit: + exit: retval = usb_submit_urb(dev->urb, GFP_ATOMIC); - if (retval) { - err("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); - } + if (retval) + err("atp_complete: usb_submit_urb failed with result %d", + retval); } static int atp_open(struct input_dev *input) @@ -593,7 +568,7 @@ static int atp_handle_geyser(struct atp *dev) { struct usb_device *udev = dev->udev; - if (!atp_is_fountain(dev)) { + if (dev->type != ATP_FOUNTAIN) { /* switch to raw sensor mode */ if (atp_geyser_init(udev)) return -EIO; @@ -604,7 +579,8 @@ static int atp_handle_geyser(struct atp *dev) return 0; } -static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id) +static int atp_probe(struct usb_interface *iface, + const struct usb_device_id *id) { struct atp *dev; struct input_dev *input_dev; @@ -640,13 +616,12 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id dev->udev = udev; dev->input = input_dev; - dev->overflowwarn = 0; - if (atp_is_geyser_3(dev)) - dev->datalen = 64; - else if (atp_is_geyser_2(dev)) - dev->datalen = 64; - else + dev->type = id->driver_info; + dev->overflow_warned = false; + if (dev->type == ATP_FOUNTAIN || dev->type == ATP_GEYSER1) dev->datalen = 81; + else + dev->datalen = 64; dev->urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urb) @@ -680,7 +655,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id set_bit(EV_ABS, input_dev->evbit); - if (atp_is_geyser_3(dev)) { + if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) { /* * MacBook have 20 X sensors, 10 Y sensors */ @@ -688,7 +663,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); input_set_abs_params(input_dev, ABS_Y, 0, ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); - } else if (atp_is_geyser_2(dev)) { + } else if (dev->type == ATP_GEYSER2) { /* * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected * later. @@ -703,9 +678,11 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id * 17" models are detected later. */ input_set_abs_params(input_dev, ABS_X, 0, - (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 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); + (ATP_YSENSORS - 1) * ATP_YFACT - 1, + ATP_FUZZ, 0); } input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); @@ -774,7 +751,7 @@ 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; + dev->valid = false; return 0; } |