linux/drivers/hid/hid-wacom.c
<<
>>
Prefs
   1/*
   2 *  Bluetooth Wacom Tablet support
   3 *
   4 *  Copyright (c) 1999 Andreas Gal
   5 *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
   6 *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
   7 *  Copyright (c) 2006-2007 Jiri Kosina
   8 *  Copyright (c) 2007 Paul Walmsley
   9 *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
  10 *  Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
  11 *  Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
  12 *  Copyright (c) 2011 Przemysław Firszt <przemo@firszt.eu>
  13 */
  14
  15/*
  16 * This program is free software; you can redistribute it and/or modify it
  17 * under the terms of the GNU General Public License as published by the Free
  18 * Software Foundation; either version 2 of the License, or (at your option)
  19 * any later version.
  20 */
  21
  22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  23
  24#include <linux/device.h>
  25#include <linux/hid.h>
  26#include <linux/module.h>
  27#include <linux/leds.h>
  28#include <linux/slab.h>
  29#include <linux/power_supply.h>
  30
  31#include "hid-ids.h"
  32
  33#define PAD_DEVICE_ID   0x0F
  34
  35#define WAC_CMD_LED_CONTROL     0x20
  36
  37struct wacom_data {
  38        __u16 tool;
  39        __u16 butstate;
  40        __u8 whlstate;
  41        __u8 features;
  42        __u32 id;
  43        __u32 serial;
  44        unsigned char high_speed;
  45        __u8 battery_capacity;
  46        __u8 power_raw;
  47        __u8 ps_connected;
  48        struct power_supply battery;
  49        struct power_supply ac;
  50        __u8 led_selector;
  51        struct led_classdev *leds[4];
  52};
  53
  54/*percent of battery capacity for Graphire
  55  8th value means AC online and show 100% capacity */
  56static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
  57/*percent of battery capacity for Intuos4 WL, AC has a separate bit*/
  58static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
  59
  60static enum power_supply_property wacom_battery_props[] = {
  61        POWER_SUPPLY_PROP_PRESENT,
  62        POWER_SUPPLY_PROP_CAPACITY,
  63        POWER_SUPPLY_PROP_SCOPE,
  64};
  65
  66static enum power_supply_property wacom_ac_props[] = {
  67        POWER_SUPPLY_PROP_PRESENT,
  68        POWER_SUPPLY_PROP_ONLINE,
  69        POWER_SUPPLY_PROP_SCOPE,
  70};
  71
  72static void wacom_leds_set_brightness(struct led_classdev *led_dev,
  73                                                enum led_brightness value)
  74{
  75        struct device *dev = led_dev->dev->parent;
  76        struct hid_device *hdev;
  77        struct wacom_data *wdata;
  78        unsigned char *buf;
  79        __u8 led = 0;
  80        int i;
  81
  82        hdev = container_of(dev, struct hid_device, dev);
  83        wdata = hid_get_drvdata(hdev);
  84        for (i = 0; i < 4; ++i) {
  85                if (wdata->leds[i] == led_dev)
  86                        wdata->led_selector = i;
  87        }
  88
  89        led = wdata->led_selector | 0x04;
  90        buf = kzalloc(9, GFP_KERNEL);
  91        if (buf) {
  92                buf[0] = WAC_CMD_LED_CONTROL;
  93                buf[1] = led;
  94                buf[2] = value;
  95                hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT);
  96                kfree(buf);
  97        }
  98
  99        return;
 100}
 101
 102static enum led_brightness wacom_leds_get_brightness(struct led_classdev *led_dev)
 103{
 104        struct wacom_data *wdata;
 105        struct device *dev = led_dev->dev->parent;
 106        int value = 0;
 107        int i;
 108
 109        wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
 110
 111        for (i = 0; i < 4; ++i) {
 112                if (wdata->leds[i] == led_dev) {
 113                        value = wdata->leds[i]->brightness;
 114                        break;
 115                }
 116        }
 117
 118        return value;
 119}
 120
 121
 122static int wacom_initialize_leds(struct hid_device *hdev)
 123{
 124        struct wacom_data *wdata = hid_get_drvdata(hdev);
 125        struct led_classdev *led;
 126        struct device *dev = &hdev->dev;
 127        size_t namesz = strlen(dev_name(dev)) + 12;
 128        char *name;
 129        int i, ret;
 130
 131        wdata->led_selector = 0;
 132
 133        for (i = 0; i < 4; i++) {
 134                led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL);
 135                if (!led) {
 136                        hid_warn(hdev,
 137                                 "can't allocate memory for LED selector\n");
 138                        ret = -ENOMEM;
 139                        goto err;
 140                }
 141
 142                name = (void *)&led[1];
 143                snprintf(name, namesz, "%s:selector:%d", dev_name(dev), i);
 144                led->name = name;
 145                led->brightness = 0;
 146                led->max_brightness = 127;
 147                led->brightness_get = wacom_leds_get_brightness;
 148                led->brightness_set = wacom_leds_set_brightness;
 149
 150                wdata->leds[i] = led;
 151
 152                ret = led_classdev_register(dev, wdata->leds[i]);
 153
 154                if (ret) {
 155                        wdata->leds[i] = NULL;
 156                        kfree(led);
 157                        hid_warn(hdev, "can't register LED\n");
 158                        goto err;
 159                }
 160        }
 161
 162err:
 163        return ret;
 164}
 165
 166static void wacom_destroy_leds(struct hid_device *hdev)
 167{
 168        struct wacom_data *wdata = hid_get_drvdata(hdev);
 169        struct led_classdev *led;
 170        int i;
 171
 172        for (i = 0; i < 4; ++i) {
 173                if (wdata->leds[i]) {
 174                        led = wdata->leds[i];
 175                        wdata->leds[i] = NULL;
 176                        led_classdev_unregister(led);
 177                        kfree(led);
 178                }
 179        }
 180
 181}
 182
 183static int wacom_battery_get_property(struct power_supply *psy,
 184                                enum power_supply_property psp,
 185                                union power_supply_propval *val)
 186{
 187        struct wacom_data *wdata = container_of(psy,
 188                                        struct wacom_data, battery);
 189        int ret = 0;
 190
 191        switch (psp) {
 192        case POWER_SUPPLY_PROP_PRESENT:
 193                val->intval = 1;
 194                break;
 195        case POWER_SUPPLY_PROP_SCOPE:
 196                val->intval = POWER_SUPPLY_SCOPE_DEVICE;
 197                break;
 198        case POWER_SUPPLY_PROP_CAPACITY:
 199                val->intval = wdata->battery_capacity;
 200                break;
 201        default:
 202                ret = -EINVAL;
 203                break;
 204        }
 205        return ret;
 206}
 207
 208static int wacom_ac_get_property(struct power_supply *psy,
 209                                enum power_supply_property psp,
 210                                union power_supply_propval *val)
 211{
 212        struct wacom_data *wdata = container_of(psy, struct wacom_data, ac);
 213        int ret = 0;
 214
 215        switch (psp) {
 216        case POWER_SUPPLY_PROP_PRESENT:
 217                /* fall through */
 218        case POWER_SUPPLY_PROP_ONLINE:
 219                val->intval = wdata->ps_connected;
 220                break;
 221        case POWER_SUPPLY_PROP_SCOPE:
 222                val->intval = POWER_SUPPLY_SCOPE_DEVICE;
 223                break;
 224        default:
 225                ret = -EINVAL;
 226                break;
 227        }
 228        return ret;
 229}
 230
 231static void wacom_set_features(struct hid_device *hdev, u8 speed)
 232{
 233        struct wacom_data *wdata = hid_get_drvdata(hdev);
 234        int limit, ret;
 235        __u8 rep_data[2];
 236
 237        switch (hdev->product) {
 238        case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
 239                rep_data[0] = 0x03 ; rep_data[1] = 0x00;
 240                limit = 3;
 241                do {
 242                        ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
 243                                        HID_FEATURE_REPORT);
 244                } while (ret < 0 && limit-- > 0);
 245
 246                if (ret >= 0) {
 247                        if (speed == 0)
 248                                rep_data[0] = 0x05;
 249                        else
 250                                rep_data[0] = 0x06;
 251
 252                        rep_data[1] = 0x00;
 253                        limit = 3;
 254                        do {
 255                                ret = hdev->hid_output_raw_report(hdev,
 256                                        rep_data, 2, HID_FEATURE_REPORT);
 257                        } while (ret < 0 && limit-- > 0);
 258
 259                        if (ret >= 0) {
 260                                wdata->high_speed = speed;
 261                                return;
 262                        }
 263                }
 264
 265                /*
 266                 * Note that if the raw queries fail, it's not a hard failure
 267                 * and it is safe to continue
 268                 */
 269                hid_warn(hdev, "failed to poke device, command %d, err %d\n",
 270                         rep_data[0], ret);
 271                break;
 272        case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
 273                if (speed == 1)
 274                        wdata->features &= ~0x20;
 275                else
 276                        wdata->features |= 0x20;
 277
 278                rep_data[0] = 0x03;
 279                rep_data[1] = wdata->features;
 280
 281                ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
 282                                        HID_FEATURE_REPORT);
 283                if (ret >= 0)
 284                        wdata->high_speed = speed;
 285                break;
 286        }
 287
 288        return;
 289}
 290
 291static ssize_t wacom_show_speed(struct device *dev,
 292                                struct device_attribute
 293                                *attr, char *buf)
 294{
 295        struct wacom_data *wdata = dev_get_drvdata(dev);
 296
 297        return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed);
 298}
 299
 300static ssize_t wacom_store_speed(struct device *dev,
 301                                struct device_attribute *attr,
 302                                const char *buf, size_t count)
 303{
 304        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
 305        int new_speed;
 306
 307        if (sscanf(buf, "%1d", &new_speed ) != 1)
 308                return -EINVAL;
 309
 310        if (new_speed == 0 || new_speed == 1) {
 311                wacom_set_features(hdev, new_speed);
 312                return strnlen(buf, PAGE_SIZE);
 313        } else
 314                return -EINVAL;
 315}
 316
 317static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
 318                wacom_show_speed, wacom_store_speed);
 319
 320static int wacom_gr_parse_report(struct hid_device *hdev,
 321                        struct wacom_data *wdata,
 322                        struct input_dev *input, unsigned char *data)
 323{
 324        int tool, x, y, rw;
 325
 326        tool = 0;
 327        /* Get X & Y positions */
 328        x = le16_to_cpu(*(__le16 *) &data[2]);
 329        y = le16_to_cpu(*(__le16 *) &data[4]);
 330
 331        /* Get current tool identifier */
 332        if (data[1] & 0x90) { /* If pen is in the in/active area */
 333                switch ((data[1] >> 5) & 3) {
 334                case 0: /* Pen */
 335                        tool = BTN_TOOL_PEN;
 336                        break;
 337
 338                case 1: /* Rubber */
 339                        tool = BTN_TOOL_RUBBER;
 340                        break;
 341
 342                case 2: /* Mouse with wheel */
 343                case 3: /* Mouse without wheel */
 344                        tool = BTN_TOOL_MOUSE;
 345                        break;
 346                }
 347
 348                /* Reset tool if out of active tablet area */
 349                if (!(data[1] & 0x10))
 350                        tool = 0;
 351        }
 352
 353        /* If tool changed, notify input subsystem */
 354        if (wdata->tool != tool) {
 355                if (wdata->tool) {
 356                        /* Completely reset old tool state */
 357                        if (wdata->tool == BTN_TOOL_MOUSE) {
 358                                input_report_key(input, BTN_LEFT, 0);
 359                                input_report_key(input, BTN_RIGHT, 0);
 360                                input_report_key(input, BTN_MIDDLE, 0);
 361                                input_report_abs(input, ABS_DISTANCE,
 362                                        input_abs_get_max(input, ABS_DISTANCE));
 363                        } else {
 364                                input_report_key(input, BTN_TOUCH, 0);
 365                                input_report_key(input, BTN_STYLUS, 0);
 366                                input_report_key(input, BTN_STYLUS2, 0);
 367                                input_report_abs(input, ABS_PRESSURE, 0);
 368                        }
 369                        input_report_key(input, wdata->tool, 0);
 370                        input_sync(input);
 371                }
 372                wdata->tool = tool;
 373                if (tool)
 374                        input_report_key(input, tool, 1);
 375        }
 376
 377        if (tool) {
 378                input_report_abs(input, ABS_X, x);
 379                input_report_abs(input, ABS_Y, y);
 380
 381                switch ((data[1] >> 5) & 3) {
 382                case 2: /* Mouse with wheel */
 383                        input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
 384                        rw = (data[6] & 0x01) ? -1 :
 385                                (data[6] & 0x02) ? 1 : 0;
 386                        input_report_rel(input, REL_WHEEL, rw);
 387                        /* fall through */
 388
 389                case 3: /* Mouse without wheel */
 390                        input_report_key(input, BTN_LEFT, data[1] & 0x01);
 391                        input_report_key(input, BTN_RIGHT, data[1] & 0x02);
 392                        /* Compute distance between mouse and tablet */
 393                        rw = 44 - (data[6] >> 2);
 394                        if (rw < 0)
 395                                rw = 0;
 396                        else if (rw > 31)
 397                                rw = 31;
 398                        input_report_abs(input, ABS_DISTANCE, rw);
 399                        break;
 400
 401                default:
 402                        input_report_abs(input, ABS_PRESSURE,
 403                                        data[6] | (((__u16) (data[1] & 0x08)) << 5));
 404                        input_report_key(input, BTN_TOUCH, data[1] & 0x01);
 405                        input_report_key(input, BTN_STYLUS, data[1] & 0x02);
 406                        input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
 407                        break;
 408                }
 409
 410                input_sync(input);
 411        }
 412
 413        /* Report the state of the two buttons at the top of the tablet
 414         * as two extra fingerpad keys (buttons 4 & 5). */
 415        rw = data[7] & 0x03;
 416        if (rw != wdata->butstate) {
 417                wdata->butstate = rw;
 418                input_report_key(input, BTN_0, rw & 0x02);
 419                input_report_key(input, BTN_1, rw & 0x01);
 420                input_report_key(input, BTN_TOOL_FINGER, 0xf0);
 421                input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
 422                input_sync(input);
 423        }
 424
 425        /* Store current battery capacity and power supply state*/
 426        rw = (data[7] >> 2 & 0x07);
 427        if (rw != wdata->power_raw) {
 428                wdata->power_raw = rw;
 429                wdata->battery_capacity = batcap_gr[rw];
 430                if (rw == 7)
 431                        wdata->ps_connected = 1;
 432                else
 433                        wdata->ps_connected = 0;
 434        }
 435        return 1;
 436}
 437
 438static void wacom_i4_parse_button_report(struct wacom_data *wdata,
 439                        struct input_dev *input, unsigned char *data)
 440{
 441        __u16 new_butstate;
 442        __u8 new_whlstate;
 443        __u8 sync = 0;
 444
 445        new_whlstate = data[1];
 446        if (new_whlstate != wdata->whlstate) {
 447                wdata->whlstate = new_whlstate;
 448                if (new_whlstate & 0x80) {
 449                        input_report_key(input, BTN_TOUCH, 1);
 450                        input_report_abs(input, ABS_WHEEL, (new_whlstate & 0x7f));
 451                        input_report_key(input, BTN_TOOL_FINGER, 1);
 452                } else {
 453                        input_report_key(input, BTN_TOUCH, 0);
 454                        input_report_abs(input, ABS_WHEEL, 0);
 455                        input_report_key(input, BTN_TOOL_FINGER, 0);
 456                }
 457                sync = 1;
 458        }
 459
 460        new_butstate = (data[3] << 1) | (data[2] & 0x01);
 461        if (new_butstate != wdata->butstate) {
 462                wdata->butstate = new_butstate;
 463                input_report_key(input, BTN_0, new_butstate & 0x001);
 464                input_report_key(input, BTN_1, new_butstate & 0x002);
 465                input_report_key(input, BTN_2, new_butstate & 0x004);
 466                input_report_key(input, BTN_3, new_butstate & 0x008);
 467                input_report_key(input, BTN_4, new_butstate & 0x010);
 468                input_report_key(input, BTN_5, new_butstate & 0x020);
 469                input_report_key(input, BTN_6, new_butstate & 0x040);
 470                input_report_key(input, BTN_7, new_butstate & 0x080);
 471                input_report_key(input, BTN_8, new_butstate & 0x100);
 472                input_report_key(input, BTN_TOOL_FINGER, 1);
 473                sync = 1;
 474        }
 475
 476        if (sync) {
 477                input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
 478                input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
 479                input_sync(input);
 480        }
 481}
 482
 483static void wacom_i4_parse_pen_report(struct wacom_data *wdata,
 484                        struct input_dev *input, unsigned char *data)
 485{
 486        __u16 x, y, pressure;
 487        __u8 distance;
 488        __u8 tilt_x, tilt_y;
 489
 490        switch (data[1]) {
 491        case 0x80: /* Out of proximity report */
 492                input_report_key(input, BTN_TOUCH, 0);
 493                input_report_abs(input, ABS_PRESSURE, 0);
 494                input_report_key(input, BTN_STYLUS, 0);
 495                input_report_key(input, BTN_STYLUS2, 0);
 496                input_report_key(input, wdata->tool, 0);
 497                input_report_abs(input, ABS_MISC, 0);
 498                input_event(input, EV_MSC, MSC_SERIAL, wdata->serial);
 499                wdata->tool = 0;
 500                input_sync(input);
 501                break;
 502        case 0xC2: /* Tool report */
 503                wdata->id = ((data[2] << 4) | (data[3] >> 4) |
 504                        ((data[7] & 0x0f) << 20) |
 505                        ((data[8] & 0xf0) << 12));
 506                wdata->serial = ((data[3] & 0x0f) << 28) +
 507                                (data[4] << 20) + (data[5] << 12) +
 508                                (data[6] << 4) + (data[7] >> 4);
 509
 510                switch (wdata->id) {
 511                case 0x100802:
 512                        wdata->tool = BTN_TOOL_PEN;
 513                        break;
 514                case 0x10080A:
 515                        wdata->tool = BTN_TOOL_RUBBER;
 516                        break;
 517                }
 518                break;
 519        default: /* Position/pressure report */
 520                x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1);
 521                y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01);
 522                pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5)
 523                        | (data[1] & 0x01);
 524                distance = (data[9] >> 2) & 0x3f;
 525                tilt_x = ((data[7] << 1) & 0x7e) | (data[8] >> 7);
 526                tilt_y = data[8] & 0x7f;
 527
 528                input_report_key(input, BTN_TOUCH, pressure > 1);
 529
 530                input_report_key(input, BTN_STYLUS, data[1] & 0x02);
 531                input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
 532                input_report_key(input, wdata->tool, 1);
 533                input_report_abs(input, ABS_X, x);
 534                input_report_abs(input, ABS_Y, y);
 535                input_report_abs(input, ABS_PRESSURE, pressure);
 536                input_report_abs(input, ABS_DISTANCE, distance);
 537                input_report_abs(input, ABS_TILT_X, tilt_x);
 538                input_report_abs(input, ABS_TILT_Y, tilt_y);
 539                input_report_abs(input, ABS_MISC, wdata->id);
 540                input_event(input, EV_MSC, MSC_SERIAL, wdata->serial);
 541                input_report_key(input, wdata->tool, 1);
 542                input_sync(input);
 543                break;
 544        }
 545
 546        return;
 547}
 548
 549static void wacom_i4_parse_report(struct hid_device *hdev,
 550                        struct wacom_data *wdata,
 551                        struct input_dev *input, unsigned char *data)
 552{
 553        switch (data[0]) {
 554        case 0x00: /* Empty report */
 555                break;
 556        case 0x02: /* Pen report */
 557                wacom_i4_parse_pen_report(wdata, input, data);
 558                break;
 559        case 0x03: /* Features Report */
 560                wdata->features = data[2];
 561                break;
 562        case 0x0C: /* Button report */
 563                wacom_i4_parse_button_report(wdata, input, data);
 564                break;
 565        default:
 566                hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]);
 567                break;
 568        }
 569}
 570
 571static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
 572                u8 *raw_data, int size)
 573{
 574        struct wacom_data *wdata = hid_get_drvdata(hdev);
 575        struct hid_input *hidinput;
 576        struct input_dev *input;
 577        unsigned char *data = (unsigned char *) raw_data;
 578        int i;
 579        __u8 power_raw;
 580
 581        if (!(hdev->claimed & HID_CLAIMED_INPUT))
 582                return 0;
 583
 584        hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
 585        input = hidinput->input;
 586
 587        switch (hdev->product) {
 588        case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
 589                if (data[0] == 0x03) {
 590                        return wacom_gr_parse_report(hdev, wdata, input, data);
 591                } else {
 592                        hid_err(hdev, "Unknown report: %d,%d size:%d\n",
 593                                        data[0], data[1], size);
 594                        return 0;
 595                }
 596                break;
 597        case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
 598                i = 1;
 599
 600                switch (data[0]) {
 601                case 0x04:
 602                        wacom_i4_parse_report(hdev, wdata, input, data + i);
 603                        i += 10;
 604                        /* fall through */
 605                case 0x03:
 606                        wacom_i4_parse_report(hdev, wdata, input, data + i);
 607                        i += 10;
 608                        wacom_i4_parse_report(hdev, wdata, input, data + i);
 609                        power_raw = data[i+10];
 610                        if (power_raw != wdata->power_raw) {
 611                                wdata->power_raw = power_raw;
 612                                wdata->battery_capacity = batcap_i4[power_raw & 0x07];
 613                                wdata->ps_connected = power_raw & 0x08;
 614                        }
 615
 616                        break;
 617                default:
 618                        hid_err(hdev, "Unknown report: %d,%d size:%d\n",
 619                                        data[0], data[1], size);
 620                        return 0;
 621                }
 622        }
 623        return 1;
 624}
 625
 626static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 627        struct hid_field *field, struct hid_usage *usage, unsigned long **bit,
 628                                                                int *max)
 629{
 630        struct input_dev *input = hi->input;
 631
 632        __set_bit(INPUT_PROP_POINTER, input->propbit);
 633
 634        /* Basics */
 635        input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
 636
 637        __set_bit(REL_WHEEL, input->relbit);
 638
 639        __set_bit(BTN_TOOL_PEN, input->keybit);
 640        __set_bit(BTN_TOUCH, input->keybit);
 641        __set_bit(BTN_STYLUS, input->keybit);
 642        __set_bit(BTN_STYLUS2, input->keybit);
 643        __set_bit(BTN_LEFT, input->keybit);
 644        __set_bit(BTN_RIGHT, input->keybit);
 645        __set_bit(BTN_MIDDLE, input->keybit);
 646
 647        /* Pad */
 648        input_set_capability(input, EV_MSC, MSC_SERIAL);
 649
 650        __set_bit(BTN_0, input->keybit);
 651        __set_bit(BTN_1, input->keybit);
 652        __set_bit(BTN_TOOL_FINGER, input->keybit);
 653
 654        /* Distance, rubber and mouse */
 655        __set_bit(BTN_TOOL_RUBBER, input->keybit);
 656        __set_bit(BTN_TOOL_MOUSE, input->keybit);
 657
 658        switch (hdev->product) {
 659        case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
 660                input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
 661                input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
 662                input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
 663                input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
 664                break;
 665        case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
 666                __set_bit(ABS_WHEEL, input->absbit);
 667                __set_bit(ABS_MISC, input->absbit);
 668                __set_bit(BTN_2, input->keybit);
 669                __set_bit(BTN_3, input->keybit);
 670                __set_bit(BTN_4, input->keybit);
 671                __set_bit(BTN_5, input->keybit);
 672                __set_bit(BTN_6, input->keybit);
 673                __set_bit(BTN_7, input->keybit);
 674                __set_bit(BTN_8, input->keybit);
 675                input_set_abs_params(input, ABS_WHEEL, 0, 71, 0, 0);
 676                input_set_abs_params(input, ABS_X, 0, 40640, 4, 0);
 677                input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0);
 678                input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0);
 679                input_set_abs_params(input, ABS_DISTANCE, 0, 63, 0, 0);
 680                input_set_abs_params(input, ABS_TILT_X, 0, 127, 0, 0);
 681                input_set_abs_params(input, ABS_TILT_Y, 0, 127, 0, 0);
 682                break;
 683        }
 684
 685        return 0;
 686}
 687
 688static int wacom_probe(struct hid_device *hdev,
 689                const struct hid_device_id *id)
 690{
 691        struct wacom_data *wdata;
 692        int ret;
 693
 694        wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
 695        if (wdata == NULL) {
 696                hid_err(hdev, "can't alloc wacom descriptor\n");
 697                return -ENOMEM;
 698        }
 699
 700        hid_set_drvdata(hdev, wdata);
 701
 702        /* Parse the HID report now */
 703        ret = hid_parse(hdev);
 704        if (ret) {
 705                hid_err(hdev, "parse failed\n");
 706                goto err_free;
 707        }
 708
 709        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 710        if (ret) {
 711                hid_err(hdev, "hw start failed\n");
 712                goto err_free;
 713        }
 714
 715        ret = device_create_file(&hdev->dev, &dev_attr_speed);
 716        if (ret)
 717                hid_warn(hdev,
 718                         "can't create sysfs speed attribute err: %d\n", ret);
 719
 720        wdata->features = 0;
 721        wacom_set_features(hdev, 1);
 722
 723        if (hdev->product == USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) {
 724                sprintf(hdev->name, "%s", "Wacom Intuos4 WL");
 725                ret = wacom_initialize_leds(hdev);
 726                if (ret) {
 727                        hid_warn(hdev,
 728                                 "can't create led attribute, err: %d\n", ret);
 729                        goto destroy_leds;
 730                }
 731        }
 732
 733        wdata->battery.properties = wacom_battery_props;
 734        wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
 735        wdata->battery.get_property = wacom_battery_get_property;
 736        wdata->battery.name = "wacom_battery";
 737        wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
 738        wdata->battery.use_for_apm = 0;
 739
 740
 741        ret = power_supply_register(&hdev->dev, &wdata->battery);
 742        if (ret) {
 743                hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
 744                         ret);
 745                goto err_battery;
 746        }
 747
 748        power_supply_powers(&wdata->battery, &hdev->dev);
 749
 750        wdata->ac.properties = wacom_ac_props;
 751        wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
 752        wdata->ac.get_property = wacom_ac_get_property;
 753        wdata->ac.name = "wacom_ac";
 754        wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
 755        wdata->ac.use_for_apm = 0;
 756
 757        ret = power_supply_register(&hdev->dev, &wdata->ac);
 758        if (ret) {
 759                hid_warn(hdev,
 760                         "can't create ac battery attribute, err: %d\n", ret);
 761                goto err_ac;
 762        }
 763
 764        power_supply_powers(&wdata->ac, &hdev->dev);
 765        return 0;
 766
 767err_ac:
 768        power_supply_unregister(&wdata->battery);
 769err_battery:
 770        device_remove_file(&hdev->dev, &dev_attr_speed);
 771        hid_hw_stop(hdev);
 772destroy_leds:
 773        wacom_destroy_leds(hdev);
 774err_free:
 775        kfree(wdata);
 776        return ret;
 777}
 778
 779static void wacom_remove(struct hid_device *hdev)
 780{
 781        struct wacom_data *wdata = hid_get_drvdata(hdev);
 782
 783        wacom_destroy_leds(hdev);
 784        device_remove_file(&hdev->dev, &dev_attr_speed);
 785        hid_hw_stop(hdev);
 786
 787        power_supply_unregister(&wdata->battery);
 788        power_supply_unregister(&wdata->ac);
 789        kfree(hid_get_drvdata(hdev));
 790}
 791
 792static const struct hid_device_id wacom_devices[] = {
 793        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
 794        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
 795
 796        { }
 797};
 798MODULE_DEVICE_TABLE(hid, wacom_devices);
 799
 800static struct hid_driver wacom_driver = {
 801        .name = "wacom",
 802        .id_table = wacom_devices,
 803        .probe = wacom_probe,
 804        .remove = wacom_remove,
 805        .raw_event = wacom_raw_event,
 806        .input_mapped = wacom_input_mapped,
 807};
 808
 809static int __init wacom_init(void)
 810{
 811        int ret;
 812
 813        ret = hid_register_driver(&wacom_driver);
 814        if (ret)
 815                pr_err("can't register wacom driver\n");
 816        return ret;
 817}
 818
 819static void __exit wacom_exit(void)
 820{
 821        hid_unregister_driver(&wacom_driver);
 822}
 823
 824module_init(wacom_init);
 825module_exit(wacom_exit);
 826MODULE_DESCRIPTION("Driver for Wacom Graphire Bluetooth and Wacom Intuos4 WL");
 827MODULE_LICENSE("GPL");
 828
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.