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\xC5\x82aw 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/slab.h>
  28#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
  29#include <linux/power_supply.h>
  30#endif
  31
  32#include "hid-ids.h"
  33
  34struct wacom_data {
  35        __u16 tool;
  36        unsigned char butstate;
  37        __u8 features;
  38        unsigned char high_speed;
  39#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
  40        int battery_capacity;
  41        struct power_supply battery;
  42        struct power_supply ac;
  43#endif
  44};
  45
  46#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
  47/*percent of battery capacity, 0 means AC online*/
  48static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 };
  49
  50static enum power_supply_property wacom_battery_props[] = {
  51        POWER_SUPPLY_PROP_PRESENT,
  52        POWER_SUPPLY_PROP_CAPACITY,
  53        POWER_SUPPLY_PROP_SCOPE,
  54};
  55
  56static enum power_supply_property wacom_ac_props[] = {
  57        POWER_SUPPLY_PROP_PRESENT,
  58        POWER_SUPPLY_PROP_ONLINE,
  59        POWER_SUPPLY_PROP_SCOPE,
  60};
  61
  62static int wacom_battery_get_property(struct power_supply *psy,
  63                                enum power_supply_property psp,
  64                                union power_supply_propval *val)
  65{
  66        struct wacom_data *wdata = container_of(psy,
  67                                        struct wacom_data, battery);
  68        int power_state = batcap[wdata->battery_capacity];
  69        int ret = 0;
  70
  71        switch (psp) {
  72        case POWER_SUPPLY_PROP_PRESENT:
  73                val->intval = 1;
  74                break;
  75        case POWER_SUPPLY_PROP_SCOPE:
  76                val->intval = POWER_SUPPLY_SCOPE_DEVICE;
  77                break;
  78        case POWER_SUPPLY_PROP_CAPACITY:
  79                /* show 100% battery capacity when charging */
  80                if (power_state == 0)
  81                        val->intval = 100;
  82                else
  83                        val->intval = power_state;
  84                break;
  85        default:
  86                ret = -EINVAL;
  87                break;
  88        }
  89        return ret;
  90}
  91
  92static int wacom_ac_get_property(struct power_supply *psy,
  93                                enum power_supply_property psp,
  94                                union power_supply_propval *val)
  95{
  96        struct wacom_data *wdata = container_of(psy, struct wacom_data, ac);
  97        int power_state = batcap[wdata->battery_capacity];
  98        int ret = 0;
  99
 100        switch (psp) {
 101        case POWER_SUPPLY_PROP_PRESENT:
 102                /* fall through */
 103        case POWER_SUPPLY_PROP_ONLINE:
 104                if (power_state == 0)
 105                        val->intval = 1;
 106                else
 107                        val->intval = 0;
 108                break;
 109        case POWER_SUPPLY_PROP_SCOPE:
 110                val->intval = POWER_SUPPLY_SCOPE_DEVICE;
 111                break;
 112        default:
 113                ret = -EINVAL;
 114                break;
 115        }
 116        return ret;
 117}
 118#endif
 119
 120static void wacom_set_features(struct hid_device *hdev)
 121{
 122        int ret;
 123        __u8 rep_data[2];
 124
 125        /*set high speed, tablet mode*/
 126        rep_data[0] = 0x03;
 127        rep_data[1] = 0x20;
 128        ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
 129                                HID_FEATURE_REPORT);
 130        return;
 131}
 132
 133static void wacom_poke(struct hid_device *hdev, u8 speed)
 134{
 135        struct wacom_data *wdata = hid_get_drvdata(hdev);
 136        int limit, ret;
 137        char rep_data[2];
 138
 139        rep_data[0] = 0x03 ; rep_data[1] = 0x00;
 140        limit = 3;
 141        do {
 142                ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
 143                                HID_FEATURE_REPORT);
 144        } while (ret < 0 && limit-- > 0);
 145
 146        if (ret >= 0) {
 147                if (speed == 0)
 148                        rep_data[0] = 0x05;
 149                else
 150                        rep_data[0] = 0x06;
 151
 152                rep_data[1] = 0x00;
 153                limit = 3;
 154                do {
 155                        ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
 156                                        HID_FEATURE_REPORT);
 157                } while (ret < 0 && limit-- > 0);
 158
 159                if (ret >= 0) {
 160                        wdata->high_speed = speed;
 161                        return;
 162                }
 163        }
 164
 165        /*
 166         * Note that if the raw queries fail, it's not a hard failure and it
 167         * is safe to continue
 168         */
 169        hid_warn(hdev, "failed to poke device, command %d, err %d\n",
 170                 rep_data[0], ret);
 171        return;
 172}
 173
 174static ssize_t wacom_show_speed(struct device *dev,
 175                                struct device_attribute
 176                                *attr, char *buf)
 177{
 178        struct wacom_data *wdata = dev_get_drvdata(dev);
 179
 180        return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed);
 181}
 182
 183static ssize_t wacom_store_speed(struct device *dev,
 184                                struct device_attribute *attr,
 185                                const char *buf, size_t count)
 186{
 187        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
 188        int new_speed;
 189
 190        if (sscanf(buf, "%1d", &new_speed ) != 1)
 191                return -EINVAL;
 192
 193        if (new_speed == 0 || new_speed == 1) {
 194                wacom_poke(hdev, new_speed);
 195                return strnlen(buf, PAGE_SIZE);
 196        } else
 197                return -EINVAL;
 198}
 199
 200static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
 201                wacom_show_speed, wacom_store_speed);
 202
 203static int wacom_gr_parse_report(struct hid_device *hdev,
 204                        struct wacom_data *wdata,
 205                        struct input_dev *input, unsigned char *data)
 206{
 207        int tool, x, y, rw;
 208
 209        tool = 0;
 210        /* Get X & Y positions */
 211        x = le16_to_cpu(*(__le16 *) &data[2]);
 212        y = le16_to_cpu(*(__le16 *) &data[4]);
 213
 214        /* Get current tool identifier */
 215        if (data[1] & 0x90) { /* If pen is in the in/active area */
 216                switch ((data[1] >> 5) & 3) {
 217                case 0: /* Pen */
 218                        tool = BTN_TOOL_PEN;
 219                        break;
 220
 221                case 1: /* Rubber */
 222                        tool = BTN_TOOL_RUBBER;
 223                        break;
 224
 225                case 2: /* Mouse with wheel */
 226                case 3: /* Mouse without wheel */
 227                        tool = BTN_TOOL_MOUSE;
 228                        break;
 229                }
 230
 231                /* Reset tool if out of active tablet area */
 232                if (!(data[1] & 0x10))
 233                        tool = 0;
 234        }
 235
 236        /* If tool changed, notify input subsystem */
 237        if (wdata->tool != tool) {
 238                if (wdata->tool) {
 239                        /* Completely reset old tool state */
 240                        if (wdata->tool == BTN_TOOL_MOUSE) {
 241                                input_report_key(input, BTN_LEFT, 0);
 242                                input_report_key(input, BTN_RIGHT, 0);
 243                                input_report_key(input, BTN_MIDDLE, 0);
 244                                input_report_abs(input, ABS_DISTANCE,
 245                                        input_abs_get_max(input, ABS_DISTANCE));
 246                        } else {
 247                                input_report_key(input, BTN_TOUCH, 0);
 248                                input_report_key(input, BTN_STYLUS, 0);
 249                                input_report_key(input, BTN_STYLUS2, 0);
 250                                input_report_abs(input, ABS_PRESSURE, 0);
 251                        }
 252                        input_report_key(input, wdata->tool, 0);
 253                        input_sync(input);
 254                }
 255                wdata->tool = tool;
 256                if (tool)
 257                        input_report_key(input, tool, 1);
 258        }
 259
 260        if (tool) {
 261                input_report_abs(input, ABS_X, x);
 262                input_report_abs(input, ABS_Y, y);
 263
 264                switch ((data[1] >> 5) & 3) {
 265                case 2: /* Mouse with wheel */
 266                        input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
 267                        rw = (data[6] & 0x01) ? -1 :
 268                                (data[6] & 0x02) ? 1 : 0;
 269                        input_report_rel(input, REL_WHEEL, rw);
 270                        /* fall through */
 271
 272                case 3: /* Mouse without wheel */
 273                        input_report_key(input, BTN_LEFT, data[1] & 0x01);
 274                        input_report_key(input, BTN_RIGHT, data[1] & 0x02);
 275                        /* Compute distance between mouse and tablet */
 276                        rw = 44 - (data[6] >> 2);
 277                        if (rw < 0)
 278                                rw = 0;
 279                        else if (rw > 31)
 280                                rw = 31;
 281                        input_report_abs(input, ABS_DISTANCE, rw);
 282                        break;
 283
 284                default:
 285                        input_report_abs(input, ABS_PRESSURE,
 286                                        data[6] | (((__u16) (data[1] & 0x08)) << 5));
 287                        input_report_key(input, BTN_TOUCH, data[1] & 0x01);
 288                        input_report_key(input, BTN_STYLUS, data[1] & 0x02);
 289                        input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
 290                        break;
 291                }
 292
 293                input_sync(input);
 294        }
 295
 296        /* Report the state of the two buttons at the top of the tablet
 297         * as two extra fingerpad keys (buttons 4 & 5). */
 298        rw = data[7] & 0x03;
 299        if (rw != wdata->butstate) {
 300                wdata->butstate = rw;
 301                input_report_key(input, BTN_0, rw & 0x02);
 302                input_report_key(input, BTN_1, rw & 0x01);
 303                input_report_key(input, BTN_TOOL_FINGER, 0xf0);
 304                input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
 305                input_sync(input);
 306        }
 307
 308#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
 309        /* Store current battery capacity */
 310        rw = (data[7] >> 2 & 0x07);
 311        if (rw != wdata->battery_capacity)
 312                wdata->battery_capacity = rw;
 313#endif
 314        return 1;
 315}
 316
 317static void wacom_i4_parse_pen_report(struct wacom_data *wdata,
 318                        struct input_dev *input, unsigned char *data)
 319{
 320        __u16 x, y, pressure;
 321        __u32 id;
 322
 323        switch (data[1]) {
 324        case 0x80: /* Out of proximity report */
 325                wdata->tool = 0;
 326                input_report_key(input, BTN_TOUCH, 0);
 327                input_report_abs(input, ABS_PRESSURE, 0);
 328                input_report_key(input, wdata->tool, 0);
 329                input_sync(input);
 330                break;
 331        case 0xC2: /* Tool report */
 332                id = ((data[2] << 4) | (data[3] >> 4) |
 333                        ((data[7] & 0x0f) << 20) |
 334                        ((data[8] & 0xf0) << 12)) & 0xfffff;
 335
 336                switch (id) {
 337                case 0x802:
 338                        wdata->tool = BTN_TOOL_PEN;
 339                        break;
 340                case 0x80A:
 341                        wdata->tool = BTN_TOOL_RUBBER;
 342                        break;
 343                }
 344                break;
 345        default: /* Position/pressure report */
 346                x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1);
 347                y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01);
 348                pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5)
 349                        | (data[1] & 0x01);
 350
 351                input_report_key(input, BTN_TOUCH, pressure > 1);
 352
 353                input_report_key(input, BTN_STYLUS, data[1] & 0x02);
 354                input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
 355                input_report_key(input, wdata->tool, 1);
 356                input_report_abs(input, ABS_X, x);
 357                input_report_abs(input, ABS_Y, y);
 358                input_report_abs(input, ABS_PRESSURE, pressure);
 359                input_sync(input);
 360                break;
 361        }
 362
 363        return;
 364}
 365
 366static void wacom_i4_parse_report(struct hid_device *hdev,
 367                        struct wacom_data *wdata,
 368                        struct input_dev *input, unsigned char *data)
 369{
 370        switch (data[0]) {
 371        case 0x00: /* Empty report */
 372                break;
 373        case 0x02: /* Pen report */
 374                wacom_i4_parse_pen_report(wdata, input, data);
 375                break;
 376        case 0x03: /* Features Report */
 377                wdata->features = data[2];
 378                break;
 379        case 0x0C: /* Button report */
 380                break;
 381        default:
 382                hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]);
 383                break;
 384        }
 385}
 386
 387static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
 388                u8 *raw_data, int size)
 389{
 390        struct wacom_data *wdata = hid_get_drvdata(hdev);
 391        struct hid_input *hidinput;
 392        struct input_dev *input;
 393        unsigned char *data = (unsigned char *) raw_data;
 394        int i;
 395
 396        if (!(hdev->claimed & HID_CLAIMED_INPUT))
 397                return 0;
 398
 399        hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
 400        input = hidinput->input;
 401
 402        /* Check if this is a tablet report */
 403        if (data[0] != 0x03)
 404                return 0;
 405
 406        switch (hdev->product) {
 407        case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
 408                return wacom_gr_parse_report(hdev, wdata, input, data);
 409                break;
 410        case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
 411                i = 1;
 412
 413                switch (data[0]) {
 414                case 0x04:
 415                        wacom_i4_parse_report(hdev, wdata, input, data + i);
 416                        i += 10;
 417                        /* fall through */
 418                case 0x03:
 419                        wacom_i4_parse_report(hdev, wdata, input, data + i);
 420                        i += 10;
 421                        wacom_i4_parse_report(hdev, wdata, input, data + i);
 422                        break;
 423                default:
 424                        hid_err(hdev, "Unknown report: %d,%d size:%d\n",
 425                                        data[0], data[1], size);
 426                        return 0;
 427                }
 428        }
 429        return 1;
 430}
 431
 432static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 433        struct hid_field *field, struct hid_usage *usage, unsigned long **bit,
 434                                                                int *max)
 435{
 436        struct input_dev *input = hi->input;
 437
 438        __set_bit(INPUT_PROP_POINTER, input->propbit);
 439
 440        /* Basics */
 441        input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
 442
 443        __set_bit(REL_WHEEL, input->relbit);
 444
 445        __set_bit(BTN_TOOL_PEN, input->keybit);
 446        __set_bit(BTN_TOUCH, input->keybit);
 447        __set_bit(BTN_STYLUS, input->keybit);
 448        __set_bit(BTN_STYLUS2, input->keybit);
 449        __set_bit(BTN_LEFT, input->keybit);
 450        __set_bit(BTN_RIGHT, input->keybit);
 451        __set_bit(BTN_MIDDLE, input->keybit);
 452
 453        /* Pad */
 454        input->evbit[0] |= BIT(EV_MSC);
 455
 456        __set_bit(MSC_SERIAL, input->mscbit);
 457
 458        __set_bit(BTN_0, input->keybit);
 459        __set_bit(BTN_1, input->keybit);
 460        __set_bit(BTN_TOOL_FINGER, input->keybit);
 461
 462        /* Distance, rubber and mouse */
 463        __set_bit(BTN_TOOL_RUBBER, input->keybit);
 464        __set_bit(BTN_TOOL_MOUSE, input->keybit);
 465
 466        switch (hdev->product) {
 467        case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
 468                input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
 469                input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
 470                input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
 471                input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
 472                break;
 473        case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
 474                input_set_abs_params(input, ABS_X, 0, 40640, 4, 0);
 475                input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0);
 476                input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0);
 477                break;
 478        }
 479
 480        return 0;
 481}
 482
 483static int wacom_probe(struct hid_device *hdev,
 484                const struct hid_device_id *id)
 485{
 486        struct wacom_data *wdata;
 487        int ret;
 488
 489        wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
 490        if (wdata == NULL) {
 491                hid_err(hdev, "can't alloc wacom descriptor\n");
 492                return -ENOMEM;
 493        }
 494
 495        hid_set_drvdata(hdev, wdata);
 496
 497        /* Parse the HID report now */
 498        ret = hid_parse(hdev);
 499        if (ret) {
 500                hid_err(hdev, "parse failed\n");
 501                goto err_free;
 502        }
 503
 504        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 505        if (ret) {
 506                hid_err(hdev, "hw start failed\n");
 507                goto err_free;
 508        }
 509
 510        ret = device_create_file(&hdev->dev, &dev_attr_speed);
 511        if (ret)
 512                hid_warn(hdev,
 513                         "can't create sysfs speed attribute err: %d\n", ret);
 514
 515        switch (hdev->product) {
 516        case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
 517                /* Set Wacom mode 2 with high reporting speed */
 518                wacom_poke(hdev, 1);
 519                break;
 520        case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
 521                wdata->features = 0;
 522                wacom_set_features(hdev);
 523                break;
 524        }
 525
 526#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
 527        wdata->battery.properties = wacom_battery_props;
 528        wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
 529        wdata->battery.get_property = wacom_battery_get_property;
 530        wdata->battery.name = "wacom_battery";
 531        wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
 532        wdata->battery.use_for_apm = 0;
 533
 534
 535        ret = power_supply_register(&hdev->dev, &wdata->battery);
 536        if (ret) {
 537                hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
 538                         ret);
 539                goto err_battery;
 540        }
 541
 542        power_supply_powers(&wdata->battery, &hdev->dev);
 543
 544        wdata->ac.properties = wacom_ac_props;
 545        wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
 546        wdata->ac.get_property = wacom_ac_get_property;
 547        wdata->ac.name = "wacom_ac";
 548        wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
 549        wdata->ac.use_for_apm = 0;
 550
 551        ret = power_supply_register(&hdev->dev, &wdata->ac);
 552        if (ret) {
 553                hid_warn(hdev,
 554                         "can't create ac battery attribute, err: %d\n", ret);
 555                goto err_ac;
 556        }
 557
 558        power_supply_powers(&wdata->ac, &hdev->dev);
 559#endif
 560        return 0;
 561
 562#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
 563err_ac:
 564        power_supply_unregister(&wdata->battery);
 565err_battery:
 566        device_remove_file(&hdev->dev, &dev_attr_speed);
 567        hid_hw_stop(hdev);
 568#endif
 569err_free:
 570        kfree(wdata);
 571        return ret;
 572}
 573
 574static void wacom_remove(struct hid_device *hdev)
 575{
 576#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
 577        struct wacom_data *wdata = hid_get_drvdata(hdev);
 578#endif
 579        device_remove_file(&hdev->dev, &dev_attr_speed);
 580        hid_hw_stop(hdev);
 581
 582#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
 583        power_supply_unregister(&wdata->battery);
 584        power_supply_unregister(&wdata->ac);
 585#endif
 586        kfree(hid_get_drvdata(hdev));
 587}
 588
 589static const struct hid_device_id wacom_devices[] = {
 590        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
 591        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
 592
 593        { }
 594};
 595MODULE_DEVICE_TABLE(hid, wacom_devices);
 596
 597static struct hid_driver wacom_driver = {
 598        .name = "wacom",
 599        .id_table = wacom_devices,
 600        .probe = wacom_probe,
 601        .remove = wacom_remove,
 602        .raw_event = wacom_raw_event,
 603        .input_mapped = wacom_input_mapped,
 604};
 605
 606static int __init wacom_init(void)
 607{
 608        int ret;
 609
 610        ret = hid_register_driver(&wacom_driver);
 611        if (ret)
 612                pr_err("can't register wacom driver\n");
 613        return ret;
 614}
 615
 616static void __exit wacom_exit(void)
 617{
 618        hid_unregister_driver(&wacom_driver);
 619}
 620
 621module_init(wacom_init);
 622module_exit(wacom_exit);
 623MODULE_LICENSE("GPL");
 624
 625