]> err.no Git - linux-2.6/blob - drivers/usb/input/appletouch.c
[PATCH] USB: add apple usb touchpad driver
[linux-2.6] / drivers / usb / input / appletouch.c
1 /*
2  * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
3  *
4  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
5  * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
6  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
7  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
8  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
9  *
10  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  */
27
28 #include <linux/config.h>
29 #include <linux/kernel.h>
30 #include <linux/errno.h>
31 #include <linux/init.h>
32 #include <linux/slab.h>
33 #include <linux/module.h>
34 #include <linux/usb.h>
35 #include <linux/input.h>
36 #include <linux/usb_input.h>
37
38 /* Apple has powerbooks which have the keyboard with different Product IDs */
39 #define APPLE_VENDOR_ID         0x05AC
40
41 #define ATP_DEVICE(prod)                                        \
42         .match_flags = USB_DEVICE_ID_MATCH_DEVICE |             \
43                        USB_DEVICE_ID_MATCH_INT_CLASS |          \
44                        USB_DEVICE_ID_MATCH_INT_PROTOCOL,        \
45         .idVendor = APPLE_VENDOR_ID,                            \
46         .idProduct = (prod),                                    \
47         .bInterfaceClass = 0x03,                                \
48         .bInterfaceProtocol = 0x02
49
50 /* table of devices that work with this driver */
51 static struct usb_device_id atp_table [] = {
52         { ATP_DEVICE(0x020E) },
53         { ATP_DEVICE(0x020F) },
54         { ATP_DEVICE(0x030A) },
55         { ATP_DEVICE(0x030B) },
56         { }                                     /* Terminating entry */
57 };
58 MODULE_DEVICE_TABLE (usb, atp_table);
59
60 /* size of a USB urb transfer */
61 #define ATP_DATASIZE    81
62
63 /*
64  * number of sensors. Note that only 16 instead of 26 X (horizontal)
65  * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
66  * (vertical) sensors.
67  */
68 #define ATP_XSENSORS    26
69 #define ATP_YSENSORS    16
70
71 /* amount of fuzz this touchpad generates */
72 #define ATP_FUZZ        16
73
74 /* maximum pressure this driver will report */
75 #define ATP_PRESSURE    300
76 /*
77  * multiplication factor for the X and Y coordinates.
78  * We try to keep the touchpad aspect ratio while still doing only simple
79  * arithmetics.
80  * The factors below give coordinates like:
81  *      0 <= x <  960 on 12" and 15" Powerbooks
82  *      0 <= x < 1600 on 17" Powerbooks
83  *      0 <= y <  646
84  */
85 #define ATP_XFACT       64
86 #define ATP_YFACT       43
87
88 /*
89  * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
90  * ignored.
91  */
92 #define ATP_THRESHOLD    5
93
94 /* Structure to hold all of our device specific stuff */
95 struct atp {
96         struct usb_device *     udev;           /* usb device */
97         struct urb *            urb;            /* usb request block */
98         signed char *           data;           /* transferred data */
99         int                     open;           /* non-zero if opened */
100         struct input_dev        input;          /* input dev */
101         int                     valid;          /* are the sensors valid ? */
102         int                     x_old;          /* last reported x/y, */
103         int                     y_old;          /* used for smoothing */
104                                                 /* current value of the sensors */
105         signed char             xy_cur[ATP_XSENSORS + ATP_YSENSORS];
106                                                 /* last value of the sensors */
107         signed char             xy_old[ATP_XSENSORS + ATP_YSENSORS];
108                                                 /* accumulated sensors */
109         int                     xy_acc[ATP_XSENSORS + ATP_YSENSORS];
110 };
111
112 #define dbg_dump(msg, tab) \
113         if (debug > 1) {                                                \
114                 int i;                                                  \
115                 printk("appletouch: %s %lld", msg, (long long)jiffies); \
116                 for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++)       \
117                         printk(" %02x", tab[i]);                        \
118                 printk("\n");                                           \
119         }
120
121 #define dprintk(format, a...)                                           \
122         do {                                                            \
123                 if (debug) printk(format, ##a);                         \
124         } while (0)
125
126 MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
127 MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
128 MODULE_LICENSE("GPL");
129
130 static int debug = 1;
131 module_param(debug, int, 0644);
132 MODULE_PARM_DESC(debug, "Activate debugging output");
133
134 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
135                              int *z, int *fingers)
136 {
137         int i;
138         /* values to calculate mean */
139         int pcum = 0, psum = 0;
140
141         *fingers = 0;
142
143         for (i = 0; i < nb_sensors; i++) {
144                 if (xy_sensors[i] < ATP_THRESHOLD)
145                         continue;
146                 if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
147                         (*fingers)++;
148                 pcum += xy_sensors[i] * i;
149                 psum += xy_sensors[i];
150         }
151
152         if (psum > 0) {
153                 *z = psum;
154                 return pcum * fact / psum;
155         }
156
157         return 0;
158 }
159
160 static inline void atp_report_fingers(struct input_dev *input, int fingers)
161 {
162         input_report_key(input, BTN_TOOL_FINGER, fingers == 1);
163         input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);
164         input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
165 }
166
167 static void atp_complete(struct urb* urb, struct pt_regs* regs)
168 {
169         int x, y, x_z, y_z, x_f, y_f;
170         int retval, i;
171         struct atp *dev = urb->context;
172
173         switch (urb->status) {
174         case 0:
175                 /* success */
176                 break;
177         case -ECONNRESET:
178         case -ENOENT:
179         case -ESHUTDOWN:
180                 /* This urb is terminated, clean up */
181                 dbg("%s - urb shutting down with status: %d",
182                     __FUNCTION__, urb->status);
183                 return;
184         default:
185                 dbg("%s - nonzero urb status received: %d",
186                     __FUNCTION__, urb->status);
187                 goto exit;
188         }
189
190         /* drop incomplete datasets */
191         if (dev->urb->actual_length != ATP_DATASIZE) {
192                 dprintk("appletouch: incomplete data package.\n");
193                 goto exit;
194         }
195
196         /* reorder the sensors values */
197         for (i = 0; i < 8; i++) {
198                 /* X values */
199                 dev->xy_cur[i     ] = dev->data[5 * i +  2];
200                 dev->xy_cur[i +  8] = dev->data[5 * i +  4];
201                 dev->xy_cur[i + 16] = dev->data[5 * i + 42];
202                 if (i < 2)
203                         dev->xy_cur[i + 24] = dev->data[5 * i + 44];
204
205                 /* Y values */
206                 dev->xy_cur[i + 26] = dev->data[5 * i +  1];
207                 dev->xy_cur[i + 34] = dev->data[5 * i +  3];
208         }
209
210         dbg_dump("sample", dev->xy_cur);
211
212         if (!dev->valid) {
213                 /* first sample */
214                 dev->valid = 1;
215                 dev->x_old = dev->y_old = -1;
216                 memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
217
218                 /* 17" Powerbooks have 10 extra X sensors */
219                 for (i = 16; i < ATP_XSENSORS; i++)
220                         if (dev->xy_cur[i]) {
221                                 printk("appletouch: 17\" model detected.\n");
222                                 input_set_abs_params(&dev->input, ABS_X, 0,
223                                                      (ATP_XSENSORS - 1) *
224                                                      ATP_XFACT - 1,
225                                                      ATP_FUZZ, 0);
226                                 break;
227                         }
228
229                 goto exit;
230         }
231
232         for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
233                 /* accumulate the change */
234                 signed char change = dev->xy_old[i] - dev->xy_cur[i];
235                 dev->xy_acc[i] -= change;
236
237                 /* prevent down drifting */
238                 if (dev->xy_acc[i] < 0)
239                         dev->xy_acc[i] = 0;
240         }
241
242         memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
243
244         dbg_dump("accumulator", dev->xy_acc);
245
246         x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
247                               ATP_XFACT, &x_z, &x_f);
248         y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
249                               ATP_YFACT, &y_z, &y_f);
250
251         if (x && y) {
252                 if (dev->x_old != -1) {
253                         x = (dev->x_old * 3 + x) >> 2;
254                         y = (dev->y_old * 3 + y) >> 2;
255                         dev->x_old = x;
256                         dev->y_old = y;
257
258                         if (debug > 1)
259                                 printk("appletouch: X: %3d Y: %3d "
260                                        "Xz: %3d Yz: %3d\n",
261                                        x, y, x_z, y_z);
262
263                         input_report_key(&dev->input, BTN_TOUCH, 1);
264                         input_report_abs(&dev->input, ABS_X, x);
265                         input_report_abs(&dev->input, ABS_Y, y);
266                         input_report_abs(&dev->input, ABS_PRESSURE,
267                                          min(ATP_PRESSURE, x_z + y_z));
268                         atp_report_fingers(&dev->input, max(x_f, y_f));
269                 }
270                 dev->x_old = x;
271                 dev->y_old = y;
272         }
273         else if (!x && !y) {
274
275                 dev->x_old = dev->y_old = -1;
276                 input_report_key(&dev->input, BTN_TOUCH, 0);
277                 input_report_abs(&dev->input, ABS_PRESSURE, 0);
278                 atp_report_fingers(&dev->input, 0);
279
280                 /* reset the accumulator on release */
281                 memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
282         }
283
284         input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);
285
286         input_sync(&dev->input);
287
288 exit:
289         retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
290         if (retval) {
291                 err("%s - usb_submit_urb failed with result %d",
292                     __FUNCTION__, retval);
293         }
294 }
295
296 static int atp_open(struct input_dev *input)
297 {
298         struct atp *dev = input->private;
299
300         if (usb_submit_urb(dev->urb, GFP_ATOMIC))
301                 return -EIO;
302
303         dev->open = 1;
304         return 0;
305 }
306
307 static void atp_close(struct input_dev *input)
308 {
309         struct atp *dev = input->private;
310
311         usb_kill_urb(dev->urb);
312         dev->open = 0;
313 }
314
315 static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
316 {
317         struct atp *dev = NULL;
318         struct usb_host_interface *iface_desc;
319         struct usb_endpoint_descriptor *endpoint;
320         int int_in_endpointAddr = 0;
321         int i, retval = -ENOMEM;
322
323         /* allocate memory for our device state and initialize it */
324         dev = kmalloc(sizeof(struct atp), GFP_KERNEL);
325         if (dev == NULL) {
326                 err("Out of memory");
327                 goto err_kmalloc;
328         }
329         memset(dev, 0, sizeof(struct atp));
330
331         dev->udev = interface_to_usbdev(iface);
332
333         /* set up the endpoint information */
334         /* use only the first interrupt-in endpoint */
335         iface_desc = iface->cur_altsetting;
336         for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
337                 endpoint = &iface_desc->endpoint[i].desc;
338                 if (!int_in_endpointAddr &&
339                     (endpoint->bEndpointAddress & USB_DIR_IN) &&
340                     ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
341                                         == USB_ENDPOINT_XFER_INT)) {
342                         /* we found an interrupt in endpoint */
343                         int_in_endpointAddr = endpoint->bEndpointAddress;
344                         break;
345                 }
346         }
347         if (!int_in_endpointAddr) {
348                 retval = -EIO;
349                 err("Could not find int-in endpoint");
350                 goto err_endpoint;
351         }
352
353         /* save our data pointer in this interface device */
354         usb_set_intfdata(iface, dev);
355
356         dev->urb = usb_alloc_urb(0, GFP_KERNEL);
357         if (!dev->urb) {
358                 retval = -ENOMEM;
359                 goto err_usballoc;
360         }
361         dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
362                                      &dev->urb->transfer_dma);
363         if (!dev->data) {
364                 retval = -ENOMEM;
365                 goto err_usbbufalloc;
366         }
367         usb_fill_int_urb(dev->urb, dev->udev,
368                          usb_rcvintpipe(dev->udev, int_in_endpointAddr),
369                          dev->data, ATP_DATASIZE, atp_complete, dev, 1);
370
371         init_input_dev(&dev->input);
372         dev->input.name = "appletouch";
373         dev->input.dev = &iface->dev;
374         dev->input.private = dev;
375         dev->input.open = atp_open;
376         dev->input.close = atp_close;
377
378         usb_to_input_id(dev->udev, &dev->input.id);
379
380         set_bit(EV_ABS, dev->input.evbit);
381
382         /*
383          * 12" and 15" Powerbooks only have 16 x sensors,
384          * 17" models are detected later.
385          */
386         input_set_abs_params(&dev->input, ABS_X, 0,
387                              (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
388         input_set_abs_params(&dev->input, ABS_Y, 0,
389                              (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
390         input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
391
392         set_bit(EV_KEY, dev->input.evbit);
393         set_bit(BTN_TOUCH, dev->input.keybit);
394         set_bit(BTN_TOOL_FINGER, dev->input.keybit);
395         set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit);
396         set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit);
397         set_bit(BTN_LEFT, dev->input.keybit);
398
399         input_register_device(&dev->input);
400
401         printk(KERN_INFO "input: appletouch connected\n");
402
403         return 0;
404
405 err_usbbufalloc:
406         usb_free_urb(dev->urb);
407 err_usballoc:
408         usb_set_intfdata(iface, NULL);
409 err_endpoint:
410         kfree(dev);
411 err_kmalloc:
412         return retval;
413 }
414
415 static void atp_disconnect(struct usb_interface *iface)
416 {
417         struct atp *dev = usb_get_intfdata(iface);
418
419         usb_set_intfdata(iface, NULL);
420         if (dev) {
421                 usb_kill_urb(dev->urb);
422                 input_unregister_device(&dev->input);
423                 usb_free_urb(dev->urb);
424                 usb_buffer_free(dev->udev, ATP_DATASIZE,
425                                 dev->data, dev->urb->transfer_dma);
426                 kfree(dev);
427         }
428         printk(KERN_INFO "input: appletouch disconnected\n");
429 }
430
431 static int atp_suspend(struct usb_interface *iface, pm_message_t message)
432 {
433         struct atp *dev = usb_get_intfdata(iface);
434         usb_kill_urb(dev->urb);
435         dev->valid = 0;
436         return 0;
437 }
438
439 static int atp_resume(struct usb_interface *iface)
440 {
441         struct atp *dev = usb_get_intfdata(iface);
442         if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
443                 return -EIO;
444
445         return 0;
446 }
447
448 static struct usb_driver atp_driver = {
449         .owner          = THIS_MODULE,
450         .name           = "appletouch",
451         .probe          = atp_probe,
452         .disconnect     = atp_disconnect,
453         .suspend        = atp_suspend,
454         .resume         = atp_resume,
455         .id_table       = atp_table,
456 };
457
458 static int __init atp_init(void)
459 {
460         return usb_register(&atp_driver);
461 }
462
463 static void __exit atp_exit(void)
464 {
465         usb_deregister(&atp_driver);
466 }
467
468 module_init(atp_init);
469 module_exit(atp_exit);