Input: wacom - add support for new LCD tablets
[safe/jmp/linux-2.6] / drivers / input / tablet / wacom_wac.c
1 /*
2  * drivers/input/tablet/wacom_wac.c
3  *
4  *  USB Wacom tablet support - Wacom specific code
5  *
6  */
7
8 /*
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  */
14 #include "wacom.h"
15 #include "wacom_wac.h"
16
17 static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo)
18 {
19         unsigned char *data = wacom->data;
20
21         switch (data[0]) {
22                 case 1:
23                         if (data[5] & 0x80) {
24                                 wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
25                                 wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID;
26                                 wacom_report_key(wcombo, wacom->tool[0], 1);
27                                 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
28                                 wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
29                                 wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
30                                 wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);
31                                 wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127));
32                                 wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));
33                         } else {
34                                 wacom_report_key(wcombo, wacom->tool[0], 0);
35                                 wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */
36                                 wacom_report_abs(wcombo, ABS_PRESSURE, -1);
37                                 wacom_report_key(wcombo, BTN_TOUCH, 0);
38                         }
39                         break;
40                 case 2:
41                         wacom_report_key(wcombo, BTN_TOOL_PEN, 1);
42                         wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
43                         wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
44                         wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
45                         wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);
46                         wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
47                         wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));
48                         break;
49                 default:
50                         printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);
51                         return 0;
52         }
53         return 1;
54 }
55
56 static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
57 {
58         unsigned char *data = wacom->data;
59         int prox, pressure;
60
61         if (data[0] != 2) {
62                 dbg("wacom_pl_irq: received unknown report #%d", data[0]);
63                 return 0;
64         }
65
66         prox = data[1] & 0x40;
67
68         if (prox) {
69                 wacom->id[0] = ERASER_DEVICE_ID;
70                 pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
71                 if (wacom->features->pressure_max > 255)
72                         pressure = (pressure << 1) | ((data[4] >> 6) & 1);
73                 pressure += (wacom->features->pressure_max + 1) / 2;
74
75                 /*
76                  * if going from out of proximity into proximity select between the eraser
77                  * and the pen based on the state of the stylus2 button, choose eraser if
78                  * pressed else choose pen. if not a proximity change from out to in, send
79                  * an out of proximity for previous tool then a in for new tool.
80                  */
81                 if (!wacom->tool[0]) {
82                         /* Eraser bit set for DTF */
83                         if (data[1] & 0x10)
84                                 wacom->tool[1] = BTN_TOOL_RUBBER;
85                         else
86                                 /* Going into proximity select tool */
87                                 wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
88                 } else {
89                         /* was entered with stylus2 pressed */
90                         if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
91                                 /* report out proximity for previous tool */
92                                 wacom_report_key(wcombo, wacom->tool[1], 0);
93                                 wacom_input_sync(wcombo);
94                                 wacom->tool[1] = BTN_TOOL_PEN;
95                                 return 0;
96                         }
97                 }
98                 if (wacom->tool[1] != BTN_TOOL_RUBBER) {
99                         /* Unknown tool selected default to pen tool */
100                         wacom->tool[1] = BTN_TOOL_PEN;
101                         wacom->id[0] = STYLUS_DEVICE_ID;
102                 }
103                 wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */
104                 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
105                 wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
106                 wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
107                 wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
108
109                 wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08);
110                 wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10);
111                 /* Only allow the stylus2 button to be reported for the pen tool. */
112                 wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
113         } else {
114                 /* report proximity-out of a (valid) tool */
115                 if (wacom->tool[1] != BTN_TOOL_RUBBER) {
116                         /* Unknown tool selected default to pen tool */
117                         wacom->tool[1] = BTN_TOOL_PEN;
118                 }
119                 wacom_report_key(wcombo, wacom->tool[1], prox);
120         }
121
122         wacom->tool[0] = prox; /* Save proximity state */
123         return 1;
124 }
125
126 static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
127 {
128         unsigned char *data = wacom->data;
129
130         if (data[0] != 2) {
131                 printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
132                 return 0;
133         }
134
135         if (data[1] & 0x04) {
136                 wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20);
137                 wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08);
138                 wacom->id[0] = ERASER_DEVICE_ID;
139         } else {
140                 wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20);
141                 wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
142                 wacom->id[0] = STYLUS_DEVICE_ID;
143         }
144         wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
145         wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
146         wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
147         wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
148         wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
149         wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
150         return 1;
151 }
152
153 static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
154 {
155         unsigned char *data = wacom->data;
156         int x, y, rw;
157
158         if (data[0] != 2) {
159                 dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
160                 return 0;
161         }
162
163         if (data[1] & 0x80) {
164                 /* in prox and not a pad data */
165
166                 switch ((data[1] >> 5) & 3) {
167
168                         case 0: /* Pen */
169                                 wacom->tool[0] = BTN_TOOL_PEN;
170                                 wacom->id[0] = STYLUS_DEVICE_ID;
171                                 break;
172
173                         case 1: /* Rubber */
174                                 wacom->tool[0] = BTN_TOOL_RUBBER;
175                                 wacom->id[0] = ERASER_DEVICE_ID;
176                                 break;
177
178                         case 2: /* Mouse with wheel */
179                                 wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
180                                 if (wacom->features->type == WACOM_G4 ||
181                                                 wacom->features->type == WACOM_MO) {
182                                         rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
183                                         wacom_report_rel(wcombo, REL_WHEEL, -rw);
184                                 } else
185                                         wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]);
186                                 /* fall through */
187
188                         case 3: /* Mouse without wheel */
189                                 wacom->tool[0] = BTN_TOOL_MOUSE;
190                                 wacom->id[0] = CURSOR_DEVICE_ID;
191                                 wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
192                                 wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
193                                 if (wacom->features->type == WACOM_G4 ||
194                                                 wacom->features->type == WACOM_MO)
195                                         wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);
196                                 else
197                                         wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
198                                 break;
199                 }
200                 x = wacom_le16_to_cpu(&data[2]);
201                 y = wacom_le16_to_cpu(&data[4]);
202                 wacom_report_abs(wcombo, ABS_X, x);
203                 wacom_report_abs(wcombo, ABS_Y, y);
204                 if (wacom->tool[0] != BTN_TOOL_MOUSE) {
205                         wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
206                         wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
207                         wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
208                         wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
209                 }
210                 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
211                 wacom_report_key(wcombo, wacom->tool[0], 1);
212         } else if (wacom->id[0]) {
213                 wacom_report_abs(wcombo, ABS_X, 0);
214                 wacom_report_abs(wcombo, ABS_Y, 0);
215                 if (wacom->tool[0] == BTN_TOOL_MOUSE) {
216                         wacom_report_key(wcombo, BTN_LEFT, 0);
217                         wacom_report_key(wcombo, BTN_RIGHT, 0);
218                         wacom_report_abs(wcombo, ABS_DISTANCE, 0);
219                 } else {
220                         wacom_report_abs(wcombo, ABS_PRESSURE, 0);
221                         wacom_report_key(wcombo, BTN_TOUCH, 0);
222                         wacom_report_key(wcombo, BTN_STYLUS, 0);
223                         wacom_report_key(wcombo, BTN_STYLUS2, 0);
224                 }
225                 wacom->id[0] = 0;
226                 wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
227                 wacom_report_key(wcombo, wacom->tool[0], 0);
228         }
229
230         /* send pad data */
231         switch (wacom->features->type) {
232             case WACOM_G4:
233                 if (data[7] & 0xf8) {
234                         wacom_input_sync(wcombo); /* sync last event */
235                         wacom->id[1] = PAD_DEVICE_ID;
236                         wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
237                         wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
238                         rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
239                         wacom_report_rel(wcombo, REL_WHEEL, rw);
240                         wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
241                         wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
242                         wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
243                 } else if (wacom->id[1]) {
244                         wacom_input_sync(wcombo); /* sync last event */
245                         wacom->id[1] = 0;
246                         wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
247                         wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
248                         wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
249                         wacom_report_abs(wcombo, ABS_MISC, 0);
250                         wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
251                 }
252                 break;
253             case WACOM_MO:
254                 if ((data[7] & 0xf8) || (data[8] & 0xff)) {
255                         wacom_input_sync(wcombo); /* sync last event */
256                         wacom->id[1] = PAD_DEVICE_ID;
257                         wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
258                         wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
259                         wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
260                         wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
261                         wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
262                         wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
263                         wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
264                         wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
265                 } else if (wacom->id[1]) {
266                         wacom_input_sync(wcombo); /* sync last event */
267                         wacom->id[1] = 0;
268                         wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
269                         wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
270                         wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
271                         wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
272                         wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
273                         wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
274                         wacom_report_abs(wcombo, ABS_MISC, 0);
275                         wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
276                 }
277                 break;
278         }
279         return 1;
280 }
281
282 static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
283 {
284         unsigned char *data = wacom->data;
285         int idx = 0;
286
287         /* tool number */
288         if (wacom->features->type == INTUOS)
289                 idx = data[1] & 0x01;
290
291         /* Enter report */
292         if ((data[1] & 0xfc) == 0xc0) {
293                 /* serial number of the tool */
294                 wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
295                         (data[4] << 20) + (data[5] << 12) +
296                         (data[6] << 4) + (data[7] >> 4);
297
298                 wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
299                 switch (wacom->id[idx]) {
300                         case 0x812: /* Inking pen */
301                         case 0x801: /* Intuos3 Inking pen */
302                         case 0x20802: /* Intuos4 Classic Pen */
303                         case 0x012:
304                                 wacom->tool[idx] = BTN_TOOL_PENCIL;
305                                 break;
306                         case 0x822: /* Pen */
307                         case 0x842:
308                         case 0x852:
309                         case 0x823: /* Intuos3 Grip Pen */
310                         case 0x813: /* Intuos3 Classic Pen */
311                         case 0x885: /* Intuos3 Marker Pen */
312                         case 0x802: /* Intuos4 Grip Pen Eraser */
313                         case 0x804: /* Intuos4 Marker Pen */
314                         case 0x40802: /* Intuos4 Classic Pen */
315                         case 0x022:
316                                 wacom->tool[idx] = BTN_TOOL_PEN;
317                                 break;
318                         case 0x832: /* Stroke pen */
319                         case 0x032:
320                                 wacom->tool[idx] = BTN_TOOL_BRUSH;
321                                 break;
322                         case 0x007: /* Mouse 4D and 2D */
323                         case 0x09c:
324                         case 0x094:
325                         case 0x017: /* Intuos3 2D Mouse */
326                         case 0x806: /* Intuos4 Mouse */
327                                 wacom->tool[idx] = BTN_TOOL_MOUSE;
328                                 break;
329                         case 0x096: /* Lens cursor */
330                         case 0x097: /* Intuos3 Lens cursor */
331                         case 0x006: /* Intuos4 Lens cursor */
332                                 wacom->tool[idx] = BTN_TOOL_LENS;
333                                 break;
334                         case 0x82a: /* Eraser */
335                         case 0x85a:
336                         case 0x91a:
337                         case 0xd1a:
338                         case 0x0fa:
339                         case 0x82b: /* Intuos3 Grip Pen Eraser */
340                         case 0x81b: /* Intuos3 Classic Pen Eraser */
341                         case 0x91b: /* Intuos3 Airbrush Eraser */
342                         case 0x80c: /* Intuos4 Marker Pen Eraser */
343                         case 0x80a: /* Intuos4 Grip Pen Eraser */
344                         case 0x4080a: /* Intuos4 Classic Pen Eraser */
345                         case 0x90a: /* Intuos4 Airbrush Eraser */
346                                 wacom->tool[idx] = BTN_TOOL_RUBBER;
347                                 break;
348                         case 0xd12:
349                         case 0x912:
350                         case 0x112:
351                         case 0x913: /* Intuos3 Airbrush */
352                         case 0x902: /* Intuos4 Airbrush */
353                                 wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
354                                 break;
355                         default: /* Unknown tool */
356                                 wacom->tool[idx] = BTN_TOOL_PEN;
357                 }
358                 return 1;
359         }
360
361         /* Exit report */
362         if ((data[1] & 0xfe) == 0x80) {
363                 /*
364                  * Reset all states otherwise we lose the initial states
365                  * when in-prox next time
366                  */
367                 wacom_report_abs(wcombo, ABS_X, 0);
368                 wacom_report_abs(wcombo, ABS_Y, 0);
369                 wacom_report_abs(wcombo, ABS_DISTANCE, 0);
370                 wacom_report_abs(wcombo, ABS_TILT_X, 0);
371                 wacom_report_abs(wcombo, ABS_TILT_Y, 0);
372                 if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
373                         wacom_report_key(wcombo, BTN_LEFT, 0);
374                         wacom_report_key(wcombo, BTN_MIDDLE, 0);
375                         wacom_report_key(wcombo, BTN_RIGHT, 0);
376                         wacom_report_key(wcombo, BTN_SIDE, 0);
377                         wacom_report_key(wcombo, BTN_EXTRA, 0);
378                         wacom_report_abs(wcombo, ABS_THROTTLE, 0);
379                         wacom_report_abs(wcombo, ABS_RZ, 0);
380                 } else {
381                         wacom_report_abs(wcombo, ABS_PRESSURE, 0);
382                         wacom_report_key(wcombo, BTN_STYLUS, 0);
383                         wacom_report_key(wcombo, BTN_STYLUS2, 0);
384                         wacom_report_key(wcombo, BTN_TOUCH, 0);
385                         wacom_report_abs(wcombo, ABS_WHEEL, 0);
386                         if (wacom->features->type >= INTUOS3S)
387                                 wacom_report_abs(wcombo, ABS_Z, 0);
388                 }
389                 wacom_report_key(wcombo, wacom->tool[idx], 0);
390                 wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
391                 wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
392                 wacom->id[idx] = 0;
393                 return 2;
394         }
395         return 0;
396 }
397
398 static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo)
399 {
400         unsigned char *data = wacom->data;
401         unsigned int t;
402
403         /* general pen packet */
404         if ((data[1] & 0xb8) == 0xa0) {
405                 t = (data[6] << 2) | ((data[7] >> 6) & 3);
406                 if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L)
407                         t = (t << 1) | (data[1] & 1);
408                 wacom_report_abs(wcombo, ABS_PRESSURE, t);
409                 wacom_report_abs(wcombo, ABS_TILT_X,
410                                 ((data[7] << 1) & 0x7e) | (data[8] >> 7));
411                 wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
412                 wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2);
413                 wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4);
414                 wacom_report_key(wcombo, BTN_TOUCH, t > 10);
415         }
416
417         /* airbrush second packet */
418         if ((data[1] & 0xbc) == 0xb4) {
419                 wacom_report_abs(wcombo, ABS_WHEEL,
420                                 (data[6] << 2) | ((data[7] >> 6) & 3));
421                 wacom_report_abs(wcombo, ABS_TILT_X,
422                                 ((data[7] << 1) & 0x7e) | (data[8] >> 7));
423                 wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
424         }
425         return;
426 }
427
428 static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
429 {
430         unsigned char *data = wacom->data;
431         unsigned int t;
432         int idx = 0, result;
433
434         if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
435                 dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
436                 return 0;
437         }
438
439         /* tool number */
440         if (wacom->features->type == INTUOS)
441                 idx = data[1] & 0x01;
442
443         /* pad packets. Works as a second tool and is always in prox */
444         if (data[0] == 12) {
445                 /* initiate the pad as a device */
446                 if (wacom->tool[1] != BTN_TOOL_FINGER)
447                         wacom->tool[1] = BTN_TOOL_FINGER;
448
449                 if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) {
450                         wacom_report_key(wcombo, BTN_0, (data[2] & 0x01));
451                         wacom_report_key(wcombo, BTN_1, (data[3] & 0x01));
452                         wacom_report_key(wcombo, BTN_2, (data[3] & 0x02));
453                         wacom_report_key(wcombo, BTN_3, (data[3] & 0x04));
454                         wacom_report_key(wcombo, BTN_4, (data[3] & 0x08));
455                         wacom_report_key(wcombo, BTN_5, (data[3] & 0x10));
456                         wacom_report_key(wcombo, BTN_6, (data[3] & 0x20));
457                         if (data[1] & 0x80) {
458                                 wacom_report_abs(wcombo, ABS_WHEEL, (data[1] & 0x7f));
459                         } else {
460                                 /* Out of proximity, clear wheel value. */
461                                 wacom_report_abs(wcombo, ABS_WHEEL, 0);
462                         }
463                         if (wacom->features->type != INTUOS4S) {
464                                 wacom_report_key(wcombo, BTN_7, (data[3] & 0x40));
465                                 wacom_report_key(wcombo, BTN_8, (data[3] & 0x80));
466                         }
467                         if (data[1] | (data[2] & 0x01) | data[3]) {
468                                 wacom_report_key(wcombo, wacom->tool[1], 1);
469                                 wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
470                         } else {
471                                 wacom_report_key(wcombo, wacom->tool[1], 0);
472                                 wacom_report_abs(wcombo, ABS_MISC, 0);
473                         }
474                 } else {
475                         wacom_report_key(wcombo, BTN_0, (data[5] & 0x01));
476                         wacom_report_key(wcombo, BTN_1, (data[5] & 0x02));
477                         wacom_report_key(wcombo, BTN_2, (data[5] & 0x04));
478                         wacom_report_key(wcombo, BTN_3, (data[5] & 0x08));
479                         wacom_report_key(wcombo, BTN_4, (data[6] & 0x01));
480                         wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
481                         wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
482                         wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
483                         wacom_report_key(wcombo, BTN_8, (data[5] & 0x10));
484                         wacom_report_key(wcombo, BTN_9, (data[6] & 0x10));
485                         wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
486                         wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
487
488                         if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
489                                 data[2] | (data[3] & 0x1f) | data[4]) {
490                                 wacom_report_key(wcombo, wacom->tool[1], 1);
491                                 wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
492                         } else {
493                                 wacom_report_key(wcombo, wacom->tool[1], 0);
494                                 wacom_report_abs(wcombo, ABS_MISC, 0);
495                         }
496                 }
497                 wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
498                 return 1;
499         }
500
501         /* process in/out prox events */
502         result = wacom_intuos_inout(wacom, wcombo);
503         if (result)
504                 return result-1;
505
506         /* don't proceed if we don't know the ID */
507         if (!wacom->id[idx])
508                 return 0;
509
510         /* Only large Intuos support Lense Cursor */
511         if ((wacom->tool[idx] == BTN_TOOL_LENS)
512                         && ((wacom->features->type == INTUOS3)
513                         || (wacom->features->type == INTUOS3S)
514                         || (wacom->features->type == INTUOS4)
515                         || (wacom->features->type == INTUOS4S)))
516                 return 0;
517
518         /* Cintiq doesn't send data when RDY bit isn't set */
519         if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
520                  return 0;
521
522         if (wacom->features->type >= INTUOS3S) {
523                 wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
524                 wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
525                 wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
526         } else {
527                 wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2]));
528                 wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4]));
529                 wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
530         }
531
532         /* process general packets */
533         wacom_intuos_general(wacom, wcombo);
534
535         /* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */
536         if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) {
537
538                 if (data[1] & 0x02) {
539                         /* Rotation packet */
540                         if (wacom->features->type >= INTUOS3S) {
541                                 /* I3 marker pen rotation */
542                                 t = (data[6] << 3) | ((data[7] >> 5) & 7);
543                                 t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
544                                         ((t-1) / 2 + 450)) : (450 - t / 2) ;
545                                 wacom_report_abs(wcombo, ABS_Z, t);
546                         } else {
547                                 /* 4D mouse rotation packet */
548                                 t = (data[6] << 3) | ((data[7] >> 5) & 7);
549                                 wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ?
550                                         ((t - 1) / 2) : -t / 2);
551                         }
552
553                 } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) {
554                         /* 4D mouse packet */
555                         wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
556                         wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
557                         wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
558
559                         wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x20);
560                         wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x10);
561                         t = (data[6] << 2) | ((data[7] >> 6) & 3);
562                         wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
563
564                 } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
565                         /* I4 mouse */
566                         if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) {
567                                 wacom_report_key(wcombo, BTN_LEFT,   data[6] & 0x01);
568                                 wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02);
569                                 wacom_report_key(wcombo, BTN_RIGHT,  data[6] & 0x04);
570                                 wacom_report_rel(wcombo, REL_WHEEL, ((data[7] & 0x80) >> 7)
571                                                  - ((data[7] & 0x40) >> 6));
572                                 wacom_report_key(wcombo, BTN_SIDE,   data[6] & 0x08);
573                                 wacom_report_key(wcombo, BTN_EXTRA,  data[6] & 0x10);
574
575                                 wacom_report_abs(wcombo, ABS_TILT_X,
576                                         ((data[7] << 1) & 0x7e) | (data[8] >> 7));
577                                 wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
578                         } else {
579                                 /* 2D mouse packet */
580                                 wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x04);
581                                 wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08);
582                                 wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x10);
583                                 wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01)
584                                                  - ((data[8] & 0x02) >> 1));
585
586                                 /* I3 2D mouse side buttons */
587                                 if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) {
588                                         wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x40);
589                                         wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x20);
590                                 }
591                         }
592                 } else if ((wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L ||
593                                 wacom->features->type == INTUOS4L) &&
594                            wacom->tool[idx] == BTN_TOOL_LENS) {
595                         /* Lens cursor packets */
596                         wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
597                         wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
598                         wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
599                         wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x10);
600                         wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x08);
601                 }
602         }
603
604         wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
605         wacom_report_key(wcombo, wacom->tool[idx], 1);
606         wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
607         return 1;
608 }
609
610
611 static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx)
612 {
613         wacom_report_abs(wcombo, ABS_X,
614                 (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8));
615         wacom_report_abs(wcombo, ABS_Y,
616                 (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8));
617         wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
618         wacom_report_key(wcombo, wacom->tool[idx], 1);
619         if (idx)
620                 wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
621         else
622                 wacom_report_key(wcombo, BTN_TOUCH, 1);
623 }
624
625 static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx)
626 {
627         wacom_report_abs(wcombo, ABS_X, 0);
628         wacom_report_abs(wcombo, ABS_Y, 0);
629         wacom_report_abs(wcombo, ABS_MISC, 0);
630         wacom_report_key(wcombo, wacom->tool[idx], 0);
631         if (idx)
632                 wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
633         else
634                 wacom_report_key(wcombo, BTN_TOUCH, 0);
635         return;
636 }
637
638 static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo)
639 {
640         char *data = wacom->data;
641         struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
642         static int firstFinger = 0;
643         static int secondFinger = 0;
644
645         wacom->tool[0] = BTN_TOOL_DOUBLETAP;
646         wacom->id[0] = TOUCH_DEVICE_ID;
647         wacom->tool[1] = BTN_TOOL_TRIPLETAP;
648
649         if (urb->actual_length != WACOM_PKGLEN_TPC1FG) {
650                 switch (data[0]) {
651                         case 6:
652                                 wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
653                                 wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
654                                 wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
655                                 wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
656                                 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
657                                 wacom_report_key(wcombo, wacom->tool[0], 1);
658                                 break;
659                         case 13:
660                                 /* keep this byte to send proper out-prox event */
661                                 wacom->id[1] = data[1] & 0x03;
662
663                                 if (data[1] & 0x01) {
664                                         wacom_tpc_finger_in(wacom, wcombo, data, 0);
665                                         firstFinger = 1;
666                                 } else if (firstFinger) {
667                                         wacom_tpc_touch_out(wacom, wcombo, 0);
668                                 }
669
670                                 if (data[1] & 0x02) {
671                                         /* sync first finger data */
672                                         if (firstFinger)
673                                                 wacom_input_sync(wcombo);
674
675                                         wacom_tpc_finger_in(wacom, wcombo, data, 1);
676                                         secondFinger = 1;
677                                 } else if (secondFinger) {
678                                         /* sync first finger data */
679                                         if (firstFinger)
680                                                 wacom_input_sync(wcombo);
681
682                                         wacom_tpc_touch_out(wacom, wcombo, 1);
683                                         secondFinger = 0;
684                                 }
685                                 if (!(data[1] & 0x01))
686                                         firstFinger = 0;
687                                 break;
688                 }
689         } else {
690                 wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
691                 wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
692                 wacom_report_key(wcombo, BTN_TOUCH, 1);
693                 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
694                 wacom_report_key(wcombo, wacom->tool[0], 1);
695         }
696         return;
697 }
698
699 static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
700 {
701         char *data = wacom->data;
702         int prox = 0, pressure, idx = -1;
703         static int stylusInProx, touchInProx = 1, touchOut;
704         struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
705
706         dbg("wacom_tpc_irq: received report #%d", data[0]);
707
708         if (urb->actual_length == WACOM_PKGLEN_TPC1FG ||
709             data[0] == 6 || /* single touch */
710             data[0] == 13) { /* 2FG touch */
711                 if (urb->actual_length == WACOM_PKGLEN_TPC1FG) {  /* with touch */
712                         prox = data[0] & 0x01;
713                 } else {  /* with capacity */
714                         if (data[0] == 6)
715                                 /* single touch */
716                                 prox = data[1] & 0x01;
717                         else
718                                 /* 2FG touch data */
719                                 prox = data[1] & 0x03;
720                 }
721
722                 if (!stylusInProx) { /* stylus not in prox */
723                         if (prox) {
724                                 if (touchInProx) {
725                                         wacom_tpc_touch_in(wacom, wcombo);
726                                         touchOut = 1;
727                                         return 1;
728                                 }
729                         } else {
730                                 /* 2FGT out-prox */
731                                 if ((data[0] & 0xff) == 13) {
732                                         idx = (wacom->id[1] & 0x01) - 1;
733                                         if (idx == 0) {
734                                                 wacom_tpc_touch_out(wacom, wcombo, idx);
735                                                 /* sync first finger event */
736                                                 if (wacom->id[1] & 0x02)
737                                                         wacom_input_sync(wcombo);
738                                         }
739                                         idx = (wacom->id[1] & 0x02) - 1;
740                                         if (idx == 1)
741                                                 wacom_tpc_touch_out(wacom, wcombo, idx);
742                                 } else /* one finger touch */
743                                         wacom_tpc_touch_out(wacom, wcombo, 0);
744                                 touchOut = 0;
745                                 touchInProx = 1;
746                                 return 1;
747                         }
748                 } else if (touchOut || !prox) { /* force touch out-prox */
749                         wacom_tpc_touch_out(wacom, wcombo, 0);
750                         touchOut = 0;
751                         touchInProx = 1;
752                         return 1;
753                 }
754         } else if (data[0] == 2) { /* Penabled */
755                 prox = data[1] & 0x20;
756
757                 touchInProx = 0;
758
759                 if (prox) { /* in prox */
760                         if (!wacom->id[0]) {
761                                 /* Going into proximity select tool */
762                                 wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
763                                 if (wacom->tool[0] == BTN_TOOL_PEN)
764                                         wacom->id[0] = STYLUS_DEVICE_ID;
765                                 else
766                                         wacom->id[0] = ERASER_DEVICE_ID;
767                         }
768                         wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
769                         wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
770                         wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
771                         wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
772                         pressure = ((data[7] & 0x01) << 8) | data[6];
773                         if (pressure < 0)
774                                 pressure = wacom->features->pressure_max + pressure + 1;
775                         wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
776                         wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05);
777                 } else {
778                         wacom_report_abs(wcombo, ABS_X, 0);
779                         wacom_report_abs(wcombo, ABS_Y, 0);
780                         wacom_report_abs(wcombo, ABS_PRESSURE, 0);
781                         wacom_report_key(wcombo, BTN_STYLUS, 0);
782                         wacom_report_key(wcombo, BTN_STYLUS2, 0);
783                         wacom_report_key(wcombo, BTN_TOUCH, 0);
784                         wacom->id[0] = 0;
785                         /* pen is out so touch can be enabled now */
786                         touchInProx = 1;
787                 }
788                 wacom_report_key(wcombo, wacom->tool[0], prox);
789                 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
790                 stylusInProx = prox;
791                 return 1;
792         }
793         return 0;
794 }
795
796 int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
797 {
798         switch (wacom_wac->features->type) {
799                 case PENPARTNER:
800                         return wacom_penpartner_irq(wacom_wac, wcombo);
801
802                 case PL:
803                         return wacom_pl_irq(wacom_wac, wcombo);
804
805                 case WACOM_G4:
806                 case GRAPHIRE:
807                 case WACOM_MO:
808                         return wacom_graphire_irq(wacom_wac, wcombo);
809
810                 case PTU:
811                         return wacom_ptu_irq(wacom_wac, wcombo);
812
813                 case INTUOS:
814                 case INTUOS3S:
815                 case INTUOS3:
816                 case INTUOS3L:
817                 case INTUOS4S:
818                 case INTUOS4:
819                 case INTUOS4L:
820                 case CINTIQ:
821                 case WACOM_BEE:
822                         return wacom_intuos_irq(wacom_wac, wcombo);
823
824                 case TABLETPC:
825                 case TABLETPC2FG:
826                         return wacom_tpc_irq(wacom_wac, wcombo);
827
828                 default:
829                         return 0;
830         }
831         return 0;
832 }
833
834 void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
835 {
836         switch (wacom_wac->features->type) {
837                 case WACOM_MO:
838                         input_dev_mo(input_dev, wacom_wac);
839                 case WACOM_G4:
840                         input_dev_g4(input_dev, wacom_wac);
841                         /* fall through */
842                 case GRAPHIRE:
843                         input_dev_g(input_dev, wacom_wac);
844                         break;
845                 case WACOM_BEE:
846                         input_dev_bee(input_dev, wacom_wac);
847                 case INTUOS3:
848                 case INTUOS3L:
849                 case CINTIQ:
850                         input_dev_i3(input_dev, wacom_wac);
851                         /* fall through */
852                 case INTUOS3S:
853                         input_dev_i3s(input_dev, wacom_wac);
854                         /* fall through */
855                 case INTUOS:
856                         input_dev_i(input_dev, wacom_wac);
857                         break;
858                 case INTUOS4:
859                 case INTUOS4L:
860                         input_dev_i4(input_dev, wacom_wac);
861                         /* fall through */
862                 case INTUOS4S:
863                         input_dev_i4s(input_dev, wacom_wac);
864                         input_dev_i(input_dev, wacom_wac);
865                         break;
866                 case TABLETPC2FG:
867                         input_dev_tpc2fg(input_dev, wacom_wac);
868                         /* fall through */
869                 case TABLETPC:
870                         input_dev_tpc(input_dev, wacom_wac);
871                         if (wacom_wac->features->device_type != BTN_TOOL_PEN)
872                                 break;  /* no need to process stylus stuff */
873
874                         /* fall through */
875                 case PL:
876                 case PTU:
877                         input_dev_pl(input_dev, wacom_wac);
878                         /* fall through */
879                 case PENPARTNER:
880                         input_dev_pt(input_dev, wacom_wac);
881                         break;
882         }
883         return;
884 }
885
886 static struct wacom_features wacom_features[] = {
887         { "Wacom Penpartner",     WACOM_PKGLEN_PENPRTN,    5040,  3780,  255,  0, PENPARTNER },
888         { "Wacom Graphire",       WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511, 63, GRAPHIRE },
889         { "Wacom Graphire2 4x5",  WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511, 63, GRAPHIRE },
890         { "Wacom Graphire2 5x7",  WACOM_PKGLEN_GRAPHIRE,  13918, 10206,  511, 63, GRAPHIRE },
891         { "Wacom Graphire3",      WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511, 63, GRAPHIRE },
892         { "Wacom Graphire3 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, GRAPHIRE },
893         { "Wacom Graphire4 4x5",  WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511, 63, WACOM_G4 },
894         { "Wacom Graphire4 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, WACOM_G4 },
895         { "Wacom BambooFun 4x5",  WACOM_PKGLEN_BBFUN,     14760,  9225,  511, 63, WACOM_MO },
896         { "Wacom BambooFun 6x8",  WACOM_PKGLEN_BBFUN,     21648, 13530,  511, 63, WACOM_MO },
897         { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, GRAPHIRE },
898         { "Wacom Volito",         WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE },
899         { "Wacom PenStation2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  255, 63, GRAPHIRE },
900         { "Wacom Volito2 4x5",    WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE },
901         { "Wacom Volito2 2x3",    WACOM_PKGLEN_GRAPHIRE,   3248,  2320,  511, 63, GRAPHIRE },
902         { "Wacom PenPartner2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  511, 63, GRAPHIRE },
903         { "Wacom Bamboo",         WACOM_PKGLEN_BBFUN,     14760,  9225,  511, 63, WACOM_MO },
904         { "Wacom Bamboo1",        WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE },
905         { "Wacom Intuos 4x5",     WACOM_PKGLEN_INTUOS,    12700, 10600, 1023, 31, INTUOS },
906         { "Wacom Intuos 6x8",     WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS },
907         { "Wacom Intuos 9x12",    WACOM_PKGLEN_INTUOS,    30480, 24060, 1023, 31, INTUOS },
908         { "Wacom Intuos 12x12",   WACOM_PKGLEN_INTUOS,    30480, 31680, 1023, 31, INTUOS },
909         { "Wacom Intuos 12x18",   WACOM_PKGLEN_INTUOS,    45720, 31680, 1023, 31, INTUOS },
910         { "Wacom PL400",          WACOM_PKGLEN_GRAPHIRE,   5408,  4056,  255,  0, PL },
911         { "Wacom PL500",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  255,  0, PL },
912         { "Wacom PL600",          WACOM_PKGLEN_GRAPHIRE,   6126,  4604,  255,  0, PL },
913         { "Wacom PL600SX",        WACOM_PKGLEN_GRAPHIRE,   6260,  5016,  255,  0, PL },
914         { "Wacom PL550",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  511,  0, PL },
915         { "Wacom PL800",          WACOM_PKGLEN_GRAPHIRE,   7220,  5780,  511,  0, PL },
916         { "Wacom PL700",          WACOM_PKGLEN_GRAPHIRE,   6758,  5406,  511,  0, PL },
917         { "Wacom PL510",          WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,  0, PL },
918         { "Wacom DTU710",         WACOM_PKGLEN_GRAPHIRE,  34080, 27660,  511,  0, PL },
919         { "Wacom DTF521",         WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,  0, PL },
920         { "Wacom DTF720",         WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,  0, PL },
921         { "Wacom DTF720a",        WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,  0, PL },
922         { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE,  20480, 15360,  511,  0, PTU },
923         { "Wacom Intuos2 4x5",    WACOM_PKGLEN_INTUOS,    12700, 10600, 1023, 31, INTUOS },
924         { "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS },
925         { "Wacom Intuos2 9x12",   WACOM_PKGLEN_INTUOS,    30480, 24060, 1023, 31, INTUOS },
926         { "Wacom Intuos2 12x12",  WACOM_PKGLEN_INTUOS,    30480, 31680, 1023, 31, INTUOS },
927         { "Wacom Intuos2 12x18",  WACOM_PKGLEN_INTUOS,    45720, 31680, 1023, 31, INTUOS },
928         { "Wacom Intuos3 4x5",    WACOM_PKGLEN_INTUOS,    25400, 20320, 1023, 63, INTUOS3S },
929         { "Wacom Intuos3 6x8",    WACOM_PKGLEN_INTUOS,    40640, 30480, 1023, 63, INTUOS3 },
930         { "Wacom Intuos3 9x12",   WACOM_PKGLEN_INTUOS,    60960, 45720, 1023, 63, INTUOS3 },
931         { "Wacom Intuos3 12x12",  WACOM_PKGLEN_INTUOS,    60960, 60960, 1023, 63, INTUOS3L },
932         { "Wacom Intuos3 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 1023, 63, INTUOS3L },
933         { "Wacom Intuos3 6x11",   WACOM_PKGLEN_INTUOS,    54204, 31750, 1023, 63, INTUOS3 },
934         { "Wacom Intuos3 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 1023, 63, INTUOS3S },
935         { "Wacom Intuos4 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 2047, 63, INTUOS4S },
936         { "Wacom Intuos4 6x9",    WACOM_PKGLEN_INTUOS,    44704, 27940, 2047, 63, INTUOS4 },
937         { "Wacom Intuos4 8x13",   WACOM_PKGLEN_INTUOS,    65024, 40640, 2047, 63, INTUOS4L },
938         { "Wacom Intuos4 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 2047, 63, INTUOS4L },
939         { "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023, 63, CINTIQ },
940         { "Wacom Cintiq 20WSX",   WACOM_PKGLEN_INTUOS,    86680, 54180, 1023, 63, WACOM_BEE },
941         { "Wacom Cintiq 12WX",    WACOM_PKGLEN_INTUOS,    53020, 33440, 1023, 63, WACOM_BEE },
942         { "Wacom DTU1931",        WACOM_PKGLEN_GRAPHIRE,  37832, 30305,  511,  0, PL },
943         { "Wacom ISDv4 90",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC },
944         { "Wacom ISDv4 93",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC },
945         { "Wacom ISDv4 9A",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC },
946         { "Wacom ISDv4 9F",       WACOM_PKGLEN_PENABLED,  26202, 16325,  255,  0, TABLETPC },
947         { "Wacom ISDv4 E2",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG },
948         { "Wacom ISDv4 E3",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG },
949         { "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS },
950         { }
951 };
952
953 static struct usb_device_id wacom_ids[] = {
954         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) },
955         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) },
956         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
957         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
958         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
959         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
960         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
961         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
962         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) },
963         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) },
964         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) },
965         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
966         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
967         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
968         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
969         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
970         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) },
971         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x69) },
972         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
973         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
974         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
975         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) },
976         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) },
977         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) },
978         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) },
979         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) },
980         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) },
981         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) },
982         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) },
983         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
984         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
985         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
986         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) },
987         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
988         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) },
989         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
990         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
991         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
992         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
993         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
994         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
995         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
996         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
997         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
998         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
999         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
1000         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
1001         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
1002         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB8) },
1003         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB9) },
1004         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBA) },
1005         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBB) },
1006         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
1007         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
1008         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
1009         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) },
1010         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) },
1011         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) },
1012         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) },
1013         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9F) },
1014         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE2) },
1015         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE3) },
1016         { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
1017         { }
1018 };
1019
1020 const struct usb_device_id *get_device_table(void)
1021 {
1022         const struct usb_device_id *id_table = wacom_ids;
1023
1024         return id_table;
1025 }
1026
1027 struct wacom_features * get_wacom_feature(const struct usb_device_id *id)
1028 {
1029         int index = id - wacom_ids;
1030         struct wacom_features *wf = &wacom_features[index];
1031
1032         return wf;
1033 }
1034
1035 MODULE_DEVICE_TABLE(usb, wacom_ids);