Merge branches 'for-4.3/chicony', 'for-4.3/cp2112', 'for-4.3/i2c-hid', 'for-4.3/lenov...
authorJiri Kosina <jkosina@suse.cz>
Tue, 1 Sep 2015 13:37:30 +0000 (15:37 +0200)
committerJiri Kosina <jkosina@suse.cz>
Tue, 1 Sep 2015 13:37:30 +0000 (15:37 +0200)
1  2  3  4  5  6  7  8  9  10  11  12 
drivers/hid/Kconfig
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-multitouch.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c

diff --combined drivers/hid/Kconfig
index e48ee2ca9d22d72d310f0b02e3ae387deb373d84,cc4c6649d19503e236f905e8feafe21440237fea,cc4c6649d19503e236f905e8feafe21440237fea,cc4c6649d19503e236f905e8feafe21440237fea,cc4c6649d19503e236f905e8feafe21440237fea,cc4c6649d19503e236f905e8feafe21440237fea,57c94d7d5834bc7ccd1bb4a4ff0ca9d60d548f21,cc4c6649d19503e236f905e8feafe21440237fea,cc4c6649d19503e236f905e8feafe21440237fea,cc4c6649d19503e236f905e8feafe21440237fea,cc4c6649d19503e236f905e8feafe21440237fea,cc4c6649d19503e236f905e8feafe21440237fea..6ab51ae3c39d5753f5315fd7451db737a311a24e
@@@@@@@@@@@@@ -251,12 -251,6 -251,6 -251,6 -251,6 -251,6 -251,6 -251,6 -251,6 -251,6 -251,6 -251,6 +251,12 @@@@@@@@@@@@@ config HID_EZKE
                ---help---
                Support for Ezkey BTC 8193 keyboard.
            
 +++++++++++config HID_GEMBIRD
 +++++++++++    tristate "Gembird Joypad"
 +++++++++++    depends on HID
 +++++++++++    ---help---
 +++++++++++    Support for Gembird JPD-DualForce 2.
 +++++++++++
            config HID_HOLTEK
                tristate "Holtek HID devices"
                depends on USB_HID
@@@@@@@@@@@@@ -486,6 -480,6 -480,6 -480,6 -480,6 -480,6 -480,7 -480,6 -480,6 -480,6 -480,6 -480,6 +486,7 @@@@@@@@@@@@@ config HID_MULTITOUC
                  - Atmel panels
                  - Cando dual touch panels
                  - Chunghwa panels
++++++ +++++      - CJTouch panels
                  - CVTouch panels
                  - Cypress TrueTouch panels
                  - Elan Microelectronics touch panels
diff --combined drivers/hid/hid-core.c
index d931886dffe8183a16ed2fd7f0e621b479b2fb98,a77d30388b4d0986d6373b85ae201ff68b0b1bcc,157c627750535e8943769e3078de068e4f1c7a47,157c627750535e8943769e3078de068e4f1c7a47,e6fce23b121adb662656bea26d8a4ace812afc9c,157c627750535e8943769e3078de068e4f1c7a47,157c627750535e8943769e3078de068e4f1c7a47,157c627750535e8943769e3078de068e4f1c7a47,157c627750535e8943769e3078de068e4f1c7a47,157c627750535e8943769e3078de068e4f1c7a47,157c627750535e8943769e3078de068e4f1c7a47,157c627750535e8943769e3078de068e4f1c7a47..8d9cb755e08add483bde47f1f9c43dd6ec1867f4
@@@@@@@@@@@@@ -427,7 -427,6 -427,6 -427,6 -427,6 -427,6 -427,6 -427,6 -427,6 -427,6 -427,6 -427,6 +427,7 @@@@@@@@@@@@@ static int hid_parser_local(struct hid_
            {
                __u32 data;
                unsigned n;
 +++++++++++    __u32 count;
            
                data = item_udata(item);
            
                        if (item->size <= 2)
                                data = (parser->global.usage_page << 16) + data;
            
 +++++++++++            count = data - parser->local.usage_minimum;
 +++++++++++            if (count + parser->local.usage_index >= HID_MAX_USAGES) {
 +++++++++++                    /*
 +++++++++++                     * We do not warn if the name is not set, we are
 +++++++++++                     * actually pre-scanning the device.
 +++++++++++                     */
 +++++++++++                    if (dev_name(&parser->device->dev))
 +++++++++++                            hid_warn(parser->device,
 +++++++++++                                     "ignoring exceeding usage max\n");
 +++++++++++                    data = HID_MAX_USAGES - parser->local.usage_index +
 +++++++++++                            parser->local.usage_minimum - 1;
 +++++++++++                    if (data <= 0) {
 +++++++++++                            hid_err(parser->device,
 +++++++++++                                    "no more usage index available\n");
 +++++++++++                            return -1;
 +++++++++++                    }
 +++++++++++            }
 +++++++++++
                        for (n = parser->local.usage_minimum; n <= data; n++)
                                if (hid_add_usage(parser, n)) {
                                        dbg_hid("hid_add_usage failed\n");
@@@@@@@@@@@@@ -1801,9 -1782,6 -1782,6 -1782,6 -1782,9 -1782,6 -1782,6 -1782,6 -1782,6 -1782,6 -1782,6 -1782,6 +1801,9 @@@@@@@@@@@@@ static const struct hid_device_id hid_h
                { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) },
                { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) },
                { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) },
 +++ +++++++    { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) },
 +++ +++++++    { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) },
 +++ +++++++    { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) },
                { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
                { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
                { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
                { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
                { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
                { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
+ ++++++++++    { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
                { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
                { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
                { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
                { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
                { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
                { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
 +++++++++++    { HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD, USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) },
                { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
                { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
                { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
@@@@@@@@@@@@@ -2486,9 -2464,6 -2463,6 -2463,6 -2466,9 -2463,6 -2463,6 -2463,6 -2463,6 -2463,6 -2463,6 -2463,6 +2487,9 @@@@@@@@@@@@@ static const struct hid_device_id hid_m
                { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) },
                { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) },
                { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) },
 +++ +++++++    { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) },
 +++ +++++++    { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) },
 +++ +++++++    { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) },
                { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
                { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
                { }
diff --combined drivers/hid/hid-ids.h
index 624d916d39d240c1a4bcce195015202b76f3621c,7c712dff2ca1c6b26047b866ab9fe80c93d179f8,b04b0820d816323a01d147c702503b0797734ea4,b04b0820d816323a01d147c702503b0797734ea4,b3b225b75d0ab7e497c389d0c9caa777da1f6948,653bfd4b9490305011e92a1fd5197dccba7149ce,591b7d06f54d3e813a22ec891b7b98a050470bcf,b04b0820d816323a01d147c702503b0797734ea4,b04b0820d816323a01d147c702503b0797734ea4,9a59810a0b217eaa3042c793b3adc46b7816f1c7,b04b0820d816323a01d147c702503b0797734ea4,b04b0820d816323a01d147c702503b0797734ea4..814f76fdc7daef35d31c84b376981af6306b5b67
            #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI        0x0290
            #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291
            #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292
 +++ +++++++#define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI        0x0272
 +++ +++++++#define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO         0x0273
 +++ +++++++#define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS         0x0274
            #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY        0x030a
            #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
            #define USB_DEVICE_ID_APPLE_IRCONTROL       0x8240
            #define USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE      0x1053
            #define USB_DEVICE_ID_CHICONY_WIRELESS2     0x1123
            #define USB_DEVICE_ID_CHICONY_AK1D  0x1125
+ ++++++++++#define USB_DEVICE_ID_CHICONY_ACER_SWITCH12 0x1421
            
            #define USB_VENDOR_ID_CHUNGHWAT             0x2247
            #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH  0x0001
            
            #define USB_VENDOR_ID_CIDC          0x1677
            
++++++ +++++#define USB_VENDOR_ID_CJTOUCH               0x24b8
++++++ +++++#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020      0x0020
++++++ +++++#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040      0x0040
++++++ +++++
            #define USB_VENDOR_ID_CMEDIA                0x0d8c
            #define USB_DEVICE_ID_CM109         0x000e
            
            #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR      0x0001
            #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR      0x0002
            
 +++++++++++#define USB_VENDOR_ID_GEMBIRD                       0x11ff
 +++++++++++#define USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2        0x3331
 +++++++++++
            #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
            #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003
            #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100
            #define USB_VENDOR_ID_IRTOUCHSYSTEMS        0x6615
            #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB  0x0070
            
+++++++++ ++#define USB_VENDOR_ID_ITE               0x048d
+++++++++ ++#define USB_DEVICE_ID_ITE_LENOVO_YOGA   0x8386
+++++++++ ++
            #define USB_VENDOR_ID_JABRA         0x0b0e
            #define USB_DEVICE_ID_JABRA_SPEAK_410       0x0412
            #define USB_DEVICE_ID_JABRA_SPEAK_510       0x0420
            #define USB_DEVICE_ID_LOGITECH_DUAL_ACTION  0xc216
            #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2   0xc218
            #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219
+++++ ++++++#define USB_DEVICE_ID_LOGITECH_G29_WHEEL    0xc24f
            #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D  0xc283
            #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO  0xc286
            #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940   0xc287
            #define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688
            
            #define USB_VENDOR_ID_TPV           0x25aa
 -----------#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN       0x8883
 +++++++++++#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882  0x8882
 +++++++++++#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883  0x8883
            
            #define USB_VENDOR_ID_TURBOX                0x062a
            #define USB_DEVICE_ID_TURBOX_KEYBOARD       0x0201
index 7c811252c1cefebb2418944a7f391117a8a92b6d,7c811252c1cefebb2418944a7f391117a8a92b6d,7c811252c1cefebb2418944a7f391117a8a92b6d,6a9b05b328a9d40e06b09ed8f8c6e6010669374b,7c811252c1cefebb2418944a7f391117a8a92b6d,7c811252c1cefebb2418944a7f391117a8a92b6d,ab0434f86f49d6841ae3f33cd42b4782e3d6bdb4,6a9b05b328a9d40e06b09ed8f8c6e6010669374b,6a9b05b328a9d40e06b09ed8f8c6e6010669374b,6a9b05b328a9d40e06b09ed8f8c6e6010669374b,6a9b05b328a9d40e06b09ed8f8c6e6010669374b,6a9b05b328a9d40e06b09ed8f8c6e6010669374b..426b2f1a34501c7516ab39dc631d3c2073591aac
@@@@@@@@@@@@@ -778,16 -778,16 -778,16 -778,9 -778,16 -778,16 -778,9 -778,9 -778,9 -778,9 -778,9 -778,9 +778,16 @@@@@@@@@@@@@ static int mt_input_mapping(struct hid_
                /*
                 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
                 * for the stylus.
   +  ++++++     * The check for mt_report_id ensures we don't process
   +  ++++++     * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical
   +  ++++++     * collection, but within the report ID.
                 */
                if (field->physical == HID_DG_STYLUS)
                        return 0;
   +  ++++++    else if ((field->physical == 0) &&
   +  ++++++             (field->report->id != td->mt_report_id) &&
   +  ++++++             (td->mt_report_id != -1))
   +  ++++++            return 0;
            
                if (field->application == HID_DG_TOUCHSCREEN ||
                    field->application == HID_DG_TOUCHPAD)
@@@@@@@@@@@@@ -1145,6 -1145,6 -1145,6 -1138,6 -1145,6 -1145,6 -1138,14 -1138,6 -1138,6 -1138,6 -1138,6 -1138,6 +1145,14 @@@@@@@@@@@@@ static const struct hid_device_id mt_de
                        MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
                                USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
            
++++++ +++++    /* CJTouch panels */
++++++ +++++    { .driver_data = MT_CLS_NSMU,
++++++ +++++            MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
++++++ +++++                    USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020) },
++++++ +++++    { .driver_data = MT_CLS_NSMU,
++++++ +++++            MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
++++++ +++++                    USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040) },
++++++ +++++
                /* CVTouch panels */
                { .driver_data = MT_CLS_NSMU,
                        MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
diff --combined drivers/hid/wacom_sys.c
index 5cdb044720231e0e32a1f2eb79cacfaefe95c4ce,44958d79d598dfc3a7e6938a2babbf3e1fdc2188,44958d79d598dfc3a7e6938a2babbf3e1fdc2188,4c0ffca97befd61cf3cdd947138d14070c4e7895,01b937e63cf37ec1424a1aad9eee0caef682c010,44958d79d598dfc3a7e6938a2babbf3e1fdc2188,4c0ffca97befd61cf3cdd947138d14070c4e7895,4c0ffca97befd61cf3cdd947138d14070c4e7895,4c0ffca97befd61cf3cdd947138d14070c4e7895,4c0ffca97befd61cf3cdd947138d14070c4e7895,4c0ffca97befd61cf3cdd947138d14070c4e7895,5f6e48e55df9b0ad305a934890e895408417d758..9a4912c1828dad3109b9473305670c79fc20d022
            #define WAC_CMD_ICON_XFER   0x23
            #define WAC_CMD_ICON_BT_XFER        0x26
            #define WAC_CMD_RETRIES             10
+++++++++++ #define WAC_CMD_DELETE_PAIRING      0x20
+++++++++++ #define WAC_CMD_UNPAIR_ALL  0xFF
+++++++++++ #define WAC_REMOTE_SERIAL_MAX_STRLEN        9
            
            #define DEV_ATTR_RW_PERM (S_IRUGO | S_IWUSR | S_IWGRP)
            #define DEV_ATTR_WO_PERM (S_IWUSR | S_IWGRP)
+++++++++++ #define DEV_ATTR_RO_PERM (S_IRUSR | S_IRGRP)
            
            static int wacom_get_report(struct hid_device *hdev, u8 type, u8 *buf,
                                    size_t size, unsigned int retries)
@@@@@@@@@@@@@ -335,7 -335,7 -335,7 -335,7 -335,7 -335,7 -335,7 -335,7 -335,7 -335,7 -335,7 -339,7 +339,7 @@@@@@@@@@@@@ static int wacom_set_device_mode(struc
                        if (error >= 0)
                                error = wacom_get_report(hdev, HID_FEATURE_REPORT,
                                                         rep_data, length, 1);
 ----------     } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
 ++++++++++     } while (error >= 0 && rep_data[1] != mode && limit++ < WAC_MSG_RETRIES);
            
                kfree(rep_data);
            
@@@@@@@@@@@@@ -453,12 -453,12 -453,12 -453,12 -453,12 -453,12 -453,12 -453,12 -453,12 -453,12 -453,12 -457,11 +457,11 @@@@@@@@@@@@@ static void wacom_retrieve_hid_descript
                 * interface number.
                 */
                if (features->type == WIRELESS) {
-----------             if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+++++++++++             if (intf->cur_altsetting->desc.bInterfaceNumber == 0)
+++++++++++                     features->device_type = WACOM_DEVICETYPE_WL_MONITOR;
+++++++++++             else
                                features->device_type = WACOM_DEVICETYPE_NONE;
-----------             } else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) {
-----------                     features->device_type |= WACOM_DEVICETYPE_TOUCH;
-----------                     features->pktlen = WACOM_PKGLEN_BBTOUCH3;
-----------             }
+++++++++++             return;
                }
            
                wacom_parse_hid(hdev, features);
@@@@@@@@@@@@@ -1120,6 -1120,6 -1120,6 -1120,6 -1120,6 -1120,6 -1120,6 -1120,6 -1120,6 -1120,6 -1120,6 -1123,189 +1123,189 @@@@@@@@@@@@@ static ssize_t wacom_store_speed(struc
            static DEVICE_ATTR(speed, DEV_ATTR_RW_PERM,
                        wacom_show_speed, wacom_store_speed);
            
+++++++++++ 
+++++++++++ static ssize_t wacom_show_remote_mode(struct kobject *kobj,
+++++++++++                                   struct kobj_attribute *kattr,
+++++++++++                                   char *buf, int index)
+++++++++++ {
+++++++++++     struct device *dev = container_of(kobj->parent, struct device, kobj);
+++++++++++     struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+++++++++++     struct wacom *wacom = hid_get_drvdata(hdev);
+++++++++++     u8 mode;
+++++++++++ 
+++++++++++     mode = wacom->led.select[index];
+++++++++++     if (mode >= 0 && mode < 3)
+++++++++++             return snprintf(buf, PAGE_SIZE, "%d\n", mode);
+++++++++++     else
+++++++++++             return snprintf(buf, PAGE_SIZE, "%d\n", -1);
+++++++++++ }
+++++++++++ 
+++++++++++ #define DEVICE_EKR_ATTR_GROUP(SET_ID)                                       \
+++++++++++ static ssize_t wacom_show_remote##SET_ID##_mode(struct kobject *kobj,       \
+++++++++++                            struct kobj_attribute *kattr, char *buf) \
+++++++++++ {                                                                   \
+++++++++++     return wacom_show_remote_mode(kobj, kattr, buf, SET_ID);        \
+++++++++++ }                                                                   \
+++++++++++ static struct kobj_attribute remote##SET_ID##_mode_attr = {         \
+++++++++++     .attr = {.name = "remote_mode",                                 \
+++++++++++             .mode = DEV_ATTR_RO_PERM},                              \
+++++++++++     .show = wacom_show_remote##SET_ID##_mode,                       \
+++++++++++ };                                                                  \
+++++++++++ static struct attribute *remote##SET_ID##_serial_attrs[] = {                \
+++++++++++     &remote##SET_ID##_mode_attr.attr,                               \
+++++++++++     NULL                                                            \
+++++++++++ };                                                                  \
+++++++++++ static struct attribute_group remote##SET_ID##_serial_group = {             \
+++++++++++     .name = NULL,                                                   \
+++++++++++     .attrs = remote##SET_ID##_serial_attrs,                         \
+++++++++++ }
+++++++++++ 
+++++++++++ DEVICE_EKR_ATTR_GROUP(0);
+++++++++++ DEVICE_EKR_ATTR_GROUP(1);
+++++++++++ DEVICE_EKR_ATTR_GROUP(2);
+++++++++++ DEVICE_EKR_ATTR_GROUP(3);
+++++++++++ DEVICE_EKR_ATTR_GROUP(4);
+++++++++++ 
+++++++++++ int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, int index)
+++++++++++ {
+++++++++++     int error = 0;
+++++++++++     char *buf;
+++++++++++     struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+++++++++++ 
+++++++++++     wacom_wac->serial[index] = serial;
+++++++++++ 
+++++++++++     buf = kzalloc(WAC_REMOTE_SERIAL_MAX_STRLEN, GFP_KERNEL);
+++++++++++     if (!buf)
+++++++++++             return -ENOMEM;
+++++++++++     snprintf(buf, WAC_REMOTE_SERIAL_MAX_STRLEN, "%d", serial);
+++++++++++     wacom->remote_group[index].name = buf;
+++++++++++ 
+++++++++++     error = sysfs_create_group(wacom->remote_dir,
+++++++++++                                &wacom->remote_group[index]);
+++++++++++     if (error) {
+++++++++++             hid_err(wacom->hdev,
+++++++++++                     "cannot create sysfs group err: %d\n", error);
+++++++++++             kobject_put(wacom->remote_dir);
+++++++++++             return error;
+++++++++++     }
+++++++++++ 
+++++++++++     return 0;
+++++++++++ }
+++++++++++ 
+++++++++++ void wacom_remote_destroy_attr_group(struct wacom *wacom, __u32 serial)
+++++++++++ {
+++++++++++     struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+++++++++++     int i;
+++++++++++ 
+++++++++++     if (!serial)
+++++++++++             return;
+++++++++++ 
+++++++++++     for (i = 0; i < WACOM_MAX_REMOTES; i++) {
+++++++++++             if (wacom_wac->serial[i] == serial) {
+++++++++++                     wacom_wac->serial[i] = 0;
+++++++++++                     wacom->led.select[i] = WACOM_STATUS_UNKNOWN;
+++++++++++                     if (wacom->remote_group[i].name) {
+++++++++++                             sysfs_remove_group(wacom->remote_dir,
+++++++++++                                                &wacom->remote_group[i]);
+++++++++++                             kfree(wacom->remote_group[i].name);
+++++++++++                             wacom->remote_group[i].name = NULL;
+++++++++++                     }
+++++++++++             }
+++++++++++     }
+++++++++++ }
+++++++++++ 
+++++++++++ static int wacom_cmd_unpair_remote(struct wacom *wacom, unsigned char selector)
+++++++++++ {
+++++++++++     const size_t buf_size = 2;
+++++++++++     unsigned char *buf;
+++++++++++     int retval;
+++++++++++ 
+++++++++++     buf = kzalloc(buf_size, GFP_KERNEL);
+++++++++++     if (!buf)
+++++++++++             return -ENOMEM;
+++++++++++ 
+++++++++++     buf[0] = WAC_CMD_DELETE_PAIRING;
+++++++++++     buf[1] = selector;
+++++++++++ 
+++++++++++     retval = wacom_set_report(wacom->hdev, HID_OUTPUT_REPORT, buf,
+++++++++++                               buf_size, WAC_CMD_RETRIES);
+++++++++++     kfree(buf);
+++++++++++ 
+++++++++++     return retval;
+++++++++++ }
+++++++++++ 
+++++++++++ static ssize_t wacom_store_unpair_remote(struct kobject *kobj,
+++++++++++                                      struct kobj_attribute *attr,
+++++++++++                                      const char *buf, size_t count)
+++++++++++ {
+++++++++++     unsigned char selector = 0;
+++++++++++     struct device *dev = container_of(kobj->parent, struct device, kobj);
+++++++++++     struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+++++++++++     struct wacom *wacom = hid_get_drvdata(hdev);
+++++++++++     int err;
+++++++++++ 
+++++++++++     if (!strncmp(buf, "*\n", 2)) {
+++++++++++             selector = WAC_CMD_UNPAIR_ALL;
+++++++++++     } else {
+++++++++++             hid_info(wacom->hdev, "remote: unrecognized unpair code: %s\n",
+++++++++++                      buf);
+++++++++++             return -1;
+++++++++++     }
+++++++++++ 
+++++++++++     mutex_lock(&wacom->lock);
+++++++++++ 
+++++++++++     err = wacom_cmd_unpair_remote(wacom, selector);
+++++++++++     mutex_unlock(&wacom->lock);
+++++++++++ 
+++++++++++     return err < 0 ? err : count;
+++++++++++ }
+++++++++++ 
+++++++++++ static struct kobj_attribute unpair_remote_attr = {
+++++++++++     .attr = {.name = "unpair_remote", .mode = 0200},
+++++++++++     .store = wacom_store_unpair_remote,
+++++++++++ };
+++++++++++ 
+++++++++++ static const struct attribute *remote_unpair_attrs[] = {
+++++++++++     &unpair_remote_attr.attr,
+++++++++++     NULL
+++++++++++ };
+++++++++++ 
+++++++++++ static int wacom_initialize_remote(struct wacom *wacom)
+++++++++++ {
+++++++++++     int error = 0;
+++++++++++     struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+++++++++++     int i;
+++++++++++ 
+++++++++++     if (wacom->wacom_wac.features.type != REMOTE)
+++++++++++             return 0;
+++++++++++ 
+++++++++++     wacom->remote_group[0] = remote0_serial_group;
+++++++++++     wacom->remote_group[1] = remote1_serial_group;
+++++++++++     wacom->remote_group[2] = remote2_serial_group;
+++++++++++     wacom->remote_group[3] = remote3_serial_group;
+++++++++++     wacom->remote_group[4] = remote4_serial_group;
+++++++++++ 
+++++++++++     wacom->remote_dir = kobject_create_and_add("wacom_remote",
+++++++++++                                                &wacom->hdev->dev.kobj);
+++++++++++     if (!wacom->remote_dir)
+++++++++++             return -ENOMEM;
+++++++++++ 
+++++++++++     error = sysfs_create_files(wacom->remote_dir, remote_unpair_attrs);
+++++++++++ 
+++++++++++     if (error) {
+++++++++++             hid_err(wacom->hdev,
+++++++++++                     "cannot create sysfs group err: %d\n", error);
+++++++++++             return error;
+++++++++++     }
+++++++++++ 
+++++++++++     for (i = 0; i < WACOM_MAX_REMOTES; i++) {
+++++++++++             wacom->led.select[i] = WACOM_STATUS_UNKNOWN;
+++++++++++             wacom_wac->serial[i] = 0;
+++++++++++     }
+++++++++++ 
+++++++++++     return 0;
+++++++++++ }
+++++++++++ 
            static struct input_dev *wacom_allocate_input(struct wacom *wacom)
            {
                struct input_dev *input_dev;
                if (!input_dev)
                        return NULL;
            
-----------     input_dev->name = wacom_wac->pen_name;
+++++++++++     input_dev->name = wacom_wac->features.name;
                input_dev->phys = hdev->phys;
                input_dev->dev.parent = &hdev->dev;
                input_dev->open = wacom_open;
                return input_dev;
            }
            
----------- static void wacom_free_inputs(struct wacom *wacom)
----------- {
-----------     struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
----------- 
-               input_free_device(wacom_wac->pen_input);
-               input_free_device(wacom_wac->touch_input);
-               input_free_device(wacom_wac->pad_input);
 ----------     if (wacom_wac->pen_input)
 ----------             input_free_device(wacom_wac->pen_input);
 ----------     if (wacom_wac->touch_input)
 ----------             input_free_device(wacom_wac->touch_input);
 ----------     if (wacom_wac->pad_input)
 ----------             input_free_device(wacom_wac->pad_input);
-----------     wacom_wac->pen_input = NULL;
-----------     wacom_wac->touch_input = NULL;
-----------     wacom_wac->pad_input = NULL;
----------- }
----------- 
----------- static int wacom_allocate_inputs(struct wacom *wacom)
----------- {
-----------     struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
-----------     struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
----------- 
-----------     pen_input_dev = wacom_allocate_input(wacom);
-----------     touch_input_dev = wacom_allocate_input(wacom);
-----------     pad_input_dev = wacom_allocate_input(wacom);
-----------     if (!pen_input_dev || !touch_input_dev || !pad_input_dev) {
-----------             wacom_free_inputs(wacom);
-----------             return -ENOMEM;
-----------     }
----------- 
-----------     wacom_wac->pen_input = pen_input_dev;
-----------     wacom_wac->touch_input = touch_input_dev;
-----------     wacom_wac->touch_input->name = wacom_wac->touch_name;
-----------     wacom_wac->pad_input = pad_input_dev;
-----------     wacom_wac->pad_input->name = wacom_wac->pad_name;
----------- 
-----------     return 0;
----------- }
----------- 
            static void wacom_clean_inputs(struct wacom *wacom)
            {
                if (wacom->wacom_wac.pen_input) {
                        else
                                input_free_device(wacom->wacom_wac.pad_input);
                }
+++++++++++     if (wacom->remote_dir)
+++++++++++             kobject_put(wacom->remote_dir);
                wacom->wacom_wac.pen_input = NULL;
                wacom->wacom_wac.touch_input = NULL;
                wacom->wacom_wac.pad_input = NULL;
                wacom_destroy_leds(wacom);
            }
            
+++++++++++ static int wacom_allocate_inputs(struct wacom *wacom)
+++++++++++ {
+++++++++++     struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+++++++++++ 
+++++++++++     wacom_wac->pen_input = wacom_allocate_input(wacom);
+++++++++++     wacom_wac->touch_input = wacom_allocate_input(wacom);
+++++++++++     wacom_wac->pad_input = wacom_allocate_input(wacom);
+++++++++++     if (!wacom_wac->pen_input || !wacom_wac->touch_input || !wacom_wac->pad_input) {
+++++++++++             wacom_clean_inputs(wacom);
+++++++++++             return -ENOMEM;
+++++++++++     }
+++++++++++ 
+++++++++++     wacom_wac->pen_input->name = wacom_wac->pen_name;
+++++++++++     wacom_wac->touch_input->name = wacom_wac->touch_name;
+++++++++++     wacom_wac->pad_input->name = wacom_wac->pad_name;
+++++++++++ 
+++++++++++     return 0;
+++++++++++ }
+++++++++++ 
            static int wacom_register_inputs(struct wacom *wacom)
            {
                struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
                        error = wacom_initialize_leds(wacom);
                        if (error)
                                goto fail_leds;
+++++++++++ 
+++++++++++             error = wacom_initialize_remote(wacom);
+++++++++++             if (error)
+++++++++++                     goto fail_remote;
                }
            
                return 0;
            
+++++++++++ fail_remote:
+++++++++++     wacom_destroy_leds(wacom);
            fail_leds:
                input_unregister_device(pad_input_dev);
                pad_input_dev = NULL;
                wacom_wac->pad_registered = false;
            fail_register_pad_input:
   -  ------    input_unregister_device(touch_input_dev);
   +  ++++++    if (touch_input_dev)
   +  ++++++            input_unregister_device(touch_input_dev);
                wacom_wac->touch_input = NULL;
                wacom_wac->touch_registered = false;
            fail_register_touch_input:
   -  ------    input_unregister_device(pen_input_dev);
   +  ++++++    if (pen_input_dev)
   +  ++++++            input_unregister_device(pen_input_dev);
                wacom_wac->pen_input = NULL;
                wacom_wac->pen_registered = false;
            fail_register_pen_input:
                return error;
            }
            
 +++ +++++++/*
 +++ +++++++ * Not all devices report physical dimensions from HID.
 +++ +++++++ * Compute the default from hardcoded logical dimension
 +++ +++++++ * and resolution before driver overwrites them.
 +++ +++++++ */
 +++ +++++++static void wacom_set_default_phy(struct wacom_features *features)
 +++ +++++++{
 +++ +++++++    if (features->x_resolution) {
 +++ +++++++            features->x_phy = (features->x_max * 100) /
 +++ +++++++                                    features->x_resolution;
 +++ +++++++            features->y_phy = (features->y_max * 100) /
 +++ +++++++                                    features->y_resolution;
 +++ +++++++    }
 +++ +++++++}
 +++ +++++++
 +++ +++++++static void wacom_calculate_res(struct wacom_features *features)
 +++ +++++++{
 +++ +++++++    /* set unit to "100th of a mm" for devices not reported by HID */
 +++ +++++++    if (!features->unit) {
 +++ +++++++            features->unit = 0x11;
 +++ +++++++            features->unitExpo = -3;
 +++ +++++++    }
 +++ +++++++
 +++ +++++++    features->x_resolution = wacom_calc_hid_res(features->x_max,
 +++ +++++++                                                features->x_phy,
 +++ +++++++                                                features->unit,
 +++ +++++++                                                features->unitExpo);
 +++ +++++++    features->y_resolution = wacom_calc_hid_res(features->y_max,
 +++ +++++++                                                features->y_phy,
 +++ +++++++                                                features->unit,
 +++ +++++++                                                features->unitExpo);
 +++ +++++++}
 +++ +++++++
            static void wacom_wireless_work(struct work_struct *work)
            {
                struct wacom *wacom = container_of(work, struct wacom, work);
                        if (wacom_wac1->features.type != INTUOSHT &&
                            wacom_wac1->features.type != BAMBOO_PT)
                                wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD;
 +++ +++++++            wacom_set_default_phy(&wacom_wac1->features);
 +++ +++++++            wacom_calculate_res(&wacom_wac1->features);
                        snprintf(wacom_wac1->pen_name, WACOM_NAME_MAX, "%s (WL) Pen",
                                 wacom_wac1->features.name);
                        snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
                                wacom_wac2->features =
                                        *((struct wacom_features *)id->driver_data);
                                wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
 +++ +++++++                    wacom_set_default_phy(&wacom_wac2->features);
                                wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096;
 +++ +++++++                    wacom_calculate_res(&wacom_wac2->features);
                                snprintf(wacom_wac2->touch_name, WACOM_NAME_MAX,
                                         "%s (WL) Finger",wacom_wac2->features.name);
                                snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX,
@@@@@@@@@@@@@ -1441,6 -1407,39 -1407,39 -1405,39 -1444,6 -1407,39 -1405,39 -1405,39 -1405,39 -1405,39 -1405,39 -1581,39 +1620,6 @@@@@@@@@@@@@ void wacom_battery_work(struct work_str
                }
            }
            
 --- -------/*
 --- ------- * Not all devices report physical dimensions from HID.
 --- ------- * Compute the default from hardcoded logical dimension
 --- ------- * and resolution before driver overwrites them.
 --- ------- */
 --- -------static void wacom_set_default_phy(struct wacom_features *features)
 --- -------{
 --- -------    if (features->x_resolution) {
 --- -------            features->x_phy = (features->x_max * 100) /
 --- -------                                    features->x_resolution;
 --- -------            features->y_phy = (features->y_max * 100) /
 --- -------                                    features->y_resolution;
 --- -------    }
 --- -------}
 --- -------
 --- -------static void wacom_calculate_res(struct wacom_features *features)
 --- -------{
 --- -------    /* set unit to "100th of a mm" for devices not reported by HID */
 --- -------    if (!features->unit) {
 --- -------            features->unit = 0x11;
 --- -------            features->unitExpo = -3;
 --- -------    }
 --- -------
 --- -------    features->x_resolution = wacom_calc_hid_res(features->x_max,
 --- -------                                                features->x_phy,
 --- -------                                                features->unit,
 --- -------                                                features->unitExpo);
 --- -------    features->y_resolution = wacom_calc_hid_res(features->y_max,
 --- -------                                                features->y_phy,
 --- -------                                                features->unit,
 --- -------                                                features->unitExpo);
 --- -------}
 --- -------
            static size_t wacom_compute_pktlen(struct hid_device *hdev)
            {
                struct hid_report_enum *report_enum;
@@@@@@@@@@@@@ -1553,11 -1552,11 -1552,11 -1550,11 -1556,11 -1552,11 -1550,11 -1550,11 -1550,11 -1550,11 -1550,11 -1726,9 +1732,9 @@@@@@@@@@@@@ static int wacom_probe(struct hid_devic
                mutex_init(&wacom->lock);
                INIT_WORK(&wacom->work, wacom_wireless_work);
            
-----------     if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
-----------             error = wacom_allocate_inputs(wacom);
-----------             if (error)
-----------                     goto fail_allocate_inputs;
-----------     }
+++++++++++     error = wacom_allocate_inputs(wacom);
+++++++++++     if (error)
+++++++++++             goto fail_allocate_inputs;
            
                /*
                 * Bamboo Pad has a generic hid handling for the Pen, and we switch it
                if (error)
                        goto fail_shared_data;
            
-----------     if (!(features->quirks & WACOM_QUIRK_MONITOR) &&
+++++++++++     if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) &&
                     (features->quirks & WACOM_QUIRK_BATTERY)) {
                        error = wacom_initialize_battery(wacom);
                        if (error)
                                goto fail_battery;
                }
            
-----------     if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
-----------             error = wacom_register_inputs(wacom);
-----------             if (error)
-----------                     goto fail_register_inputs;
-----------     }
+++++++++++     error = wacom_register_inputs(wacom);
+++++++++++     if (error)
+++++++++++             goto fail_register_inputs;
            
                if (hdev->bus == BUS_BLUETOOTH) {
                        error = device_create_file(&hdev->dev, &dev_attr_speed);
                /* Note that if query fails it is not a hard failure */
                wacom_query_tablet_data(hdev, features);
            
-----------     if (features->quirks & WACOM_QUIRK_MONITOR)
+++++++++++     if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
                        error = hid_hw_open(hdev);
            
                if (wacom_wac->features.type == INTUOSHT && 
@@@@@@@@@@@@@ -1711,7 -1710,7 -1710,7 -1708,7 -1714,7 -1710,7 -1708,7 -1708,7 -1708,7 -1708,7 -1708,7 -1880,6 +1886,6 @@@@@@@@@@@@@ static struct hid_driver wacom_driver 
                .id_table =     wacom_ids,
                .probe =        wacom_probe,
                .remove =       wacom_remove,
-----------     .event =        wacom_wac_event,
                .report =       wacom_wac_report,
            #ifdef CONFIG_PM
                .resume =       wacom_resume,
diff --combined drivers/hid/wacom_wac.c
index 0d244239e55def103f786254f3f617a84b2f0ba2,0d244239e55def103f786254f3f617a84b2f0ba2,0d244239e55def103f786254f3f617a84b2f0ba2,232da89f4e886fe02b82d452c1a0868f0b65b967,0d244239e55def103f786254f3f617a84b2f0ba2,0d244239e55def103f786254f3f617a84b2f0ba2,232da89f4e886fe02b82d452c1a0868f0b65b967,232da89f4e886fe02b82d452c1a0868f0b65b967,232da89f4e886fe02b82d452c1a0868f0b65b967,232da89f4e886fe02b82d452c1a0868f0b65b967,232da89f4e886fe02b82d452c1a0868f0b65b967,c40a6d14c8f2e3a6578f0c574a585d5a229001ca..0215ab62bb93f1b3669ed02ba1087ab43ffa6456
@@@@@@@@@@@@@ -125,61 -125,61 -125,61 -125,61 -125,61 -125,61 -125,61 -125,61 -125,61 -125,61 -125,61 -125,47 +125,47 @@@@@@@@@@@@@ static int wacom_pl_irq(struct wacom_wa
            
                prox = data[1] & 0x40;
            
-----------     if (prox) {
-----------             wacom->id[0] = ERASER_DEVICE_ID;
-----------             pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
-----------             if (features->pressure_max > 255)
-----------                     pressure = (pressure << 1) | ((data[4] >> 6) & 1);
-----------             pressure += (features->pressure_max + 1) / 2;
----------- 
-----------             /*
-----------              * if going from out of proximity into proximity select between the eraser
-----------              * and the pen based on the state of the stylus2 button, choose eraser if
-----------              * pressed else choose pen. if not a proximity change from out to in, send
-----------              * an out of proximity for previous tool then a in for new tool.
-----------              */
-----------             if (!wacom->tool[0]) {
-----------                     /* Eraser bit set for DTF */
-----------                     if (data[1] & 0x10)
-----------                             wacom->tool[1] = BTN_TOOL_RUBBER;
-----------                     else
-----------                             /* Going into proximity select tool */
-----------                             wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-----------             } else {
-----------                     /* was entered with stylus2 pressed */
-----------                     if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
-----------                             /* report out proximity for previous tool */
-----------                             input_report_key(input, wacom->tool[1], 0);
-----------                             input_sync(input);
-----------                             wacom->tool[1] = BTN_TOOL_PEN;
-----------                             return 0;
-----------                     }
+++++++++++     if (!wacom->id[0]) {
+++++++++++             if ((data[0] & 0x10) || (data[4] & 0x20)) {
+++++++++++                     wacom->tool[0] = BTN_TOOL_RUBBER;
+++++++++++                     wacom->id[0] = ERASER_DEVICE_ID;
                        }
-----------             if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-----------                     /* Unknown tool selected default to pen tool */
-----------                     wacom->tool[1] = BTN_TOOL_PEN;
+++++++++++             else {
+++++++++++                     wacom->tool[0] = BTN_TOOL_PEN;
                                wacom->id[0] = STYLUS_DEVICE_ID;
                        }
-----------             input_report_key(input, wacom->tool[1], prox); /* report in proximity for tool */
-----------             input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
-----------             input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
-----------             input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
-----------             input_report_abs(input, ABS_PRESSURE, pressure);
+++++++++++     }
            
-----------             input_report_key(input, BTN_TOUCH, data[4] & 0x08);
-----------             input_report_key(input, BTN_STYLUS, data[4] & 0x10);
-----------             /* Only allow the stylus2 button to be reported for the pen tool. */
-----------             input_report_key(input, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
-----------     } else {
-----------             /* report proximity-out of a (valid) tool */
-----------             if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-----------                     /* Unknown tool selected default to pen tool */
-----------                     wacom->tool[1] = BTN_TOOL_PEN;
-----------             }
-----------             input_report_key(input, wacom->tool[1], prox);
+++++++++++     /* If the eraser is in prox, STYLUS2 is always set. If we
+++++++++++      * mis-detected the type and notice that STYLUS2 isn't set
+++++++++++      * then force the eraser out of prox and let the pen in.
+++++++++++      */
+++++++++++     if (wacom->tool[0] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
+++++++++++             input_report_key(input, BTN_TOOL_RUBBER, 0);
+++++++++++             input_report_abs(input, ABS_MISC, 0);
+++++++++++             input_sync(input);
+++++++++++             wacom->tool[0] = BTN_TOOL_PEN;
+++++++++++             wacom->id[0] = STYLUS_DEVICE_ID;
                }
            
-----------     wacom->tool[0] = prox; /* Save proximity state */
+++++++++++     pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
+++++++++++     if (features->pressure_max > 255)
+++++++++++             pressure = (pressure << 1) | ((data[4] >> 6) & 1);
+++++++++++     pressure += (features->pressure_max + 1) / 2;
+++++++++++ 
+++++++++++     input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
+++++++++++     input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
+++++++++++     input_report_abs(input, ABS_PRESSURE, pressure);
+++++++++++ 
+++++++++++     input_report_key(input, BTN_TOUCH, data[4] & 0x08);
+++++++++++     input_report_key(input, BTN_STYLUS, data[4] & 0x10);
+++++++++++     /* Only allow the stylus2 button to be reported for the pen tool. */
+++++++++++     input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
+++++++++++ 
+++++++++++     if (!prox)
+++++++++++             wacom->id[0] = 0;
+++++++++++     input_report_key(input, wacom->tool[0], prox);
+++++++++++     input_report_abs(input, ABS_MISC, wacom->id[0]);
                return 1;
            }
            
@@@@@@@@@@@@@ -645,6 -645,6 -645,6 -645,6 -645,6 -645,6 -645,6 -645,6 -645,6 -645,6 -645,6 -631,130 +631,130 @@@@@@@@@@@@@ static int wacom_intuos_inout(struct wa
                return 0;
            }
            
+++++++++++ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len)
+++++++++++ {
+++++++++++     unsigned char *data = wacom_wac->data;
+++++++++++     struct input_dev *input = wacom_wac->pad_input;
+++++++++++     struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+++++++++++     struct wacom_features *features = &wacom_wac->features;
+++++++++++     int bat_charging, bat_percent, touch_ring_mode;
+++++++++++     __u32 serial;
+++++++++++     int i;
+++++++++++ 
+++++++++++     if (data[0] != WACOM_REPORT_REMOTE) {
+++++++++++             dev_dbg(input->dev.parent,
+++++++++++                     "%s: received unknown report #%d", __func__, data[0]);
+++++++++++             return 0;
+++++++++++     }
+++++++++++ 
+++++++++++     serial = data[3] + (data[4] << 8) + (data[5] << 16);
+++++++++++     wacom_wac->id[0] = PAD_DEVICE_ID;
+++++++++++ 
+++++++++++     input_report_key(input, BTN_0, (data[9] & 0x01));
+++++++++++     input_report_key(input, BTN_1, (data[9] & 0x02));
+++++++++++     input_report_key(input, BTN_2, (data[9] & 0x04));
+++++++++++     input_report_key(input, BTN_3, (data[9] & 0x08));
+++++++++++     input_report_key(input, BTN_4, (data[9] & 0x10));
+++++++++++     input_report_key(input, BTN_5, (data[9] & 0x20));
+++++++++++     input_report_key(input, BTN_6, (data[9] & 0x40));
+++++++++++     input_report_key(input, BTN_7, (data[9] & 0x80));
+++++++++++ 
+++++++++++     input_report_key(input, BTN_8, (data[10] & 0x01));
+++++++++++     input_report_key(input, BTN_9, (data[10] & 0x02));
+++++++++++     input_report_key(input, BTN_A, (data[10] & 0x04));
+++++++++++     input_report_key(input, BTN_B, (data[10] & 0x08));
+++++++++++     input_report_key(input, BTN_C, (data[10] & 0x10));
+++++++++++     input_report_key(input, BTN_X, (data[10] & 0x20));
+++++++++++     input_report_key(input, BTN_Y, (data[10] & 0x40));
+++++++++++     input_report_key(input, BTN_Z, (data[10] & 0x80));
+++++++++++ 
+++++++++++     input_report_key(input, BTN_BASE, (data[11] & 0x01));
+++++++++++     input_report_key(input, BTN_BASE2, (data[11] & 0x02));
+++++++++++ 
+++++++++++     if (data[12] & 0x80)
+++++++++++             input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f));
+++++++++++     else
+++++++++++             input_report_abs(input, ABS_WHEEL, 0);
+++++++++++ 
+++++++++++     bat_percent = data[7] & 0x7f;
+++++++++++     bat_charging = !!(data[7] & 0x80);
+++++++++++ 
+++++++++++     if (data[9] | data[10] | (data[11] & 0x03) | data[12])
+++++++++++             input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+++++++++++     else
+++++++++++             input_report_abs(input, ABS_MISC, 0);
+++++++++++ 
+++++++++++     input_event(input, EV_MSC, MSC_SERIAL, serial);
+++++++++++ 
+++++++++++     /*Which mode select (LED light) is currently on?*/
+++++++++++     touch_ring_mode = (data[11] & 0xC0) >> 6;
+++++++++++ 
+++++++++++     for (i = 0; i < WACOM_MAX_REMOTES; i++) {
+++++++++++             if (wacom_wac->serial[i] == serial)
+++++++++++                     wacom->led.select[i] = touch_ring_mode;
+++++++++++     }
+++++++++++ 
+++++++++++     if (!wacom->battery &&
+++++++++++         !(features->quirks & WACOM_QUIRK_BATTERY)) {
+++++++++++             features->quirks |= WACOM_QUIRK_BATTERY;
+++++++++++             INIT_WORK(&wacom->work, wacom_battery_work);
+++++++++++             wacom_schedule_work(wacom_wac);
+++++++++++     }
+++++++++++ 
+++++++++++     wacom_notify_battery(wacom_wac, bat_percent, bat_charging, 1,
+++++++++++                          bat_charging);
+++++++++++ 
+++++++++++     return 1;
+++++++++++ }
+++++++++++ 
+++++++++++ static int wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len)
+++++++++++ {
+++++++++++     struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+++++++++++     unsigned char *data = wacom_wac->data;
+++++++++++     int i;
+++++++++++ 
+++++++++++     if (data[0] != WACOM_REPORT_DEVICE_LIST)
+++++++++++             return 0;
+++++++++++ 
+++++++++++     for (i = 0; i < WACOM_MAX_REMOTES; i++) {
+++++++++++             int j = i * 6;
+++++++++++             int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4];
+++++++++++             bool connected = data[j+2];
+++++++++++ 
+++++++++++             if (connected) {
+++++++++++                     int k;
+++++++++++ 
+++++++++++                     if (wacom_wac->serial[i] == serial)
+++++++++++                             continue;
+++++++++++ 
+++++++++++                     if (wacom_wac->serial[i]) {
+++++++++++                             wacom_remote_destroy_attr_group(wacom,
+++++++++++                                                     wacom_wac->serial[i]);
+++++++++++                     }
+++++++++++ 
+++++++++++                     /* A remote can pair more than once with an EKR,
+++++++++++                      * check to make sure this serial isn't already paired.
+++++++++++                      */
+++++++++++                     for (k = 0; k < WACOM_MAX_REMOTES; k++) {
+++++++++++                             if (wacom_wac->serial[k] == serial)
+++++++++++                                     break;
+++++++++++                     }
+++++++++++ 
+++++++++++                     if (k < WACOM_MAX_REMOTES) {
+++++++++++                             wacom_wac->serial[i] = serial;
+++++++++++                             continue;
+++++++++++                     }
+++++++++++                     wacom_remote_create_attr_group(wacom, serial, i);
+++++++++++ 
+++++++++++             } else if (wacom_wac->serial[i]) {
+++++++++++                     wacom_remote_destroy_attr_group(wacom,
+++++++++++                                                     wacom_wac->serial[i]);
+++++++++++             }
+++++++++++     }
+++++++++++ 
+++++++++++     return 0;
+++++++++++ }
+++++++++++ 
            static void wacom_intuos_general(struct wacom_wac *wacom)
            {
                struct wacom_features *features = &wacom->features;
@@@@@@@@@@@@@ -1437,6 -1437,6 -1437,6 -1437,6 -1437,6 -1437,6 -1437,6 -1437,6 -1437,6 -1437,6 -1437,6 -1547,12 +1547,12 @@@@@@@@@@@@@ static int wacom_wac_pen_event(struct h
                return 0;
            }
            
+++++++++++ static void wacom_wac_pen_pre_report(struct hid_device *hdev,
+++++++++++             struct hid_report *report)
+++++++++++ {
+++++++++++     return;
+++++++++++ }
+++++++++++ 
            static void wacom_wac_pen_report(struct hid_device *hdev,
                        struct hid_report *report)
            {
@@@@@@@@@@@@@ -1491,6 -1491,6 -1491,6 -1491,6 -1491,6 -1491,6 -1491,6 -1491,6 -1491,6 -1491,6 -1491,6 -1607,13 +1607,13 @@@@@@@@@@@@@ static void wacom_wac_finger_usage_mapp
                                wacom_map_usage(input, usage, field, EV_ABS,
                                                ABS_MT_POSITION_Y, 4);
                        break;
+++++++++++     case HID_DG_WIDTH:
+++++++++++     case HID_DG_HEIGHT:
+++++++++++             features->last_slot_field = usage->hid;
+++++++++++             wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
+++++++++++             wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0);
+++++++++++             input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+++++++++++             break;
                case HID_DG_CONTACTID:
                        features->last_slot_field = usage->hid;
                        break;
                        features->last_slot_field = usage->hid;
                        wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
                        break;
+++++++++++     case HID_DG_CONTACTCOUNT:
+++++++++++             wacom_wac->hid_data.cc_index = field->index;
+++++++++++             wacom_wac->hid_data.cc_value_index = usage->usage_index;
+++++++++++             break;
                }
            }
            
@@@@@@@@@@@@@ -1515,6 -1515,6 -1515,6 -1515,6 -1515,6 -1515,6 -1515,6 -1515,6 -1515,6 -1515,6 -1515,6 -1642,10 +1642,10 @@@@@@@@@@@@@ static void wacom_wac_finger_slot(struc
                bool prox = hid_data->tipswitch &&
                            !wacom_wac->shared->stylus_in_proximity;
            
+++++++++++     wacom_wac->hid_data.num_received++;
+++++++++++     if (wacom_wac->hid_data.num_received > wacom_wac->hid_data.num_expected)
+++++++++++             return;
+++++++++++ 
                if (mt) {
                        int slot;
            
                                         hid_data->x);
                        input_report_abs(input, mt ? ABS_MT_POSITION_Y : ABS_Y,
                                         hid_data->y);
+++++++++++ 
+++++++++++             if (test_bit(ABS_MT_TOUCH_MAJOR, input->absbit)) {
+++++++++++                     input_report_abs(input, ABS_MT_TOUCH_MAJOR, max(hid_data->width, hid_data->height));
+++++++++++                     input_report_abs(input, ABS_MT_TOUCH_MINOR, min(hid_data->width, hid_data->height));
+++++++++++                     if (hid_data->width != hid_data->height)
+++++++++++                             input_report_abs(input, ABS_MT_ORIENTATION, hid_data->width <= hid_data->height ? 0 : 1);
+++++++++++             }
                }
            }
            
@@@@@@@@@@@@@ -1547,6 -1547,6 -1547,6 -1547,6 -1547,6 -1547,6 -1547,6 -1547,6 -1547,6 -1547,6 -1547,6 -1685,12 +1685,12 @@@@@@@@@@@@@ static int wacom_wac_finger_event(struc
                case HID_GD_Y:
                        wacom_wac->hid_data.y = value;
                        break;
+++++++++++     case HID_DG_WIDTH:
+++++++++++             wacom_wac->hid_data.width = value;
+++++++++++             break;
+++++++++++     case HID_DG_HEIGHT:
+++++++++++             wacom_wac->hid_data.height = value;
+++++++++++             break;
                case HID_DG_CONTACTID:
                        wacom_wac->hid_data.id = value;
                        break;
                return 0;
            }
            
+++++++++++ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
+++++++++++             struct hid_report *report)
+++++++++++ {
+++++++++++     struct wacom *wacom = hid_get_drvdata(hdev);
+++++++++++     struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+++++++++++     struct hid_data* hid_data = &wacom_wac->hid_data;
+++++++++++ 
+++++++++++     if (hid_data->cc_index >= 0) {
+++++++++++             struct hid_field *field = report->field[hid_data->cc_index];
+++++++++++             int value = field->value[hid_data->cc_value_index];
+++++++++++             if (value)
+++++++++++                     hid_data->num_expected = value;
+++++++++++     }
+++++++++++     else {
+++++++++++             hid_data->num_expected = wacom_wac->features.touch_max;
+++++++++++     }
+++++++++++ }
+++++++++++ 
            static void wacom_wac_finger_report(struct hid_device *hdev,
                        struct hid_report *report)
            {
                struct input_dev *input = wacom_wac->touch_input;
                unsigned touch_max = wacom_wac->features.touch_max;
            
+++++++++++     /* If more packets of data are expected, give us a chance to
+++++++++++      * process them rather than immediately syncing a partial
+++++++++++      * update.
+++++++++++      */
+++++++++++     if (wacom_wac->hid_data.num_received < wacom_wac->hid_data.num_expected)
+++++++++++             return;
+++++++++++ 
                if (touch_max > 1)
                        input_mt_sync_frame(input);
            
                input_sync(input);
+++++++++++     wacom_wac->hid_data.num_received = 0;
            
                /* keep touch state for pen event */
                wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
@@@@@@@@@@@@@ -1615,6 -1615,6 -1615,6 -1615,6 -1615,6 -1615,6 -1615,6 -1615,6 -1615,6 -1615,6 -1615,6 -1785,25 +1785,25 @@@@@@@@@@@@@ int wacom_wac_event(struct hid_device *
                return 0;
            }
            
+++++++++++ static void wacom_report_events(struct hid_device *hdev, struct hid_report *report)
+++++++++++ {
+++++++++++     int r;
+++++++++++ 
+++++++++++     for (r = 0; r < report->maxfield; r++) {
+++++++++++             struct hid_field *field;
+++++++++++             unsigned count, n;
+++++++++++ 
+++++++++++             field = report->field[r];
+++++++++++             count = field->report_count;
+++++++++++ 
+++++++++++             if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
+++++++++++                     continue;
+++++++++++ 
+++++++++++             for (n = 0; n < count; n++)
+++++++++++                     wacom_wac_event(hdev, field, &field->usage[n], field->value[n]);
+++++++++++     }
+++++++++++ }
+++++++++++ 
            void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
            {
                struct wacom *wacom = hid_get_drvdata(hdev);
                if (wacom_wac->features.type != HID_GENERIC)
                        return;
            
+++++++++++     if (WACOM_PEN_FIELD(field))
+++++++++++             wacom_wac_pen_pre_report(hdev, report);
+++++++++++ 
+++++++++++     if (WACOM_FINGER_FIELD(field))
+++++++++++             wacom_wac_finger_pre_report(hdev, report);
+++++++++++ 
+++++++++++     wacom_report_events(hdev, report);
+++++++++++ 
                if (WACOM_PEN_FIELD(field))
                        return wacom_wac_pen_report(hdev, report);
            
@@@@@@@@@@@@@ -1699,7 -1699,7 -1699,7 -1699,7 -1699,7 -1699,7 -1699,7 -1699,7 -1699,7 -1699,7 -1699,7 -1896,7 +1896,7 @@@@@@@@@@@@@ static void wacom_bpt3_touch_msg(struc
                        int y = (data[3] << 4) | (data[4] & 0x0f);
                        int width, height;
            
-----------             if (features->type >= INTUOSPS && features->type <= INTUOSPL) {
+++++++++++             if (features->type >= INTUOSPS && features->type <= INTUOSHT) {
                                width  = data[5] * 100;
                                height = data[6] * 100;
                        } else {
@@@@@@@@@@@@@ -2118,6 -2118,6 -2118,6 -2118,6 -2118,6 -2118,6 -2118,6 -2118,6 -2118,6 -2118,6 -2118,6 -2315,13 +2315,13 @@@@@@@@@@@@@ void wacom_wac_irq(struct wacom_wac *wa
                        sync = wacom_wireless_irq(wacom_wac, len);
                        break;
            
+++++++++++     case REMOTE:
+++++++++++             if (wacom_wac->data[0] == WACOM_REPORT_DEVICE_LIST)
+++++++++++                     sync = wacom_remote_status_irq(wacom_wac, len);
+++++++++++             else
+++++++++++                     sync = wacom_remote_irq(wacom_wac, len);
+++++++++++             break;
+++++++++++ 
                default:
                        sync = false;
                        break;
@@@@@@@@@@@@@ -2213,9 -2213,9 -2213,9 -2213,6 -2213,9 -2213,9 -2213,6 -2213,6 -2213,6 -2213,6 -2213,6 -2417,6 +2417,9 @@@@@@@@@@@@@ void wacom_setup_device_quirks(struct w
                                features->x_max = 4096;
                                features->y_max = 4096;
                        }
   +  ++++++            else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) {
   +  ++++++                    features->device_type |= WACOM_DEVICETYPE_PAD;
   +  ++++++            }
                }
            
                /*
                 * 0, whose HID descriptor has an application usage of 0xFF0D
                 * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back
                 * out through the HID_GENERIC device created for interface 1,
-----------      * so rewrite this one to be of type BTN_TOOL_FINGER.
+++++++++++      * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH.
                 */
                if (features->type == BAMBOO_PAD)
-----------             features->device_type |= WACOM_DEVICETYPE_TOUCH;
+++++++++++             features->device_type = WACOM_DEVICETYPE_TOUCH;
+++++++++++ 
+++++++++++     if (features->type == REMOTE)
+++++++++++             features->device_type = WACOM_DEVICETYPE_PAD;
            
                if (wacom->hdev->bus == BUS_BLUETOOTH)
                        features->quirks |= WACOM_QUIRK_BATTERY;
                }
            
                if (features->type == WIRELESS) {
----------- 
-----------             /* monitor never has input and pen/touch have delayed create */
-----------             features->quirks |= WACOM_QUIRK_NO_INPUT;
----------- 
-----------             /* must be monitor interface if no device_type set */
-----------             if (features->device_type == WACOM_DEVICETYPE_NONE) {
-----------                     features->quirks |= WACOM_QUIRK_MONITOR;
+++++++++++             if (features->device_type == WACOM_DEVICETYPE_WL_MONITOR) {
                                features->quirks |= WACOM_QUIRK_BATTERY;
                        }
                }
@@@@@@@@@@@@@ -2513,11 -2513,11 -2513,11 -2510,11 -2513,11 -2513,11 -2510,11 -2510,11 -2510,11 -2510,11 -2510,11 -2711,23 +2714,23 @@@@@@@@@@@@@ int wacom_setup_touch_input_capabilitie
                return 0;
            }
            
+++++++++++ static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
+++++++++++                             int button_count)
+++++++++++ {
+++++++++++     int i;
+++++++++++ 
+++++++++++     for (i = 0; i < button_count && i < 10; i++)
+++++++++++             __set_bit(BTN_0 + i, input_dev->keybit);
+++++++++++     for (i = 10; i < button_count && i < 16; i++)
+++++++++++             __set_bit(BTN_A + (i-10), input_dev->keybit);
+++++++++++     for (i = 16; i < button_count && i < 18; i++)
+++++++++++             __set_bit(BTN_BASE + (i-16), input_dev->keybit);
+++++++++++ }
+++++++++++ 
            int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
                                           struct wacom_wac *wacom_wac)
            {
                struct wacom_features *features = &wacom_wac->features;
-----------     int i;
            
                if (!(features->device_type & WACOM_DEVICETYPE_PAD))
                        return -ENODEV;
                /* kept for making udev and libwacom accepting the pad */
                __set_bit(BTN_STYLUS, input_dev->keybit);
            
+++++++++++     wacom_setup_numbered_buttons(input_dev, features->numbered_buttons);
+++++++++++ 
                switch (features->type) {
+++++++++++ 
+++++++++++     case CINTIQ_HYBRID:
+++++++++++     case DTK:
+++++++++++     case DTUS:
                case GRAPHIRE_BT:
-----------             __set_bit(BTN_0, input_dev->keybit);
-----------             __set_bit(BTN_1, input_dev->keybit);
                        break;
            
                case WACOM_MO:
                        break;
            
                case WACOM_24HD:
-----------             __set_bit(BTN_A, input_dev->keybit);
-----------             __set_bit(BTN_B, input_dev->keybit);
-----------             __set_bit(BTN_C, input_dev->keybit);
-----------             __set_bit(BTN_X, input_dev->keybit);
-----------             __set_bit(BTN_Y, input_dev->keybit);
-----------             __set_bit(BTN_Z, input_dev->keybit);
----------- 
-----------             for (i = 0; i < 10; i++)
-----------                     __set_bit(BTN_0 + i, input_dev->keybit);
----------- 
                        __set_bit(KEY_PROG1, input_dev->keybit);
                        __set_bit(KEY_PROG2, input_dev->keybit);
                        __set_bit(KEY_PROG3, input_dev->keybit);
                        __set_bit(INPUT_PROP_ACCELEROMETER, input_dev->propbit);
                        break;
            
-----------     case DTK:
-----------             for (i = 0; i < 6; i++)
-----------                     __set_bit(BTN_0 + i, input_dev->keybit);
----------- 
-----------             break;
----------- 
                case WACOM_22HD:
                        __set_bit(KEY_PROG1, input_dev->keybit);
                        __set_bit(KEY_PROG2, input_dev->keybit);
                        /* fall through */
            
                case WACOM_21UX2:
-----------             __set_bit(BTN_A, input_dev->keybit);
-----------             __set_bit(BTN_B, input_dev->keybit);
-----------             __set_bit(BTN_C, input_dev->keybit);
-----------             __set_bit(BTN_X, input_dev->keybit);
-----------             __set_bit(BTN_Y, input_dev->keybit);
-----------             __set_bit(BTN_Z, input_dev->keybit);
-----------             __set_bit(BTN_BASE, input_dev->keybit);
-----------             __set_bit(BTN_BASE2, input_dev->keybit);
-----------             /* fall through */
----------- 
                case WACOM_BEE:
-----------             __set_bit(BTN_8, input_dev->keybit);
-----------             __set_bit(BTN_9, input_dev->keybit);
-----------             /* fall through */
----------- 
                case CINTIQ:
-----------             for (i = 0; i < 8; i++)
-----------                     __set_bit(BTN_0 + i, input_dev->keybit);
----------- 
                        input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
                        input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
                        break;
            
                case WACOM_13HD:
-----------             for (i = 0; i < 9; i++)
-----------                     __set_bit(BTN_0 + i, input_dev->keybit);
----------- 
                        input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
                        break;
            
                case INTUOS3:
                case INTUOS3L:
-----------             __set_bit(BTN_4, input_dev->keybit);
-----------             __set_bit(BTN_5, input_dev->keybit);
-----------             __set_bit(BTN_6, input_dev->keybit);
-----------             __set_bit(BTN_7, input_dev->keybit);
----------- 
                        input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
                        /* fall through */
            
                case INTUOS3S:
-----------             __set_bit(BTN_0, input_dev->keybit);
-----------             __set_bit(BTN_1, input_dev->keybit);
-----------             __set_bit(BTN_2, input_dev->keybit);
-----------             __set_bit(BTN_3, input_dev->keybit);
----------- 
                        input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
                        break;
            
                case INTUOS5L:
                case INTUOSPM:
                case INTUOSPL:
-----------             __set_bit(BTN_7, input_dev->keybit);
-----------             __set_bit(BTN_8, input_dev->keybit);
-----------             /* fall through */
----------- 
                case INTUOS5S:
                case INTUOSPS:
-----------             for (i = 0; i < 7; i++)
-----------                     __set_bit(BTN_0 + i, input_dev->keybit);
----------- 
                        input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
                        break;
            
            
                case INTUOS4:
                case INTUOS4L:
-----------             __set_bit(BTN_7, input_dev->keybit);
-----------             __set_bit(BTN_8, input_dev->keybit);
-----------             /* fall through */
----------- 
                case INTUOS4S:
-----------             for (i = 0; i < 7; i++)
-----------                     __set_bit(BTN_0 + i, input_dev->keybit);
----------- 
                        input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
                        break;
            
-----------     case CINTIQ_HYBRID:
-----------             for (i = 0; i < 9; i++)
-----------                     __set_bit(BTN_0 + i, input_dev->keybit);
----------- 
-----------             break;
----------- 
-----------     case DTUS:
-----------             for (i = 0; i < 4; i++)
-----------                     __set_bit(BTN_0 + i, input_dev->keybit);
-----------             break;
----------- 
                case INTUOSHT:
                case BAMBOO_PT:
                        __clear_bit(ABS_MISC, input_dev->absbit);
            
                        break;
            
+++++++++++     case REMOTE:
+++++++++++             input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
+++++++++++             input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+++++++++++             break;
+++++++++++ 
                default:
                        /* no pad supported */
                        return -ENODEV;
@@@@@@@@@@@@@ -2723,7 -2723,7 -2723,7 -2720,7 -2723,7 -2723,7 -2720,7 -2720,7 -2720,7 -2720,7 -2720,7 -2871,7 +2874,7 @@@@@@@@@@@@@ static const struct wacom_features waco
                  GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
            static const struct wacom_features wacom_features_0x81 =
                { "Wacom Graphire BT", 16704, 12064, 511, 32,
-----------       GRAPHIRE_BT, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+++++++++++       GRAPHIRE_BT, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES, 2 };
            static const struct wacom_features wacom_features_0x11 =
                { "Wacom Graphire2 4x5", 10206, 7422, 511, 63,
                  GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
@@@@@@@@@@@@@ -2849,77 -2849,77 -2849,77 -2846,77 -2849,77 -2849,77 -2846,77 -2846,77 -2846,77 -2846,77 -2846,77 -2997,77 +3000,77 @@@@@@@@@@@@@ static const struct wacom_features waco
                  INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
            static const struct wacom_features wacom_features_0xB0 =
                { "Wacom Intuos3 4x5", 25400, 20320, 1023, 63,
-----------       INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 4 };
            static const struct wacom_features wacom_features_0xB1 =
                { "Wacom Intuos3 6x8", 40640, 30480, 1023, 63,
-----------       INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
            static const struct wacom_features wacom_features_0xB2 =
                { "Wacom Intuos3 9x12", 60960, 45720, 1023, 63,
-----------       INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
            static const struct wacom_features wacom_features_0xB3 =
                { "Wacom Intuos3 12x12", 60960, 60960, 1023, 63,
-----------       INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
            static const struct wacom_features wacom_features_0xB4 =
                { "Wacom Intuos3 12x19", 97536, 60960, 1023, 63,
-----------       INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
            static const struct wacom_features wacom_features_0xB5 =
                { "Wacom Intuos3 6x11", 54204, 31750, 1023, 63,
-----------       INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
            static const struct wacom_features wacom_features_0xB7 =
                { "Wacom Intuos3 4x6", 31496, 19685, 1023, 63,
-----------       INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 4 };
            static const struct wacom_features wacom_features_0xB8 =
                { "Wacom Intuos4 4x6", 31496, 19685, 2047, 63,
-----------       INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7 };
            static const struct wacom_features wacom_features_0xB9 =
                { "Wacom Intuos4 6x9", 44704, 27940, 2047, 63,
-----------       INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
            static const struct wacom_features wacom_features_0xBA =
                { "Wacom Intuos4 8x13", 65024, 40640, 2047, 63,
-----------       INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
            static const struct wacom_features wacom_features_0xBB =
                { "Wacom Intuos4 12x19", 97536, 60960, 2047, 63,
-----------       INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
            static const struct wacom_features wacom_features_0xBC =
                { "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
-----------       INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
            static const struct wacom_features wacom_features_0xBD =
                { "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
-----------       INTUOS4WL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS4WL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
            static const struct wacom_features wacom_features_0x26 =
                { "Wacom Intuos5 touch S", 31496, 19685, 2047, 63,
-----------       INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
+++++++++++       INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, .touch_max = 16 };
            static const struct wacom_features wacom_features_0x27 =
                { "Wacom Intuos5 touch M", 44704, 27940, 2047, 63,
-----------       INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
+++++++++++       INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16 };
            static const struct wacom_features wacom_features_0x28 =
                { "Wacom Intuos5 touch L", 65024, 40640, 2047, 63,
-----------       INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
+++++++++++       INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16 };
            static const struct wacom_features wacom_features_0x29 =
                { "Wacom Intuos5 S", 31496, 19685, 2047, 63,
-----------       INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7 };
            static const struct wacom_features wacom_features_0x2A =
                { "Wacom Intuos5 M", 44704, 27940, 2047, 63,
-----------       INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 };
            static const struct wacom_features wacom_features_0x314 =
                { "Wacom Intuos Pro S", 31496, 19685, 2047, 63,
-----------       INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
+++++++++++       INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, .touch_max = 16,
                  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
            static const struct wacom_features wacom_features_0x315 =
                { "Wacom Intuos Pro M", 44704, 27940, 2047, 63,
-----------       INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
+++++++++++       INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16,
                  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
            static const struct wacom_features wacom_features_0x317 =
                { "Wacom Intuos Pro L", 65024, 40640, 2047, 63,
-----------       INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
+++++++++++       INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16,
                  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
            static const struct wacom_features wacom_features_0xF4 =
                { "Wacom Cintiq 24HD", 104080, 65200, 2047, 63,
-----------       WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
            static const struct wacom_features wacom_features_0xF8 =
                { "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */
-----------       WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
                  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
            static const struct wacom_features wacom_features_0xF6 =
                  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
            static const struct wacom_features wacom_features_0x32A =
                { "Wacom Cintiq 27QHD", 119740, 67520, 2047, 63,
-----------       WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
            static const struct wacom_features wacom_features_0x32B =
                { "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63,
-----------       WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
                  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C };
            static const struct wacom_features wacom_features_0x32C =
                  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32B, .touch_max = 10 };
            static const struct wacom_features wacom_features_0x3F =
                { "Wacom Cintiq 21UX", 87200, 65600, 1023, 63,
-----------       CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 };
            static const struct wacom_features wacom_features_0xC5 =
                { "Wacom Cintiq 20WSX", 86680, 54180, 1023, 63,
-----------       WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };
            static const struct wacom_features wacom_features_0xC6 =
                { "Wacom Cintiq 12WX", 53020, 33440, 1023, 63,
-----------       WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+++++++++++       WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };
            static const struct wacom_features wacom_features_0x304 =
                { "Wacom Cintiq 13HD", 59152, 33448, 1023, 63,
-----------       WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
            static const struct wacom_features wacom_features_0x333 =
                { "Wacom Cintiq 13HD touch", 59152, 33448, 2047, 63,
-----------       WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
                  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 };
            static const struct wacom_features wacom_features_0x335 =
@@@@@@@@@@@@@ -2972,22 -2972,22 -2972,22 -2969,22 -2972,22 -2972,22 -2969,22 -2969,22 -2969,22 -2969,22 -2969,22 -3120,22 +3123,22 @@@@@@@@@@@@@ static const struct wacom_features waco
                  DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
            static const struct wacom_features wacom_features_0xFB =
                { "Wacom DTU1031", 21896, 13760, 511, 0,
-----------       DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+++++++++++       DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
                  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
            static const struct wacom_features wacom_features_0x32F =
                { "Wacom DTU1031X", 22472, 12728, 511, 0,
-----------       DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+++++++++++       DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0,
                  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
            static const struct wacom_features wacom_features_0x336 =
                { "Wacom DTU1141", 23472, 13203, 1023, 0,
-----------       DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+++++++++++       DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
            static const struct wacom_features wacom_features_0x57 =
                { "Wacom DTK2241", 95640, 54060, 2047, 63,
-----------       DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
            static const struct wacom_features wacom_features_0x59 = /* Pen */
                { "Wacom DTH2242", 95640, 54060, 2047, 63,
-----------       DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
                  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D };
            static const struct wacom_features wacom_features_0x5D = /* Touch */
                  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
            static const struct wacom_features wacom_features_0xCC =
                { "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63,
-----------       WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
            static const struct wacom_features wacom_features_0xFA =
                { "Wacom Cintiq 22HD", 95440, 53860, 2047, 63,
-----------       WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
            static const struct wacom_features wacom_features_0x5B =
                { "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63,
-----------       WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
                  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
            static const struct wacom_features wacom_features_0x5E =
@@@@@@@@@@@@@ -3151,7 -3151,7 -3151,7 -3148,7 -3151,7 -3151,7 -3148,7 -3148,7 -3148,7 -3148,7 -3148,7 -3299,7 +3302,7 @@@@@@@@@@@@@ static const struct wacom_features waco
                  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
            static const struct wacom_features wacom_features_0x307 =
                { "Wacom ISDv5 307", 59152, 33448, 2047, 63,
-----------       CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
                  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
            static const struct wacom_features wacom_features_0x309 =
                  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
            static const struct wacom_features wacom_features_0x30A =
                { "Wacom ISDv5 30A", 59152, 33448, 2047, 63,
-----------       CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+++++++++++       CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
                  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
                  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C };
            static const struct wacom_features wacom_features_0x30C =
@@@@@@@@@@@@@ -3177,6 -3177,6 -3177,6 -3174,6 -3177,6 -3177,6 -3174,6 -3174,6 -3174,6 -3174,6 -3174,6 -3325,10 +3328,10 @@@@@@@@@@@@@ static const struct wacom_features waco
                { "Wacom Intuos P M", 21600, 13500, 1023, 31,
                  INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
                  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+++++++++++ static const struct wacom_features wacom_features_0x331 =
+++++++++++     { "Wacom Express Key Remote", 0, 0, 0, 0,
+++++++++++       REMOTE, 0, 0, 18, .check_for_hid_type = true,
+++++++++++       .hid_type = HID_TYPE_USBNONE };
            
            static const struct wacom_features wacom_features_HID_ANY_ID =
                { "Wacom HID", .type = HID_GENERIC };
@@@@@@@@@@@@@ -3332,6 -3332,6 -3332,6 -3329,6 -3332,6 -3332,6 -3329,6 -3329,6 -3329,6 -3329,6 -3329,6 -3484,7 +3487,7 @@@@@@@@@@@@@ const struct hid_device_id wacom_ids[] 
                { USB_DEVICE_WACOM(0x32B) },
                { USB_DEVICE_WACOM(0x32C) },
                { USB_DEVICE_WACOM(0x32F) },
+++++++++++     { USB_DEVICE_WACOM(0x331) },
                { USB_DEVICE_WACOM(0x333) },
                { USB_DEVICE_WACOM(0x335) },
                { USB_DEVICE_WACOM(0x336) },