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