Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: appletouch - add support for Geyser 2

This patch adds support for the Geyser 2 touchpads used on post Oct 2005
Apple PowerBooks to the appletouch driver.

Signed-off-by: Michael Hanselmann <linux-kernel@hansmi.ch>
Acked-by: Rene Nussbaumer <linux-kernel@killerfox.forkbomb.ch>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Stelian Pop <stelian@popies.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Michael Hanselmann and committed by
Dmitry Torokhov
e1e02c9f 041387d9

+111 -37
+3 -2
Documentation/input/appletouch.txt
··· 3 3 Copyright (C) 2005 Stelian Pop <stelian@popies.net> 4 4 5 5 appletouch is a Linux kernel driver for the USB touchpad found on post 6 - February 2005 Apple Alu Powerbooks. 6 + February 2005 and October 2005 Apple Aluminium Powerbooks. 7 7 8 8 This driver is derived from Johannes Berg's appletrackpad driver[1], but it has 9 9 been improved in some areas: ··· 13 13 14 14 Credits go to Johannes Berg for reverse-engineering the touchpad protocol, 15 15 Frank Arnold for further improvements, and Alex Harper for some additional 16 - information about the inner workings of the touchpad sensors. 16 + information about the inner workings of the touchpad sensors. Michael 17 + Hanselmann added support for the October 2005 models. 17 18 18 19 Usage: 19 20 ------
+108 -35
drivers/usb/input/appletouch.c
··· 6 6 * Copyright (C) 2005 Stelian Pop (stelian@popies.net) 7 7 * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) 8 8 * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) 9 + * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) 9 10 * 10 11 * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. 11 12 * ··· 39 38 /* Apple has powerbooks which have the keyboard with different Product IDs */ 40 39 #define APPLE_VENDOR_ID 0x05AC 41 40 41 + /* These names come from Info.plist in AppleUSBTrackpad.kext */ 42 + #define GEYSER_ANSI_PRODUCT_ID 0x0214 43 + #define GEYSER_ISO_PRODUCT_ID 0x0215 44 + #define GEYSER_JIS_PRODUCT_ID 0x0216 45 + 42 46 #define ATP_DEVICE(prod) \ 43 47 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ 44 48 USB_DEVICE_ID_MATCH_INT_CLASS | \ ··· 59 53 { ATP_DEVICE(0x020F) }, 60 54 { ATP_DEVICE(0x030A) }, 61 55 { ATP_DEVICE(0x030B) }, 62 - { } /* Terminating entry */ 56 + 57 + /* PowerBooks Oct 2005 */ 58 + { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) }, 59 + { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, 60 + { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, 61 + 62 + /* Terminating entry */ 63 + { } 63 64 }; 64 65 MODULE_DEVICE_TABLE (usb, atp_table); 65 - 66 - /* size of a USB urb transfer */ 67 - #define ATP_DATASIZE 81 68 66 69 67 /* 70 68 * number of sensors. Note that only 16 instead of 26 X (horizontal) ··· 118 108 signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; 119 109 /* accumulated sensors */ 120 110 int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; 111 + int overflowwarn; /* overflow warning printed? */ 112 + int datalen; /* size of an USB urb transfer */ 121 113 }; 122 114 123 115 #define dbg_dump(msg, tab) \ ··· 136 124 if (debug) printk(format, ##a); \ 137 125 } while (0) 138 126 139 - MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold"); 127 + MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); 140 128 MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver"); 141 129 MODULE_LICENSE("GPL"); 142 130 143 131 static int debug = 1; 144 132 module_param(debug, int, 0644); 145 133 MODULE_PARM_DESC(debug, "Activate debugging output"); 134 + 135 + /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ 136 + static inline int atp_is_geyser_2(struct atp *dev) 137 + { 138 + int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct); 139 + 140 + return (productId == GEYSER_ANSI_PRODUCT_ID) || 141 + (productId == GEYSER_ISO_PRODUCT_ID) || 142 + (productId == GEYSER_JIS_PRODUCT_ID); 143 + } 146 144 147 145 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, 148 146 int *z, int *fingers) ··· 190 168 static void atp_complete(struct urb* urb, struct pt_regs* regs) 191 169 { 192 170 int x, y, x_z, y_z, x_f, y_f; 193 - int retval, i; 171 + int retval, i, j; 194 172 struct atp *dev = urb->context; 195 173 196 174 switch (urb->status) { 197 175 case 0: 198 176 /* success */ 199 177 break; 178 + case -EOVERFLOW: 179 + if(!dev->overflowwarn) { 180 + printk("appletouch: OVERFLOW with data " 181 + "length %d, actual length is %d\n", 182 + dev->datalen, dev->urb->actual_length); 183 + dev->overflowwarn = 1; 184 + } 200 185 case -ECONNRESET: 201 186 case -ENOENT: 202 187 case -ESHUTDOWN: ··· 218 189 } 219 190 220 191 /* drop incomplete datasets */ 221 - if (dev->urb->actual_length != ATP_DATASIZE) { 192 + if (dev->urb->actual_length != dev->datalen) { 222 193 dprintk("appletouch: incomplete data package.\n"); 223 194 goto exit; 224 195 } 225 196 226 197 /* reorder the sensors values */ 227 - for (i = 0; i < 8; i++) { 228 - /* X values */ 229 - dev->xy_cur[i ] = dev->data[5 * i + 2]; 230 - dev->xy_cur[i + 8] = dev->data[5 * i + 4]; 231 - dev->xy_cur[i + 16] = dev->data[5 * i + 42]; 232 - if (i < 2) 233 - dev->xy_cur[i + 24] = dev->data[5 * i + 44]; 198 + if (atp_is_geyser_2(dev)) { 199 + memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); 234 200 235 - /* Y values */ 236 - dev->xy_cur[i + 26] = dev->data[5 * i + 1]; 237 - dev->xy_cur[i + 34] = dev->data[5 * i + 3]; 201 + /* 202 + * The values are laid out like this: 203 + * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ... 204 + * '-' is an unused value. 205 + */ 206 + 207 + /* read X values */ 208 + for (i = 0, j = 19; i < 20; i += 2, j += 3) { 209 + dev->xy_cur[i] = dev->data[j]; 210 + dev->xy_cur[i + 1] = dev->data[j + 1]; 211 + } 212 + 213 + /* read Y values */ 214 + for (i = 0, j = 1; i < 9; i += 2, j += 3) { 215 + dev->xy_cur[ATP_XSENSORS + i] = dev->data[j]; 216 + dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1]; 217 + } 218 + } else { 219 + for (i = 0; i < 8; i++) { 220 + /* X values */ 221 + dev->xy_cur[i ] = dev->data[5 * i + 2]; 222 + dev->xy_cur[i + 8] = dev->data[5 * i + 4]; 223 + dev->xy_cur[i + 16] = dev->data[5 * i + 42]; 224 + if (i < 2) 225 + dev->xy_cur[i + 24] = dev->data[5 * i + 44]; 226 + 227 + /* Y values */ 228 + dev->xy_cur[i + 26] = dev->data[5 * i + 1]; 229 + dev->xy_cur[i + 34] = dev->data[5 * i + 3]; 230 + } 238 231 } 239 232 240 233 dbg_dump("sample", dev->xy_cur); ··· 267 216 dev->x_old = dev->y_old = -1; 268 217 memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); 269 218 270 - /* 17" Powerbooks have 10 extra X sensors */ 271 - for (i = 16; i < ATP_XSENSORS; i++) 272 - if (dev->xy_cur[i]) { 273 - printk("appletouch: 17\" model detected.\n"); 219 + /* 17" Powerbooks have extra X sensors */ 220 + for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { 221 + if (!dev->xy_cur[i]) continue; 222 + 223 + printk("appletouch: 17\" model detected.\n"); 224 + if(atp_is_geyser_2(dev)) 225 + input_set_abs_params(dev->input, ABS_X, 0, 226 + (20 - 1) * 227 + ATP_XFACT - 1, 228 + ATP_FUZZ, 0); 229 + else 274 230 input_set_abs_params(dev->input, ABS_X, 0, 275 231 (ATP_XSENSORS - 1) * 276 232 ATP_XFACT - 1, 277 233 ATP_FUZZ, 0); 278 - break; 279 - } 234 + 235 + break; 236 + } 280 237 281 238 goto exit; 282 239 } ··· 341 282 memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); 342 283 } 343 284 344 - input_report_key(dev->input, BTN_LEFT, !!dev->data[80]); 285 + input_report_key(dev->input, BTN_LEFT, 286 + !!dev->data[dev->datalen - 1]); 345 287 346 288 input_sync(dev->input); 347 289 ··· 413 353 414 354 dev->udev = udev; 415 355 dev->input = input_dev; 356 + dev->overflowwarn = 0; 357 + dev->datalen = (atp_is_geyser_2(dev)?64:81); 416 358 417 359 dev->urb = usb_alloc_urb(0, GFP_KERNEL); 418 360 if (!dev->urb) { ··· 422 360 goto err_free_devs; 423 361 } 424 362 425 - dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL, 363 + dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL, 426 364 &dev->urb->transfer_dma); 427 365 if (!dev->data) { 428 366 retval = -ENOMEM; ··· 431 369 432 370 usb_fill_int_urb(dev->urb, udev, 433 371 usb_rcvintpipe(udev, int_in_endpointAddr), 434 - dev->data, ATP_DATASIZE, atp_complete, dev, 1); 372 + dev->data, dev->datalen, atp_complete, dev, 1); 435 373 436 374 usb_make_path(udev, dev->phys, sizeof(dev->phys)); 437 375 strlcat(dev->phys, "/input0", sizeof(dev->phys)); ··· 447 385 448 386 set_bit(EV_ABS, input_dev->evbit); 449 387 450 - /* 451 - * 12" and 15" Powerbooks only have 16 x sensors, 452 - * 17" models are detected later. 453 - */ 454 - input_set_abs_params(input_dev, ABS_X, 0, 455 - (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); 456 - input_set_abs_params(input_dev, ABS_Y, 0, 457 - (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); 388 + if (atp_is_geyser_2(dev)) { 389 + /* 390 + * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected 391 + * later. 392 + */ 393 + input_set_abs_params(input_dev, ABS_X, 0, 394 + ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); 395 + input_set_abs_params(input_dev, ABS_Y, 0, 396 + ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); 397 + } else { 398 + /* 399 + * 12" and 15" Powerbooks only have 16 x sensors, 400 + * 17" models are detected later. 401 + */ 402 + input_set_abs_params(input_dev, ABS_X, 0, 403 + (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); 404 + input_set_abs_params(input_dev, ABS_Y, 0, 405 + (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); 406 + } 458 407 input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); 459 408 460 409 set_bit(EV_KEY, input_dev->evbit); ··· 500 427 usb_kill_urb(dev->urb); 501 428 input_unregister_device(dev->input); 502 429 usb_free_urb(dev->urb); 503 - usb_buffer_free(dev->udev, ATP_DATASIZE, 430 + usb_buffer_free(dev->udev, dev->datalen, 504 431 dev->data, dev->urb->transfer_dma); 505 432 kfree(dev); 506 433 }