diff options
Diffstat (limited to 'drivers/usb/input/appletouch.c')
| -rw-r--r-- | drivers/usb/input/appletouch.c | 117 |
1 files changed, 108 insertions, 9 deletions
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index c222ed13deab..36855062eacc 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Apple USB Touchpad (for post-February 2005 PowerBooks) driver | 2 | * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | 4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) |
| 5 | * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) | 5 | * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) |
| @@ -7,6 +7,7 @@ | |||
| 7 | * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) | 7 | * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) |
| 8 | * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) | 8 | * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) |
| 9 | * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) | 9 | * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) |
| 10 | * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) | ||
| 10 | * | 11 | * |
| 11 | * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. | 12 | * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. |
| 12 | * | 13 | * |
| @@ -32,9 +33,7 @@ | |||
| 32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
| 33 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 34 | #include <linux/module.h> | 35 | #include <linux/module.h> |
| 35 | #include <linux/usb.h> | 36 | #include <linux/usb/input.h> |
| 36 | #include <linux/input.h> | ||
| 37 | #include <linux/usb_input.h> | ||
| 38 | 37 | ||
| 39 | /* Apple has powerbooks which have the keyboard with different Product IDs */ | 38 | /* Apple has powerbooks which have the keyboard with different Product IDs */ |
| 40 | #define APPLE_VENDOR_ID 0x05AC | 39 | #define APPLE_VENDOR_ID 0x05AC |
| @@ -44,6 +43,11 @@ | |||
| 44 | #define GEYSER_ISO_PRODUCT_ID 0x0215 | 43 | #define GEYSER_ISO_PRODUCT_ID 0x0215 |
| 45 | #define GEYSER_JIS_PRODUCT_ID 0x0216 | 44 | #define GEYSER_JIS_PRODUCT_ID 0x0216 |
| 46 | 45 | ||
| 46 | /* MacBook devices */ | ||
| 47 | #define GEYSER3_ANSI_PRODUCT_ID 0x0217 | ||
| 48 | #define GEYSER3_ISO_PRODUCT_ID 0x0218 | ||
| 49 | #define GEYSER3_JIS_PRODUCT_ID 0x0219 | ||
| 50 | |||
| 47 | #define ATP_DEVICE(prod) \ | 51 | #define ATP_DEVICE(prod) \ |
| 48 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ | 52 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ |
| 49 | USB_DEVICE_ID_MATCH_INT_CLASS | \ | 53 | USB_DEVICE_ID_MATCH_INT_CLASS | \ |
| @@ -65,6 +69,10 @@ static struct usb_device_id atp_table [] = { | |||
| 65 | { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, | 69 | { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, |
| 66 | { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, | 70 | { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, |
| 67 | 71 | ||
| 72 | { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) }, | ||
| 73 | { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) }, | ||
| 74 | { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) }, | ||
| 75 | |||
| 68 | /* Terminating entry */ | 76 | /* Terminating entry */ |
| 69 | { } | 77 | { } |
| 70 | }; | 78 | }; |
| @@ -101,6 +109,13 @@ MODULE_DEVICE_TABLE (usb, atp_table); | |||
| 101 | */ | 109 | */ |
| 102 | #define ATP_THRESHOLD 5 | 110 | #define ATP_THRESHOLD 5 |
| 103 | 111 | ||
| 112 | /* MacBook Pro (Geyser 3) initialization constants */ | ||
| 113 | #define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 | ||
| 114 | #define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 | ||
| 115 | #define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 | ||
| 116 | #define ATP_GEYSER3_MODE_REQUEST_INDEX 0 | ||
| 117 | #define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04 | ||
| 118 | |||
| 104 | /* Structure to hold all of our device specific stuff */ | 119 | /* Structure to hold all of our device specific stuff */ |
| 105 | struct atp { | 120 | struct atp { |
| 106 | char phys[64]; | 121 | char phys[64]; |
| @@ -147,13 +162,22 @@ MODULE_PARM_DESC(debug, "Activate debugging output"); | |||
| 147 | /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ | 162 | /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ |
| 148 | static inline int atp_is_geyser_2(struct atp *dev) | 163 | static inline int atp_is_geyser_2(struct atp *dev) |
| 149 | { | 164 | { |
| 150 | int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct); | 165 | u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); |
| 151 | 166 | ||
| 152 | return (productId == GEYSER_ANSI_PRODUCT_ID) || | 167 | return (productId == GEYSER_ANSI_PRODUCT_ID) || |
| 153 | (productId == GEYSER_ISO_PRODUCT_ID) || | 168 | (productId == GEYSER_ISO_PRODUCT_ID) || |
| 154 | (productId == GEYSER_JIS_PRODUCT_ID); | 169 | (productId == GEYSER_JIS_PRODUCT_ID); |
| 155 | } | 170 | } |
| 156 | 171 | ||
| 172 | static inline int atp_is_geyser_3(struct atp *dev) | ||
| 173 | { | ||
| 174 | u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); | ||
| 175 | |||
| 176 | return (productId == GEYSER3_ANSI_PRODUCT_ID) || | ||
| 177 | (productId == GEYSER3_ISO_PRODUCT_ID) || | ||
| 178 | (productId == GEYSER3_JIS_PRODUCT_ID); | ||
| 179 | } | ||
| 180 | |||
| 157 | static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, | 181 | static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, |
| 158 | int *z, int *fingers) | 182 | int *z, int *fingers) |
| 159 | { | 183 | { |
| @@ -219,12 +243,33 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) | |||
| 219 | 243 | ||
| 220 | /* drop incomplete datasets */ | 244 | /* drop incomplete datasets */ |
| 221 | if (dev->urb->actual_length != dev->datalen) { | 245 | if (dev->urb->actual_length != dev->datalen) { |
| 222 | dprintk("appletouch: incomplete data package.\n"); | 246 | dprintk("appletouch: incomplete data package" |
| 247 | " (first byte: %d, length: %d).\n", | ||
| 248 | dev->data[0], dev->urb->actual_length); | ||
| 223 | goto exit; | 249 | goto exit; |
| 224 | } | 250 | } |
| 225 | 251 | ||
| 226 | /* reorder the sensors values */ | 252 | /* reorder the sensors values */ |
| 227 | if (atp_is_geyser_2(dev)) { | 253 | if (atp_is_geyser_3(dev)) { |
| 254 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | ||
| 255 | |||
| 256 | /* | ||
| 257 | * The values are laid out like this: | ||
| 258 | * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... | ||
| 259 | * '-' is an unused value. | ||
| 260 | */ | ||
| 261 | |||
| 262 | /* read X values */ | ||
| 263 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | ||
| 264 | dev->xy_cur[i] = dev->data[j + 1]; | ||
| 265 | dev->xy_cur[i + 1] = dev->data[j + 2]; | ||
| 266 | } | ||
| 267 | /* read Y values */ | ||
| 268 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | ||
| 269 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; | ||
| 270 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; | ||
| 271 | } | ||
| 272 | } else if (atp_is_geyser_2(dev)) { | ||
| 228 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | 273 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); |
| 229 | 274 | ||
| 230 | /* | 275 | /* |
| @@ -267,6 +312,9 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) | |||
| 267 | dev->x_old = dev->y_old = -1; | 312 | dev->x_old = dev->y_old = -1; |
| 268 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | 313 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); |
| 269 | 314 | ||
| 315 | if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ | ||
| 316 | goto exit; | ||
| 317 | |||
| 270 | /* 17" Powerbooks have extra X sensors */ | 318 | /* 17" Powerbooks have extra X sensors */ |
| 271 | for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { | 319 | for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { |
| 272 | if (!dev->xy_cur[i]) continue; | 320 | if (!dev->xy_cur[i]) continue; |
| @@ -414,7 +462,50 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id | |||
| 414 | dev->udev = udev; | 462 | dev->udev = udev; |
| 415 | dev->input = input_dev; | 463 | dev->input = input_dev; |
| 416 | dev->overflowwarn = 0; | 464 | dev->overflowwarn = 0; |
| 417 | dev->datalen = (atp_is_geyser_2(dev)?64:81); | 465 | if (atp_is_geyser_3(dev)) |
| 466 | dev->datalen = 64; | ||
| 467 | else if (atp_is_geyser_2(dev)) | ||
| 468 | dev->datalen = 64; | ||
| 469 | else | ||
| 470 | dev->datalen = 81; | ||
| 471 | |||
| 472 | if (atp_is_geyser_3(dev)) { | ||
| 473 | /* | ||
| 474 | * By default Geyser 3 device sends standard USB HID mouse | ||
| 475 | * packets (Report ID 2). This code changes device mode, so it | ||
| 476 | * sends raw sensor reports (Report ID 5). | ||
| 477 | */ | ||
| 478 | char data[8]; | ||
| 479 | int size; | ||
| 480 | |||
| 481 | size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 482 | ATP_GEYSER3_MODE_READ_REQUEST_ID, | ||
| 483 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
| 484 | ATP_GEYSER3_MODE_REQUEST_VALUE, | ||
| 485 | ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); | ||
| 486 | |||
| 487 | if (size != 8) { | ||
| 488 | err("Could not do mode read request from device" | ||
| 489 | " (Geyser 3 mode)"); | ||
| 490 | goto err_free_devs; | ||
| 491 | } | ||
| 492 | |||
| 493 | /* Apply the mode switch */ | ||
| 494 | data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE; | ||
| 495 | |||
| 496 | size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 497 | ATP_GEYSER3_MODE_WRITE_REQUEST_ID, | ||
| 498 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
| 499 | ATP_GEYSER3_MODE_REQUEST_VALUE, | ||
| 500 | ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); | ||
| 501 | |||
| 502 | if (size != 8) { | ||
| 503 | err("Could not do mode write request to device" | ||
| 504 | " (Geyser 3 mode)"); | ||
| 505 | goto err_free_devs; | ||
| 506 | } | ||
| 507 | printk("appletouch Geyser 3 inited.\n"); | ||
| 508 | } | ||
| 418 | 509 | ||
| 419 | dev->urb = usb_alloc_urb(0, GFP_KERNEL); | 510 | dev->urb = usb_alloc_urb(0, GFP_KERNEL); |
| 420 | if (!dev->urb) { | 511 | if (!dev->urb) { |
| @@ -447,7 +538,15 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id | |||
| 447 | 538 | ||
| 448 | set_bit(EV_ABS, input_dev->evbit); | 539 | set_bit(EV_ABS, input_dev->evbit); |
| 449 | 540 | ||
| 450 | if (atp_is_geyser_2(dev)) { | 541 | if (atp_is_geyser_3(dev)) { |
| 542 | /* | ||
| 543 | * MacBook have 20 X sensors, 10 Y sensors | ||
| 544 | */ | ||
| 545 | input_set_abs_params(input_dev, ABS_X, 0, | ||
| 546 | ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); | ||
| 547 | input_set_abs_params(input_dev, ABS_Y, 0, | ||
| 548 | ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); | ||
| 549 | } else if (atp_is_geyser_2(dev)) { | ||
| 451 | /* | 550 | /* |
| 452 | * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected | 551 | * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected |
| 453 | * later. | 552 | * later. |
