linux/drivers/input/tablet/wacom_wac.c
<<
>>
Prefs
   1/*
   2 * drivers/input/tablet/wacom_wac.c
   3 *
   4 *  USB Wacom Graphire and Wacom Intuos 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        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        wacom->id[0] = ERASER_DEVICE_ID;
  69        if (prox) {
  70
  71                pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
  72                if (wacom->features->pressure_max > 255)
  73                        pressure = (pressure << 1) | ((data[4] >> 6) & 1);
  74                pressure += (wacom->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] != 2) {
 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        unsigned char *data = wacom->data;
 157        int x, y, rw;
 158
 159        if (data[0] != 2) {
 160                dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
 161                return 0;
 162        }
 163
 164        if (data[1] & 0x80) {
 165                /* in prox and not a pad data */
 166
 167                switch ((data[1] >> 5) & 3) {
 168
 169                        case 0: /* Pen */
 170                                wacom->tool[0] = BTN_TOOL_PEN;
 171                                wacom->id[0] = STYLUS_DEVICE_ID;
 172                                break;
 173
 174                        case 1: /* Rubber */
 175                                wacom->tool[0] = BTN_TOOL_RUBBER;
 176                                wacom->id[0] = ERASER_DEVICE_ID;
 177                                break;
 178
 179                        case 2: /* Mouse with wheel */
 180                                wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
 181                                if (wacom->features->type == WACOM_G4 ||
 182                                                wacom->features->type == WACOM_MO) {
 183                                        rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
 184                                        wacom_report_rel(wcombo, REL_WHEEL, -rw);
 185                                } else
 186                                        wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]);
 187                                /* fall through */
 188
 189                        case 3: /* Mouse without wheel */
 190                                wacom->tool[0] = BTN_TOOL_MOUSE;
 191                                wacom->id[0] = CURSOR_DEVICE_ID;
 192                                wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
 193                                wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
 194                                if (wacom->features->type == WACOM_G4 ||
 195                                                wacom->features->type == WACOM_MO)
 196                                        wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);
 197                                else
 198                                        wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
 199                                break;
 200                }
 201                x = wacom_le16_to_cpu(&data[2]);
 202                y = wacom_le16_to_cpu(&data[4]);
 203                wacom_report_abs(wcombo, ABS_X, x);
 204                wacom_report_abs(wcombo, ABS_Y, y);
 205                if (wacom->tool[0] != BTN_TOOL_MOUSE) {
 206                        wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
 207                        wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
 208                        wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
 209                        wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
 210                }
 211                wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
 212                wacom_report_key(wcombo, wacom->tool[0], 1);
 213        } else if (wacom->id[0]) {
 214                wacom_report_abs(wcombo, ABS_X, 0);
 215                wacom_report_abs(wcombo, ABS_Y, 0);
 216                if (wacom->tool[0] == BTN_TOOL_MOUSE) {
 217                        wacom_report_key(wcombo, BTN_LEFT, 0);
 218                        wacom_report_key(wcombo, BTN_RIGHT, 0);
 219                        wacom_report_abs(wcombo, ABS_DISTANCE, 0);
 220                } else {
 221                        wacom_report_abs(wcombo, ABS_PRESSURE, 0);
 222                        wacom_report_key(wcombo, BTN_TOUCH, 0);
 223                        wacom_report_key(wcombo, BTN_STYLUS, 0);
 224                        wacom_report_key(wcombo, BTN_STYLUS2, 0);
 225                }
 226                wacom->id[0] = 0;
 227                wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
 228                wacom_report_key(wcombo, wacom->tool[0], 0);
 229        }
 230
 231        /* send pad data */
 232        switch (wacom->features->type) {
 233            case WACOM_G4:
 234                if (data[7] & 0xf8) {
 235                        wacom_input_sync(wcombo); /* sync last event */
 236                        wacom->id[1] = PAD_DEVICE_ID;
 237                        wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
 238                        wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
 239                        rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
 240                        wacom_report_rel(wcombo, REL_WHEEL, rw);
 241                        wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
 242                        wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
 243                        wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 244                } else if (wacom->id[1]) {
 245                        wacom_input_sync(wcombo); /* sync last event */
 246                        wacom->id[1] = 0;
 247                        wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
 248                        wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
 249                        wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
 250                        wacom_report_abs(wcombo, ABS_MISC, 0);
 251                        wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 252                }
 253                break;
 254            case WACOM_MO:
 255                if ((data[7] & 0xf8) || (data[8] & 0xff)) {
 256                        wacom_input_sync(wcombo); /* sync last event */
 257                        wacom->id[1] = PAD_DEVICE_ID;
 258                        wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
 259                        wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
 260                        wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
 261                        wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
 262                        wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
 263                        wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
 264                        wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
 265                        wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 266                } else if (wacom->id[1]) {
 267                        wacom_input_sync(wcombo); /* sync last event */
 268                        wacom->id[1] = 0;
 269                        wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
 270                        wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
 271                        wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
 272                        wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
 273                        wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
 274                        wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
 275                        wacom_report_abs(wcombo, ABS_MISC, 0);
 276                        wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 277                }
 278                break;
 279        }
 280        return 1;
 281}
 282
 283static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
 284{
 285        unsigned char *data = wacom->data;
 286        int idx;
 287
 288        /* tool number */
 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 0x012:
 303                                wacom->tool[idx] = BTN_TOOL_PENCIL;
 304                                break;
 305                        case 0x822: /* Pen */
 306                        case 0x842:
 307                        case 0x852:
 308                        case 0x823: /* Intuos3 Grip Pen */
 309                        case 0x813: /* Intuos3 Classic Pen */
 310                        case 0x885: /* Intuos3 Marker Pen */
 311                        case 0x022:
 312                                wacom->tool[idx] = BTN_TOOL_PEN;
 313                                break;
 314                        case 0x832: /* Stroke pen */
 315                        case 0x032:
 316                                wacom->tool[idx] = BTN_TOOL_BRUSH;
 317                                break;
 318                        case 0x007: /* Mouse 4D and 2D */
 319                        case 0x09c:
 320                        case 0x094:
 321                        case 0x017: /* Intuos3 2D Mouse */
 322                                wacom->tool[idx] = BTN_TOOL_MOUSE;
 323                                break;
 324                        case 0x096: /* Lens cursor */
 325                        case 0x097: /* Intuos3 Lens cursor */
 326                                wacom->tool[idx] = BTN_TOOL_LENS;
 327                                break;
 328                        case 0x82a: /* Eraser */
 329                        case 0x85a:
 330                        case 0x91a:
 331                        case 0xd1a:
 332                        case 0x0fa:
 333                        case 0x82b: /* Intuos3 Grip Pen Eraser */
 334                        case 0x81b: /* Intuos3 Classic Pen Eraser */
 335                        case 0x91b: /* Intuos3 Airbrush Eraser */
 336                                wacom->tool[idx] = BTN_TOOL_RUBBER;
 337                                break;
 338                        case 0xd12:
 339                        case 0x912:
 340                        case 0x112:
 341                        case 0x913: /* Intuos3 Airbrush */
 342                                wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
 343                                break;
 344                        default: /* Unknown tool */
 345                                wacom->tool[idx] = BTN_TOOL_PEN;
 346                }
 347                return 1;
 348        }
 349
 350        /* Exit report */
 351        if ((data[1] & 0xfe) == 0x80) {
 352                wacom_report_abs(wcombo, ABS_X, 0);
 353                wacom_report_abs(wcombo, ABS_Y, 0);
 354                wacom_report_abs(wcombo, ABS_DISTANCE, 0);
 355                if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
 356                        wacom_report_key(wcombo, BTN_LEFT, 0);
 357                        wacom_report_key(wcombo, BTN_MIDDLE, 0);
 358                        wacom_report_key(wcombo, BTN_RIGHT, 0);
 359                        wacom_report_key(wcombo, BTN_SIDE, 0);
 360                        wacom_report_key(wcombo, BTN_EXTRA, 0);
 361                        wacom_report_abs(wcombo, ABS_THROTTLE, 0);
 362                        wacom_report_abs(wcombo, ABS_RZ, 0);
 363                } else {
 364                        wacom_report_abs(wcombo, ABS_PRESSURE, 0);
 365                        wacom_report_abs(wcombo, ABS_TILT_X, 0);
 366                        wacom_report_abs(wcombo, ABS_TILT_Y, 0);
 367                        wacom_report_key(wcombo, BTN_STYLUS, 0);
 368                        wacom_report_key(wcombo, BTN_STYLUS2, 0);
 369                        wacom_report_key(wcombo, BTN_TOUCH, 0);
 370                        wacom_report_abs(wcombo, ABS_WHEEL, 0);
 371                }
 372                wacom_report_key(wcombo, wacom->tool[idx], 0);
 373                wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
 374                wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 375                return 2;
 376        }
 377        return 0;
 378}
 379
 380static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo)
 381{
 382        unsigned char *data = wacom->data;
 383        unsigned int t;
 384
 385        /* general pen packet */
 386        if ((data[1] & 0xb8) == 0xa0) {
 387                t = (data[6] << 2) | ((data[7] >> 6) & 3);
 388                wacom_report_abs(wcombo, ABS_PRESSURE, t);
 389                wacom_report_abs(wcombo, ABS_TILT_X,
 390                                ((data[7] << 1) & 0x7e) | (data[8] >> 7));
 391                wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
 392                wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2);
 393                wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4);
 394                wacom_report_key(wcombo, BTN_TOUCH, t > 10);
 395        }
 396
 397        /* airbrush second packet */
 398        if ((data[1] & 0xbc) == 0xb4) {
 399                wacom_report_abs(wcombo, ABS_WHEEL,
 400                                (data[6] << 2) | ((data[7] >> 6) & 3));
 401                wacom_report_abs(wcombo, ABS_TILT_X,
 402                                ((data[7] << 1) & 0x7e) | (data[8] >> 7));
 403                wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
 404        }
 405        return;
 406}
 407
 408static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
 409{
 410        unsigned char *data = wacom->data;
 411        unsigned int t;
 412        int idx, result;
 413
 414        if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
 415                dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
 416                return 0;
 417        }
 418
 419        /* tool number */
 420        idx = data[1] & 0x01;
 421
 422        /* pad packets. Works as a second tool and is always in prox */
 423        if (data[0] == 12) {
 424                /* initiate the pad as a device */
 425                if (wacom->tool[1] != BTN_TOOL_FINGER)
 426                        wacom->tool[1] = BTN_TOOL_FINGER;
 427
 428                wacom_report_key(wcombo, BTN_0, (data[5] & 0x01));
 429                wacom_report_key(wcombo, BTN_1, (data[5] & 0x02));
 430                wacom_report_key(wcombo, BTN_2, (data[5] & 0x04));
 431                wacom_report_key(wcombo, BTN_3, (data[5] & 0x08));
 432                wacom_report_key(wcombo, BTN_4, (data[6] & 0x01));
 433                wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
 434                wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
 435                wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
 436                wacom_report_key(wcombo, BTN_8, (data[5] & 0x10));
 437                wacom_report_key(wcombo, BTN_9, (data[6] & 0x10));
 438                wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
 439                wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
 440
 441                if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
 442                        data[2] | (data[3] & 0x1f) | data[4])
 443                        wacom_report_key(wcombo, wacom->tool[1], 1);
 444                else
 445                        wacom_report_key(wcombo, wacom->tool[1], 0);
 446                wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
 447                wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
 448                return 1;
 449        }
 450
 451        /* process in/out prox events */
 452        result = wacom_intuos_inout(wacom, wcombo);
 453        if (result)
 454                return result-1;
 455
 456        /* Only large I3 and I1 & I2 support Lense Cursor */
 457        if ((wacom->tool[idx] == BTN_TOOL_LENS)
 458                        && ((wacom->features->type == INTUOS3)
 459                        || (wacom->features->type == INTUOS3S)))
 460                return 0;
 461
 462        /* Cintiq doesn't send data when RDY bit isn't set */
 463        if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
 464                 return 0;
 465
 466        if (wacom->features->type >= INTUOS3S) {
 467                wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
 468                wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
 469                wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
 470        } else {
 471                wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2]));
 472                wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4]));
 473                wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
 474        }
 475
 476        /* process general packets */
 477        wacom_intuos_general(wacom, wcombo);
 478
 479        /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
 480        if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
 481
 482                if (data[1] & 0x02) {
 483                        /* Rotation packet */
 484                        if (wacom->features->type >= INTUOS3S) {
 485                                /* I3 marker pen rotation */
 486                                t = (data[6] << 3) | ((data[7] >> 5) & 7);
 487                                t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
 488                                        ((t-1) / 2 + 450)) : (450 - t / 2) ;
 489                                wacom_report_abs(wcombo, ABS_Z, t);
 490                        } else {
 491                                /* 4D mouse rotation packet */
 492                                t = (data[6] << 3) | ((data[7] >> 5) & 7);
 493                                wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ?
 494                                        ((t - 1) / 2) : -t / 2);
 495                        }
 496
 497                } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) {
 498                        /* 4D mouse packet */
 499                        wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
 500                        wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
 501                        wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
 502
 503                        wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x20);
 504                        wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x10);
 505                        t = (data[6] << 2) | ((data[7] >> 6) & 3);
 506                        wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
 507
 508                } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
 509                        /* 2D mouse packet */
 510                        wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x04);
 511                        wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08);
 512                        wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x10);
 513                        wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01)
 514                                                 - ((data[8] & 0x02) >> 1));
 515
 516                        /* I3 2D mouse side buttons */
 517                        if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) {
 518                                wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x40);
 519                                wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x20);
 520                        }
 521
 522                } else if (wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L) {
 523                        /* Lens cursor packets */
 524                        wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
 525                        wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
 526                        wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
 527                        wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x10);
 528                        wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x08);
 529                }
 530        }
 531
 532        wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
 533        wacom_report_key(wcombo, wacom->tool[idx], 1);
 534        wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 535        return 1;
 536}
 537
 538static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
 539{
 540        char *data = wacom->data;
 541        int prox = 0, pressure;
 542        static int stylusInProx, touchInProx = 1, touchOut;
 543        struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
 544
 545        dbg("wacom_tpc_irq: received report #%d", data[0]);
 546
 547        if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */
 548                if (urb->actual_length == 5) {  /* with touch */
 549                        prox = data[0] & 0x03;
 550                } else {  /* with capacity */
 551                        prox = data[1] & 0x03;
 552                }
 553
 554                if (!stylusInProx) { /* stylus not in prox */
 555                        if (prox) {
 556                                if (touchInProx) {
 557                                        wacom->tool[1] = BTN_TOOL_DOUBLETAP;
 558                                        wacom->id[0] = TOUCH_DEVICE_ID;
 559                                        if (urb->actual_length != 5) {
 560                                                wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
 561                                                wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
 562                                                wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
 563                                                wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
 564                                        } else {
 565                                                wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
 566                                                wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
 567                                                wacom_report_key(wcombo, BTN_TOUCH, 1);
 568                                        }
 569                                        wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
 570                                        wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
 571                                        touchOut = 1;
 572                                        return 1;
 573                                }
 574                        } else {
 575                                wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
 576                                wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
 577                                wacom_report_key(wcombo, BTN_TOUCH, 0);
 578                                touchOut = 0;
 579                                touchInProx = 1;
 580                                return 1;
 581                        }
 582                } else if (touchOut || !prox) { /* force touch out-prox */
 583                        wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
 584                        wacom_report_key(wcombo, BTN_TOUCH, 0);
 585                        touchOut = 0;
 586                        touchInProx = 1;
 587                        return 1;
 588                }
 589        } else if (data[0] == 2) { /* Penabled */
 590                prox = data[1] & 0x20;
 591
 592                touchInProx = 0;
 593
 594                wacom->id[0] = ERASER_DEVICE_ID;
 595
 596                /*
 597                 * if going from out of proximity into proximity select between the eraser
 598                 * and the pen based on the state of the stylus2 button, choose eraser if
 599                 * pressed else choose pen. if not a proximity change from out to in, send
 600                 * an out of proximity for previous tool then a in for new tool.
 601                 */
 602                if (prox) { /* in prox */
 603                        if (!wacom->tool[0]) {
 604                                /* Going into proximity select tool */
 605                                wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 606                                if (wacom->tool[1] == BTN_TOOL_PEN)
 607                                        wacom->id[0] = STYLUS_DEVICE_ID;
 608                        } else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) {
 609                                /*
 610                                 * was entered with stylus2 pressed
 611                                 * report out proximity for previous tool
 612                                */
 613                                wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
 614                                wacom_report_key(wcombo, wacom->tool[1], 0);
 615                                wacom_input_sync(wcombo);
 616
 617                                /* set new tool */
 618                                wacom->tool[1] = BTN_TOOL_PEN;
 619                                wacom->id[0] = STYLUS_DEVICE_ID;
 620                                return 0;
 621                        }
 622                        if (wacom->tool[1] != BTN_TOOL_RUBBER) {
 623                                /* Unknown tool selected default to pen tool */
 624                                wacom->tool[1] = BTN_TOOL_PEN;
 625                                wacom->id[0] = STYLUS_DEVICE_ID;
 626                        }
 627                        wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
 628                        wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
 629                        wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
 630                        wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
 631                        pressure = ((data[7] & 0x01) << 8) | data[6];
 632                        if (pressure < 0)
 633                                pressure = wacom->features->pressure_max + pressure + 1;
 634                        wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
 635                        wacom_report_key(wcombo, BTN_TOUCH, pressure);
 636                } else {
 637                        wacom_report_abs(wcombo, ABS_PRESSURE, 0);
 638                        wacom_report_key(wcombo, BTN_STYLUS, 0);
 639                        wacom_report_key(wcombo, BTN_STYLUS2, 0);
 640                        wacom_report_key(wcombo, BTN_TOUCH, 0);
 641                }
 642                wacom_report_key(wcombo, wacom->tool[1], prox);
 643                wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
 644                stylusInProx = prox;
 645                wacom->tool[0] = prox;
 646                return 1;
 647        }
 648        return 0;
 649}
 650
 651int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
 652{
 653        switch (wacom_wac->features->type) {
 654                case PENPARTNER:
 655                        return wacom_penpartner_irq(wacom_wac, wcombo);
 656
 657                case PL:
 658                        return wacom_pl_irq(wacom_wac, wcombo);
 659
 660                case WACOM_G4:
 661                case GRAPHIRE:
 662                case WACOM_MO:
 663                        return wacom_graphire_irq(wacom_wac, wcombo);
 664
 665                case PTU:
 666                        return wacom_ptu_irq(wacom_wac, wcombo);
 667
 668                case INTUOS:
 669                case INTUOS3S:
 670                case INTUOS3:
 671                case INTUOS3L:
 672                case CINTIQ:
 673                case WACOM_BEE:
 674                        return wacom_intuos_irq(wacom_wac, wcombo);
 675
 676                case TABLETPC:
 677                        return wacom_tpc_irq(wacom_wac, wcombo);
 678
 679                default:
 680                        return 0;
 681        }
 682        return 0;
 683}
 684
 685void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 686{
 687        switch (wacom_wac->features->type) {
 688                case WACOM_MO:
 689                        input_dev_mo(input_dev, wacom_wac);
 690                case WACOM_G4:
 691                        input_dev_g4(input_dev, wacom_wac);
 692                        /* fall through */
 693                case GRAPHIRE:
 694                        input_dev_g(input_dev, wacom_wac);
 695                        break;
 696                case WACOM_BEE:
 697                        input_dev_bee(input_dev, wacom_wac);
 698                case INTUOS3:
 699                case INTUOS3L:
 700                case CINTIQ:
 701                        input_dev_i3(input_dev, wacom_wac);
 702                        /* fall through */
 703                case INTUOS3S:
 704                        input_dev_i3s(input_dev, wacom_wac);
 705                        /* fall through */
 706                case INTUOS:
 707                        input_dev_i(input_dev, wacom_wac);
 708                        break;
 709                case PL:
 710                case PTU:
 711                case TABLETPC:
 712                        input_dev_pl(input_dev, wacom_wac);
 713                        /* fall through */
 714                case PENPARTNER:
 715                        input_dev_pt(input_dev, wacom_wac);
 716                        break;
 717        }
 718        return;
 719}
 720
 721static struct wacom_features wacom_features[] = {
 722        { "Wacom Penpartner",    7,   5040,  3780,  255,  0, PENPARTNER },
 723        { "Wacom Graphire",      8,  10206,  7422,  511, 63, GRAPHIRE },
 724        { "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 63, GRAPHIRE },
 725        { "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 63, GRAPHIRE },
 726        { "Wacom Graphire3",     8,  10208,  7424,  511, 63, GRAPHIRE },
 727        { "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 63, GRAPHIRE },
 728        { "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 63, WACOM_G4 },
 729        { "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 63, WACOM_G4 },
 730        { "Wacom BambooFun 4x5", 9,  14760,  9225,  511, 63, WACOM_MO },
 731        { "Wacom BambooFun 6x8", 9,  21648, 13530,  511, 63, WACOM_MO },
 732        { "Wacom Bamboo1 Medium",8,  16704, 12064,  511, 63, GRAPHIRE },
 733        { "Wacom Volito",        8,   5104,  3712,  511, 63, GRAPHIRE },
 734        { "Wacom PenStation2",   8,   3250,  2320,  255, 63, GRAPHIRE },
 735        { "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE },
 736        { "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE },
 737        { "Wacom PenPartner2",   8,   3250,  2320,  511, 63, GRAPHIRE },
 738        { "Wacom Bamboo",        9,  14760,  9225,  511, 63, WACOM_MO },
 739        { "Wacom Bamboo1",       8,   5104,  3712,  511, 63, GRAPHIRE },
 740        { "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS },
 741        { "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS },
 742        { "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS },
 743        { "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 31, INTUOS },
 744        { "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 31, INTUOS },
 745        { "Wacom PL400",         8,   5408,  4056,  255,  0, PL },
 746        { "Wacom PL500",         8,   6144,  4608,  255,  0, PL },
 747        { "Wacom PL600",         8,   6126,  4604,  255,  0, PL },
 748        { "Wacom PL600SX",       8,   6260,  5016,  255,  0, PL },
 749        { "Wacom PL550",         8,   6144,  4608,  511,  0, PL },
 750        { "Wacom PL800",         8,   7220,  5780,  511,  0, PL },
 751        { "Wacom PL700",         8,   6758,  5406,  511,  0, PL },
 752        { "Wacom PL510",         8,   6282,  4762,  511,  0, PL },
 753        { "Wacom DTU710",        8,  34080, 27660,  511,  0, PL },
 754        { "Wacom DTF521",        8,   6282,  4762,  511,  0, PL },
 755        { "Wacom DTF720",        8,   6858,  5506,  511,  0, PL },
 756        { "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU },
 757        { "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 31, INTUOS },
 758        { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
 759        { "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 31, INTUOS },
 760        { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS },
 761        { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS },
 762        { "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 63, INTUOS3S },
 763        { "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 63, INTUOS3 },
 764        { "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 63, INTUOS3 },
 765        { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L },
 766        { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L },
 767        { "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
 768        { "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
 769        { "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
 770        { "Wacom Cintiq 20WSX",  10, 86680, 54180, 1023, 63, WACOM_BEE },
 771        { "Wacom Cintiq 12WX",   10, 53020, 33440, 1023, 63, WACOM_BEE },
 772        { "Wacom DTU1931",        8, 37832, 30305,  511,  0, PL },
 773        { "Wacom ISDv4 90",       8, 26202, 16325,  255,  0, TABLETPC },
 774        { "Wacom ISDv4 93",       8, 26202, 16325,  255,  0, TABLETPC },
 775        { "Wacom ISDv4 9A",       8, 26202, 16325,  255,  0, TABLETPC },
 776        { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
 777        { }
 778};
 779
 780static struct usb_device_id wacom_ids[] = {
 781        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) },
 782        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) },
 783        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
 784        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
 785        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
 786        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
 787        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
 788        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
 789        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) },
 790        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) },
 791        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) },
 792        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
 793        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
 794        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
 795        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
 796        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
 797        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) },
 798        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x69) },
 799        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
 800        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
 801        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
 802        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) },
 803        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) },
 804        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) },
 805        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) },
 806        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) },
 807        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) },
 808        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) },
 809        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) },
 810        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
 811        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
 812        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
 813        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
 814        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) },
 815        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
 816        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
 817        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
 818        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
 819        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
 820        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
 821        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
 822        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
 823        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
 824        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
 825        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
 826        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
 827        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
 828        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
 829        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
 830        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
 831        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) },
 832        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) },
 833        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) },
 834        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) },
 835        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
 836        { }
 837};
 838
 839const struct usb_device_id *get_device_table(void)
 840{
 841        const struct usb_device_id *id_table = wacom_ids;
 842
 843        return id_table;
 844}
 845
 846struct wacom_features * get_wacom_feature(const struct usb_device_id *id)
 847{
 848        int index = id - wacom_ids;
 849        struct wacom_features *wf = &wacom_features[index];
 850
 851        return wf;
 852}
 853
 854MODULE_DEVICE_TABLE(usb, wacom_ids);
 855