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. |