]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
authorJiri Kosina <jkosina@suse.cz>
Tue, 2 May 2017 09:01:10 +0000 (11:01 +0200)
committerJiri Kosina <jkosina@suse.cz>
Tue, 2 May 2017 09:01:10 +0000 (11:01 +0200)
1  2  3  4  5  6  7  8  9  10  11  12 
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
include/linux/hid.h

index 8c54cb8f5d6d1013ec1f4a39e8f88fcfe3333758,fb4cc0d28eea13076c600f6f566efdc8f2291ed9,00e2809724bd718dd43fd5662bfd22854b18c890,1aeb80e5242461830f1d4075f0fb59bcb6ddc898,1aeb80e5242461830f1d4075f0fb59bcb6ddc898,1aeb80e5242461830f1d4075f0fb59bcb6ddc898,1aeb80e5242461830f1d4075f0fb59bcb6ddc898,820bc73ac058218bf91c054573bf983665b05bb1,1aeb80e5242461830f1d4075f0fb59bcb6ddc898,627452fe250d2eb8778f87f9a7e6bdd7cdc0d07c,1aeb80e5242461830f1d4075f0fb59bcb6ddc898,1aeb80e5242461830f1d4075f0fb59bcb6ddc898..816679150b3510bf928683750d09ec97dc6c3194
@@@@@@@@@@@@@ -215,7 -226,7 -214,8 -214,7 -214,7 -214,7 -214,7 -214,7 -214,7 -214,7 -214,7 -214,7 +227,8 @@@@@@@@@@@@@ config HID_CMEDI
            
            config HID_CP2112
                tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support"
-- ---- ----    depends on USB_HID && I2C && GPIOLIB && GPIOLIB_IRQCHIP
++ ++++ ++++    depends on USB_HID && I2C && GPIOLIB
++ +++++++++    select GPIOLIB_IRQCHIP
                ---help---
                Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge.
                This is a HID device driver which registers as an i2c adapter
index 4d111f23e801c28151a58a7e6745d8332758db76,48be3ed9be4ef08c071ea8f93d8e4fd827d95ef8,4d111f23e801c28151a58a7e6745d8332758db76,4d111f23e801c28151a58a7e6745d8332758db76,4d111f23e801c28151a58a7e6745d8332758db76,4d111f23e801c28151a58a7e6745d8332758db76,4d111f23e801c28151a58a7e6745d8332758db76,a2fb562de7489f868a1c39f7f0eedcab6a9063a7,4d111f23e801c28151a58a7e6745d8332758db76,c0a844b43dcc13664193d15d2844e05e34cc76b6,4d111f23e801c28151a58a7e6745d8332758db76,4d111f23e801c28151a58a7e6745d8332758db76..fef027bc7fa3b17b6cd337c7d2460bd3245314d9
@@@@@@@@@@@@@ -21,7 -21,8 -21,7 -21,7 -21,7 -21,7 -21,7 -21,6 -21,7 -21,7 -21,7 -21,7 +21,8 @@@@@@@@@@@@@ hid-wiimote-y         := hid-wiimote-core.o hi
            hid-wiimote-$(CONFIG_DEBUG_FS)      += hid-wiimote-debug.o
            
            obj-$(CONFIG_HID_A4TECH)    += hid-a4tech.o
+ ++++++++++obj-$(CONFIG_HID_ACCUTOUCH) += hid-accutouch.o
       +    obj-$(CONFIG_HID_ALPS)              += hid-alps.o
            obj-$(CONFIG_HID_ACRUX)             += hid-axff.o
            obj-$(CONFIG_HID_APPLE)             += hid-apple.o
            obj-$(CONFIG_HID_APPLEIR)   += hid-appleir.o
index d162f0dc76e3f44e2134eafa5509137ddf0cc411,a4cb18ed7b01afe027172e5aeccfe11078833f3f,e9e87d337446918f672771551f41041755d83d22,e9e87d337446918f672771551f41041755d83d22,1a0b9105748495297699410343b754e020c58ad7,e9e87d337446918f672771551f41041755d83d22,e9e87d337446918f672771551f41041755d83d22,8ea3a26360e941614efd496a2d8435322e0ff567,e9e87d337446918f672771551f41041755d83d22,e9a9d8a424d374b4cbc407dfe6ca7d92f14248ba,e9e87d337446918f672771551f41041755d83d22,e9e87d337446918f672771551f41041755d83d22..cd6eba051b97e2de8b8489545a60935f9237d304
@@@@@@@@@@@@@ -2089,13 -2089,12 -2088,12 -2088,12 -2088,12 -2088,12 -2088,12 -2076,6 -2088,12 -2089,12 -2088,12 -2088,12 +2091,13 @@@@@@@@@@@@@ static const struct hid_device_id hid_h
                { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
                { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
                { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
       +        { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) },
       +        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) },
       +        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) },
       +        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) },
       +        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) },
       +        { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
 +++++++++++    { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_EX07S) },
                { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
                { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
                { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
index cac06b5144559c7c7dda02540992935324fb3e34,af517973ec2c8b61445f2b6ba42a99961400bcea,86c95d30ac801f2895caef97a575955289d352a4,86c95d30ac801f2895caef97a575955289d352a4,86c95d30ac801f2895caef97a575955289d352a4,86c95d30ac801f2895caef97a575955289d352a4,758e160378694ae3de514d8a1c80dccde70d1a63,3eec09a134cb66ac1b9e03f89e3c201cd1b48adb,86c95d30ac801f2895caef97a575955289d352a4,026739d5ec42deee8475029333c5c5c069168709,86c95d30ac801f2895caef97a575955289d352a4,86c95d30ac801f2895caef97a575955289d352a4..4b07a467d7a3574c5f4c84ee58e699ae43135ec3
            #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
            #define USB_DEVICE_ID_ATEN_4PORTKVMC        0x2208
            #define USB_DEVICE_ID_ATEN_CS682    0x2213
       +    #define USB_DEVICE_ID_ATEN_CS692    0x8021
 +++++++++++#define USB_DEVICE_ID_ATEN_CS1758   0x2220
            
            #define USB_VENDOR_ID_ATMEL         0x03eb
            #define USB_DEVICE_ID_ATMEL_MULTITOUCH      0x211c
            #define USB_DEVICE_ID_CORSAIR_K95RGB    0x1b11
            #define USB_DEVICE_ID_CORSAIR_M65RGB    0x1b12
            #define USB_DEVICE_ID_CORSAIR_K70RGB    0x1b13
       +    #define USB_DEVICE_ID_CORSAIR_STRAFE    0x1b15
            #define USB_DEVICE_ID_CORSAIR_K65RGB    0x1b17
 +++++++++++#define USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE  0x1b38
 +++++++++++#define USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE  0x1b39
 +++++++++++#define USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB  0x1b3e
            
            #define USB_VENDOR_ID_CREATIVELABS  0x041e
            #define USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51  0x322c
            #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064
            #define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850       0x0522
            #define USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60 0x0781
       +    #define USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3  0x3031
       +    #define USB_DEVICE_ID_UGEE_TABLET_81                0x0081
       +    #define USB_DEVICE_ID_UGEE_TABLET_45                0x0045
       +    #define USB_DEVICE_ID_YIYNOVA_TABLET                0x004d
       +    
 +++++++++++#define USB_VENDOR_ID_UGEE          0x28bd
 +++++++++++#define USB_DEVICE_ID_UGEE_TABLET_EX07S             0x0071
 ++++++ ++++
            #define USB_VENDOR_ID_UNITEC        0x227d
            #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709
            #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19 0x0a19
index ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed,ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed,ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed,ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed,042b90d451eeed2f4eafa05ed682d257289538f8,a8381494946723c476946a8dbb1af485056d801b,ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed,2e021ba8ff052eacdf1dda7bf68af24d9d628543,ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed,ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed,ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed,ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed..8daa8ce64ebba51e91e57ec801fa7e702fb2a072
@@@@@@@@@@@@@ -1053,6 -1053,6 -1053,6 -1053,6 -990,6 -1058,24 -1053,6 -983,23 -1053,6 -1053,6 -1053,6 -1053,6 +995,24 @@@@@@@@@@@@@ static int i2c_hid_probe(struct i2c_cli
                        ihid->pdata = *platform_data;
                }
            
       -        if (client->irq > 0) {
       -                ihid->irq = client->irq;
       -        } else if (ACPI_COMPANION(&client->dev)) {
       -                ihid->desc = gpiod_get(&client->dev, NULL, GPIOD_IN);
       -                if (IS_ERR(ihid->desc)) {
       -                        dev_err(&client->dev, "Failed to get GPIO interrupt\n");
       -                        return PTR_ERR(ihid->desc);
       -                }
+++++ ++++++    ihid->pdata.supply = devm_regulator_get(&client->dev, "vdd");
+++++ ++++++    if (IS_ERR(ihid->pdata.supply)) {
+++++ ++++++            ret = PTR_ERR(ihid->pdata.supply);
+++++ ++++++            if (ret != -EPROBE_DEFER)
+++++ ++++++                    dev_err(&client->dev, "Failed to get regulator: %d\n",
+++++ ++++++                            ret);
+++++ ++++++            goto err;
+++++ ++++++    }
+++++ + ++++
       -                ihid->irq = gpiod_to_irq(ihid->desc);
       -                if (ihid->irq < 0) {
       -                        gpiod_put(ihid->desc);
       -                        dev_err(&client->dev, "Failed to convert GPIO to IRQ\n");
       -                        return ihid->irq;
       -                }
+++++ ++++++    ret = regulator_enable(ihid->pdata.supply);
+++++ ++++++    if (ret < 0) {
+++++ ++++++            dev_err(&client->dev, "Failed to enable regulator: %d\n",
+++++ ++++++                    ret);
+++++ ++++++            goto err;
+++++ + ++++    }
+++++ ++++++    if (ihid->pdata.post_power_delay_ms)
+++++ ++++++            msleep(ihid->pdata.post_power_delay_ms);
+++++ + ++++
                i2c_set_clientdata(client, ihid);
            
                ihid->client = client;
                pm_runtime_put_noidle(&client->dev);
                pm_runtime_disable(&client->dev);
            
       -    err:
       -        if (ihid->desc)
       -                gpiod_put(ihid->desc);
+++++ ++++++err_regulator:
+++++ ++++++    regulator_disable(ihid->pdata.supply);
+++++ + ++++
       +    err:
                i2c_hid_free_buffers(ihid);
                kfree(ihid);
                return ret;
@@@@@@@@@@@@@ -1149,8 -1149,8 -1149,8 -1149,8 -1086,8 -1175,10 -1149,8 -1096,13 -1149,8 -1149,8 -1149,8 -1149,8 +1112,10 @@@@@@@@@@@@@ static int i2c_hid_remove(struct i2c_cl
                if (ihid->bufsize)
                        i2c_hid_free_buffers(ihid);
            
       -        if (ihid->desc)
       -                gpiod_put(ihid->desc);
+++++ ++++++    regulator_disable(ihid->pdata.supply);
+++++ + ++++
                kfree(ihid);
            
       -        acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev));
       -    
                return 0;
            }
            
@@@@@@@@@@@@@ -1212,8 -1212,8 -1212,8 -1212,8 -1149,8 -1244,14 -1212,8 -1156,8 -1212,8 -1212,8 -1212,8 -1212,8 +1181,14 @@@@@@@@@@@@@ static int i2c_hid_resume(struct devic
                struct hid_device *hid = ihid->hid;
                int wake_status;
            
----- ------    if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) {
       -                wake_status = disable_irq_wake(ihid->irq);
+++++ ++++++    if (!device_may_wakeup(&client->dev)) {
+++++ ++++++            ret = regulator_enable(ihid->pdata.supply);
+++++ ++++++            if (ret < 0)
+++++ ++++++                    hid_warn(hid, "Failed to enable supply: %d\n", ret);
+++++ ++++++            if (ihid->pdata.post_power_delay_ms)
+++++ ++++++                    msleep(ihid->pdata.post_power_delay_ms);
+++++ ++++++    } else if (ihid->irq_wake_enabled) {
       +                wake_status = disable_irq_wake(client->irq);
                        if (!wake_status)
                                ihid->irq_wake_enabled = false;
                        else
index 961bc6fdd2d908835fa9a07d169a4746fb44189d,961bc6fdd2d908835fa9a07d169a4746fb44189d,961bc6fdd2d908835fa9a07d169a4746fb44189d,961bc6fdd2d908835fa9a07d169a4746fb44189d,00e72c6ffc76b0b94e2323172b7864b24161f3df,961bc6fdd2d908835fa9a07d169a4746fb44189d,961bc6fdd2d908835fa9a07d169a4746fb44189d,ae83af649a607f67239f1a64bf45dd4b5770cc7d,961bc6fdd2d908835fa9a07d169a4746fb44189d,961bc6fdd2d908835fa9a07d169a4746fb44189d,9ef9c0837d953e731238d2d3258d6e3f2d330432,961bc6fdd2d908835fa9a07d169a4746fb44189d..83772fa7d92a6f6178cd3a4a5c0fea28350040b5
@@@@@@@@@@@@@ -1456,10 -1456,10 -1456,10 -1456,10 -1451,10 -1456,10 -1456,10 -1457,10 -1456,10 -1456,10 -1467,9 -1456,10 +1462,9 @@@@@@@@@@@@@ static int hid_post_reset(struct usb_in
                 * the size of the HID report descriptor has not changed.
                 */
                rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL);
---------- -    if (!rdesc) {
---------- -            dbg_hid("couldn't allocate rdesc memory (post_reset)\n");
       -                return 1;
       -        }
++++++++++ +    if (!rdesc)
       +                return -ENOMEM;
------- -- -    }
++++++++++ +
                status = hid_get_class_descriptor(dev,
                                        interface->desc.bInterfaceNumber,
                                        HID_DT_REPORT, rdesc, hid->dev_rsize);
index 8284781782cdd1af9041e34c3a82d5dbc4d2644f,d6847a664446529831395a962aacab7cb49ab8f5,d6847a664446529831395a962aacab7cb49ab8f5,d6847a664446529831395a962aacab7cb49ab8f5,ec4fdba39722e39895c157579f713cb0b1af15f1,d6847a664446529831395a962aacab7cb49ab8f5,f27921efe8fc9c703c1a27b1cbcf149fa7874022,b4b8c6abb03e130e5ee54d473fce11070d51eb81,d6847a664446529831395a962aacab7cb49ab8f5,d6847a664446529831395a962aacab7cb49ab8f5,9287ab03e1176d66dac5e5306c763497f69440e4,d6847a664446529831395a962aacab7cb49ab8f5..6316498b78128574ff63b0047772f009e6d0cfeb
@@@@@@@@@@@@@ -64,8 -64,7 -64,7 -64,7 -64,7 -64,7 -64,7 -62,6 -64,7 -64,7 -64,7 -64,7 +64,8 @@@@@@@@@@@@@ static const struct hid_blacklist 
                { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
                { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
                { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET },
       +        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692, HID_QUIRK_NOGET },
 +++++++++++    { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS1758, HID_QUIRK_NOGET },
                { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET },
                { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET },
                { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET },
                { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
                { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB, HID_QUIRK_NO_INIT_REPORTS },
                { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB, HID_QUIRK_NO_INIT_REPORTS },
       +        { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
 +++++++++++    { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
 +++++++++++    { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
 +++++++++++    { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
                { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
                { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
                { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
index e2666ef84dc1ca479646fd1211f45341704755a8,be8f7e2a026f428f51200e395792dd715a612eeb,be8f7e2a026f428f51200e395792dd715a612eeb,be8f7e2a026f428f51200e395792dd715a612eeb,be8f7e2a026f428f51200e395792dd715a612eeb,be8f7e2a026f428f51200e395792dd715a612eeb,be8f7e2a026f428f51200e395792dd715a612eeb,499cc8213cfe1627b95364f7143bd6f98e064eee,be8f7e2a026f428f51200e395792dd715a612eeb,be8f7e2a026f428f51200e395792dd715a612eeb,be8f7e2a026f428f51200e395792dd715a612eeb,037b9c04745a1a0474113176a7599c1dcb5055d0..0022c0dac88a20c79e4d080cbbdd35850ab36712
@@@@@@@@@@@@@ -325,15 -325,15 -325,15 -325,15 -325,15 -325,15 -325,15 -277,9 -325,15 -325,15 -325,15 -325,22 +325,22 @@@@@@@@@@@@@ static void wacom_post_parse_hid(struc
            
                if (features->type == HID_GENERIC) {
                        /* Any last-minute generic device setup */
+++++++++++             if (wacom_wac->has_mode_change) {
+++++++++++                     if (wacom_wac->is_direct_mode)
+++++++++++                             features->device_type |= WACOM_DEVICETYPE_DIRECT;
+++++++++++                     else
+++++++++++                             features->device_type &= ~WACOM_DEVICETYPE_DIRECT;
+++++++++++             }
+++++++++++ 
                        if (features->touch_max > 1) {
       -                        input_mt_init_slots(wacom_wac->touch_input, wacom_wac->features.touch_max,
       -                                    INPUT_MT_DIRECT);
       +                        if (features->device_type & WACOM_DEVICETYPE_DIRECT)
       +                                input_mt_init_slots(wacom_wac->touch_input,
       +                                                    wacom_wac->features.touch_max,
       +                                                    INPUT_MT_DIRECT);
       +                        else
       +                                input_mt_init_slots(wacom_wac->touch_input,
       +                                                    wacom_wac->features.touch_max,
       +                                                    INPUT_MT_POINTER);
                        }
                }
            }
@@@@@@@@@@@@@ -2070,40 -2070,40 -2070,40 -2070,40 -2070,40 -2070,40 -2070,40 -1615,6 -2070,40 -2070,40 -2070,40 -2077,42 +2077,42 @@@@@@@@@@@@@ static void wacom_update_name(struct wa
                        "%s%s Pad", name, suffix);
            }
            
------- ---     if (wacom_wac->has_mute_touch_switch)
       +    static void wacom_release_resources(struct wacom *wacom)
       +    {
       +        struct hid_device *hdev = wacom->hdev;
       +    
       +        if (!wacom->resources)
       +                return;
       +    
       +        devres_release_group(&hdev->dev, wacom);
       +    
       +        wacom->resources = false;
       +    
       +        wacom->wacom_wac.pen_input = NULL;
       +        wacom->wacom_wac.touch_input = NULL;
       +        wacom->wacom_wac.pad_input = NULL;
       +    }
       +    
       +    static void wacom_set_shared_values(struct wacom_wac *wacom_wac)
       +    {
       +        if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
       +                wacom_wac->shared->type = wacom_wac->features.type;
       +                wacom_wac->shared->touch_input = wacom_wac->touch_input;
       +        }
       +    
+++++++++++     if (wacom_wac->has_mute_touch_switch) {
       +                wacom_wac->shared->has_mute_touch_switch = true;
+++++++++++             wacom_wac->shared->is_touch_on = true;
+++++++++++     }
       +    
       +        if (wacom_wac->shared->has_mute_touch_switch &&
       +            wacom_wac->shared->touch_input) {
       +                set_bit(EV_SW, wacom_wac->shared->touch_input->evbit);
       +                input_set_capability(wacom_wac->shared->touch_input, EV_SW,
       +                                     SW_MUTE_DEVICE);
       +        }
       +    }
       +    
            static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
            {
                struct wacom_wac *wacom_wac = &wacom->wacom_wac;
            
                wacom_update_name(wacom, wireless ? " (WL)" : "");
            
 +++++++++++    /* pen only Bamboo neither support touch nor pad */
 +++++++++++    if ((features->type == BAMBOO_PEN) &&
 +++++++++++        ((features->device_type & WACOM_DEVICETYPE_TOUCH) ||
 +++++++++++        (features->device_type & WACOM_DEVICETYPE_PAD))) {
 +++++++++++            error = -ENODEV;
 +++++++++++            goto fail;
 +++++++++++    }
 +++++++++++
                error = wacom_add_shared_data(hdev);
                if (error)
       -                goto fail_shared_data;
       +                goto fail;
            
                if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) &&
                     (features->quirks & WACOM_QUIRK_BATTERY)) {
                /* touch only Bamboo doesn't support pen */
                if ((features->type == BAMBOO_TOUCH) &&
                    (features->device_type & WACOM_DEVICETYPE_PEN)) {
 ------ ----            error = -ENODEV;
 ------ ----            goto fail_quirks;
 ------ ----    }
 ------ ----
 ------ ----    /* pen only Bamboo neither support touch nor pad */
 ------ ----    if ((features->type == BAMBOO_PEN) &&
 ------ ----        ((features->device_type & WACOM_DEVICETYPE_TOUCH) ||
 ------ ----        (features->device_type & WACOM_DEVICETYPE_PAD))) {
 +++++++++++            cancel_delayed_work_sync(&wacom->init_work);
 +++++++++++            _wacom_query_tablet_data(wacom);
                        error = -ENODEV;
       -                goto fail_hw_start;
       -        }
       -    
       -        /* pen only Bamboo neither support touch nor pad */
       -        if ((features->type == BAMBOO_PEN) &&
       -            ((features->device_type & WACOM_DEVICETYPE_TOUCH) ||
       -            (features->device_type & WACOM_DEVICETYPE_PAD))) {
       -                error = -ENODEV;
       -                goto fail_hw_start;
       +                goto fail_quirks;
                }
            
                if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
@@@@@@@@@@@@@ -2319,177 -2317,177 -2317,177 -2317,177 -2317,177 -2317,177 -2317,177 -1822,11 -2317,177 -2317,177 -2317,177 -2326,217 +2328,217 @@@@@@@@@@@@@ static void wacom_wireless_work(struct 
                return;
            
            fail:
       -        wacom_clean_inputs(wacom1);
       -        wacom_clean_inputs(wacom2);
       +        wacom_release_resources(wacom1);
       +        wacom_release_resources(wacom2);
       +        return;
       +    }
       +    
       +    static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index)
       +    {
       +        struct wacom_remote *remote = wacom->remote;
       +        u32 serial = remote->remotes[index].serial;
       +        int i;
       +        unsigned long flags;
       +    
       +        spin_lock_irqsave(&remote->remote_lock, flags);
       +        remote->remotes[index].registered = false;
       +        spin_unlock_irqrestore(&remote->remote_lock, flags);
       +    
       +        if (remote->remotes[index].battery.battery)
       +                devres_release_group(&wacom->hdev->dev,
       +                                     &remote->remotes[index].battery.bat_desc);
       +    
       +        if (remote->remotes[index].group.name)
       +                devres_release_group(&wacom->hdev->dev,
       +                                     &remote->remotes[index]);
       +    
       +        for (i = 0; i < WACOM_MAX_REMOTES; i++) {
       +                if (remote->remotes[i].serial == serial) {
       +                        remote->remotes[i].serial = 0;
       +                        remote->remotes[i].group.name = NULL;
       +                        remote->remotes[i].registered = false;
       +                        remote->remotes[i].battery.battery = NULL;
       +                        wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN;
       +                }
       +        }
       +    }
       +    
       +    static int wacom_remote_create_one(struct wacom *wacom, u32 serial,
       +                                   unsigned int index)
       +    {
       +        struct wacom_remote *remote = wacom->remote;
       +        struct device *dev = &wacom->hdev->dev;
       +        int error, k;
       +    
       +        /* 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 (remote->remotes[k].serial == serial)
       +                        break;
       +        }
       +    
       +        if (k < WACOM_MAX_REMOTES) {
       +                remote->remotes[index].serial = serial;
       +                return 0;
       +        }
       +    
       +        if (!devres_open_group(dev, &remote->remotes[index], GFP_KERNEL))
       +                return -ENOMEM;
       +    
       +        error = wacom_remote_create_attr_group(wacom, serial, index);
       +        if (error)
       +                goto fail;
       +    
       +        remote->remotes[index].input = wacom_allocate_input(wacom);
       +        if (!remote->remotes[index].input) {
       +                error = -ENOMEM;
       +                goto fail;
       +        }
       +        remote->remotes[index].input->uniq = remote->remotes[index].group.name;
       +        remote->remotes[index].input->name = wacom->wacom_wac.pad_name;
       +    
       +        if (!remote->remotes[index].input->name) {
       +                error = -EINVAL;
       +                goto fail;
       +        }
       +    
       +        error = wacom_setup_pad_input_capabilities(remote->remotes[index].input,
       +                                                   &wacom->wacom_wac);
       +        if (error)
       +                goto fail;
       +    
       +        remote->remotes[index].serial = serial;
       +    
       +        error = input_register_device(remote->remotes[index].input);
       +        if (error)
       +                goto fail;
       +    
       +        error = wacom_led_groups_alloc_and_register_one(
       +                                        &remote->remotes[index].input->dev,
       +                                        wacom, index, 3, true);
       +        if (error)
       +                goto fail;
       +    
       +        remote->remotes[index].registered = true;
       +    
       +        devres_close_group(dev, &remote->remotes[index]);
       +        return 0;
       +    
       +    fail:
       +        devres_release_group(dev, &remote->remotes[index]);
       +        remote->remotes[index].serial = 0;
       +        return error;
       +    }
       +    
       +    static int wacom_remote_attach_battery(struct wacom *wacom, int index)
       +    {
       +        struct wacom_remote *remote = wacom->remote;
       +        int error;
       +    
       +        if (!remote->remotes[index].registered)
       +                return 0;
       +    
       +        if (remote->remotes[index].battery.battery)
       +                return 0;
       +    
       +        if (wacom->led.groups[index].select == WACOM_STATUS_UNKNOWN)
       +                return 0;
       +    
       +        error = __wacom_initialize_battery(wacom,
       +                                        &wacom->remote->remotes[index].battery);
       +        if (error)
       +                return error;
       +    
       +        return 0;
       +    }
       +    
       +    static void wacom_remote_work(struct work_struct *work)
       +    {
       +        struct wacom *wacom = container_of(work, struct wacom, remote_work);
       +        struct wacom_remote *remote = wacom->remote;
       +        struct wacom_remote_data data;
       +        unsigned long flags;
       +        unsigned int count;
       +        u32 serial;
       +        int i;
       +    
       +        spin_lock_irqsave(&remote->remote_lock, flags);
       +    
       +        count = kfifo_out(&remote->remote_fifo, &data, sizeof(data));
       +    
       +        if (count != sizeof(data)) {
       +                hid_err(wacom->hdev,
       +                        "workitem triggered without status available\n");
       +                spin_unlock_irqrestore(&remote->remote_lock, flags);
       +                return;
       +        }
       +    
       +        if (!kfifo_is_empty(&remote->remote_fifo))
       +                wacom_schedule_work(&wacom->wacom_wac, WACOM_WORKER_REMOTE);
       +    
       +        spin_unlock_irqrestore(&remote->remote_lock, flags);
       +    
       +        for (i = 0; i < WACOM_MAX_REMOTES; i++) {
       +                serial = data.remote[i].serial;
       +                if (data.remote[i].connected) {
       +    
       +                        if (remote->remotes[i].serial == serial) {
       +                                wacom_remote_attach_battery(wacom, i);
       +                                continue;
       +                        }
       +    
       +                        if (remote->remotes[i].serial)
       +                                wacom_remote_destroy_one(wacom, i);
       +    
       +                        wacom_remote_create_one(wacom, serial, i);
       +    
       +                } else if (remote->remotes[i].serial) {
       +                        wacom_remote_destroy_one(wacom, i);
       +                }
       +        }
       +    }
       +    
+++++++++++ static void wacom_mode_change_work(struct work_struct *work)
+++++++++++ {
+++++++++++     struct wacom *wacom = container_of(work, struct wacom, mode_change_work);
+++++++++++     struct wacom_shared *shared = wacom->wacom_wac.shared;
+++++++++++     struct wacom *wacom1 = NULL;
+++++++++++     struct wacom *wacom2 = NULL;
+++++++++++     bool is_direct = wacom->wacom_wac.is_direct_mode;
+++++++++++     int error = 0;
+++++++++++ 
+++++++++++     if (shared->pen) {
+++++++++++             wacom1 = hid_get_drvdata(shared->pen);
+++++++++++             wacom_release_resources(wacom1);
+++++++++++             hid_hw_stop(wacom1->hdev);
+++++++++++             wacom1->wacom_wac.has_mode_change = true;
+++++++++++             wacom1->wacom_wac.is_direct_mode = is_direct;
+++++++++++     }
+++++++++++ 
+++++++++++     if (shared->touch) {
+++++++++++             wacom2 = hid_get_drvdata(shared->touch);
+++++++++++             wacom_release_resources(wacom2);
+++++++++++             hid_hw_stop(wacom2->hdev);
+++++++++++             wacom2->wacom_wac.has_mode_change = true;
+++++++++++             wacom2->wacom_wac.is_direct_mode = is_direct;
+++++++++++     }
+++++++++++ 
+++++++++++     if (wacom1) {
+++++++++++             error = wacom_parse_and_register(wacom1, false);
+++++++++++             if (error)
+++++++++++                     return;
+++++++++++     }
+++++++++++ 
+++++++++++     if (wacom2) {
+++++++++++             error = wacom_parse_and_register(wacom2, false);
+++++++++++             if (error)
+++++++++++                     return;
+++++++++++     }
+++++++++++ 
+++++++ +++     return;
+++++++ +++ }
+++++++ +++ 
            static int wacom_probe(struct hid_device *hdev,
                        const struct hid_device_id *id)
            {
                wacom->usbdev = dev;
                wacom->intf = intf;
                mutex_init(&wacom->lock);
       -        INIT_WORK(&wacom->work, wacom_wireless_work);
       +        INIT_DELAYED_WORK(&wacom->init_work, wacom_init_work);
       +        INIT_WORK(&wacom->wireless_work, wacom_wireless_work);
       +        INIT_WORK(&wacom->battery_work, wacom_battery_work);
       +        INIT_WORK(&wacom->remote_work, wacom_remote_work);
+++++++++++     INIT_WORK(&wacom->mode_change_work, wacom_mode_change_work);
            
                /* ask for the report descriptor to be loaded by HID */
                error = hid_parse(hdev);
@@@@@@@@@@@@@ -2572,20 -2570,18 -2570,18 -2570,18 -2570,18 -2570,18 -2570,18 -1908,15 -2570,18 -2570,18 -2570,18 -2620,19 +2622,21 @@@@@@@@@@@@@ static void wacom_remove(struct hid_dev
            
                hid_hw_stop(hdev);
            
       -        cancel_work_sync(&wacom->work);
       -        wacom_clean_inputs(wacom);
       +        cancel_delayed_work_sync(&wacom->init_work);
       +        cancel_work_sync(&wacom->wireless_work);
       +        cancel_work_sync(&wacom->battery_work);
       +        cancel_work_sync(&wacom->remote_work);
+++++++++++     cancel_work_sync(&wacom->mode_change_work);
                if (hdev->bus == BUS_BLUETOOTH)
                        device_remove_file(&hdev->dev, &dev_attr_speed);
       -        wacom_destroy_battery(wacom);
       -        wacom_remove_shared_data(wacom);
       +    
       +        /* make sure we don't trigger the LEDs */
       +        wacom_led_groups_release(wacom);
 ------ ----    wacom_release_resources(wacom);
 +++++++++++
 +++++++++++    if (wacom->wacom_wac.features.type != REMOTE)
 +++++++++++            wacom_release_resources(wacom);
            
                hid_set_drvdata(hdev, NULL);
       -        kfree(wacom);
            }
            
            #ifdef CONFIG_PM
index c68ac65db7ffec361169c326ede5bbf263a00b1b,4aa3de9f1163b30eb64b4304f285a4167aef0cf0,4aa3de9f1163b30eb64b4304f285a4167aef0cf0,4aa3de9f1163b30eb64b4304f285a4167aef0cf0,4aa3de9f1163b30eb64b4304f285a4167aef0cf0,4aa3de9f1163b30eb64b4304f285a4167aef0cf0,4aa3de9f1163b30eb64b4304f285a4167aef0cf0,1eae13cdc5020b5ec5dbcfe05f452f5528e8b958,4aa3de9f1163b30eb64b4304f285a4167aef0cf0,4aa3de9f1163b30eb64b4304f285a4167aef0cf0,4aa3de9f1163b30eb64b4304f285a4167aef0cf0,6b8f6b81619595f62449ed6157cc878cb29d9d6a..4b225fb19a16842f635026d1b1023d5d1cf5068e
@@@@@@@@@@@@@ -773,139 -773,139 -773,139 -773,139 -773,139 -773,139 -773,139 -748,128 -773,139 -773,139 -773,139 -773,14 +773,14 @@@@@@@@@@@@@ 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;
------- ---     struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
------- ---     struct wacom_remote *remote = wacom->remote;
------- ---     int bat_charging, bat_percent, touch_ring_mode;
------- ---     __u32 serial;
------- ---     int i, index = -1;
------- ---     unsigned long flags;
------- --- 
------- ---     if (data[0] != WACOM_REPORT_REMOTE) {
------- ---             hid_dbg(wacom->hdev, "%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;
------- --- 
------- ---     spin_lock_irqsave(&remote->remote_lock, flags);
------- --- 
------- ---     for (i = 0; i < WACOM_MAX_REMOTES; i++) {
------- ---             if (remote->remotes[i].serial == serial) {
------- ---                     index = i;
------- ---                     break;
------- ---             }
------- ---     }
------- --- 
------- ---     if (index < 0 || !remote->remotes[index].registered)
------- ---             goto out;
------- --- 
------- ---     input = remote->remotes[index].input;
------- --- 
------- ---     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);
------- --- 
------- ---     input_sync(input);
------- --- 
------- ---     /*Which mode select (LED light) is currently on?*/
------- ---     touch_ring_mode = (data[11] & 0xC0) >> 6;
------- --- 
------- ---     for (i = 0; i < WACOM_MAX_REMOTES; i++) {
------- ---             if (remote->remotes[i].serial == serial)
------- ---                     wacom->led.groups[i].select = touch_ring_mode;
------- ---     }
------- --- 
------- ---     __wacom_notify_battery(&remote->remotes[index].battery, bat_percent,
------- ---                             bat_charging, 1, bat_charging);
------- --- 
------- --- out:
------- ---     spin_unlock_irqrestore(&remote->remote_lock, flags);
------- ---     return 0;
------- --- }
------- --- 
------- --- static void 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;
------- ---     struct wacom_remote *remote = wacom->remote;
------- ---     struct wacom_remote_data remote_data;
------- ---     unsigned long flags;
------- ---     int i, ret;
------- --- 
------- ---     if (data[0] != WACOM_REPORT_DEVICE_LIST)
------- ---             return;
------- --- 
------- ---     memset(&remote_data, 0, sizeof(struct wacom_remote_data));
------- --- 
------- ---     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];
------- --- 
------- ---             remote_data.remote[i].serial = serial;
------- ---             remote_data.remote[i].connected = connected;
------- ---     }
------- --- 
------- ---     spin_lock_irqsave(&remote->remote_lock, flags);
------- --- 
------- ---     ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data));
------- ---     if (ret != sizeof(remote_data)) {
------- ---             spin_unlock_irqrestore(&remote->remote_lock, flags);
------- ---             hid_err(wacom->hdev, "Can't queue Remote status event.\n");
------- ---             return;
------- ---     }
------- --- 
------- ---     spin_unlock_irqrestore(&remote->remote_lock, flags);
------- --- 
------- ---     wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE);
------- --- }
------- --- 
       +    static inline bool report_touch_events(struct wacom_wac *wacom)
            {
       -        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;
       +        return (touch_arbitration ? !wacom->shared->stylus_in_proximity : 1);
            }
            
       -    static int wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len)
       +    static inline bool delay_pen_events(struct wacom_wac *wacom)
            {
       -        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;
       +        return (wacom->shared->touch_down && touch_arbitration);
            }
            
            static int wacom_intuos_general(struct wacom_wac *wacom)
@@@@@@@@@@@@@ -1651,245 -1651,245 -1651,245 -1651,245 -1651,245 -1651,245 -1651,245 -1412,27 -1651,245 -1651,245 -1651,245 -1651,286 +1651,286 @@@@@@@@@@@@@ int wacom_equivalent_usage(int usage
            static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
                        struct hid_field *field, __u8 type, __u16 code, int fuzz)
            {
       +        struct wacom *wacom = input_get_drvdata(input);
       +        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
       +        struct wacom_features *features = &wacom_wac->features;
                int fmin = field->logical_minimum;
                int fmax = field->logical_maximum;
------- ---     if (!usage->type)
       +        unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
       +        int resolution_code = code;
       +    
       +        if (equivalent_usage == HID_DG_TWIST) {
       +                resolution_code = ABS_RZ;
       +        }
       +    
       +        if (equivalent_usage == HID_GD_X) {
       +                fmin += features->offset_left;
       +                fmax -= features->offset_right;
       +        }
       +        if (equivalent_usage == HID_GD_Y) {
       +                fmin += features->offset_top;
       +                fmax -= features->offset_bottom;
       +        }
       +    
       +        usage->type = type;
       +        usage->code = code;
       +    
       +        set_bit(type, input->evbit);
       +    
       +        switch (type) {
       +        case EV_ABS:
       +                input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
       +                input_abs_set_res(input, code,
       +                                  hidinput_calc_abs_res(field, resolution_code));
       +                break;
       +        case EV_KEY:
       +                input_set_capability(input, EV_KEY, code);
       +                break;
       +        case EV_MSC:
       +                input_set_capability(input, EV_MSC, code);
       +                break;
       +        case EV_SW:
       +                input_set_capability(input, EV_SW, code);
       +                break;
       +        }
       +    }
       +    
       +    static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
       +                struct hid_field *field, struct hid_usage *usage)
       +    {
       +        struct wacom *wacom = hid_get_drvdata(hdev);
       +        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
       +        struct wacom_features *features = &wacom_wac->features;
       +        struct input_dev *input = wacom_wac->pad_input;
       +        unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
       +    
       +        switch (equivalent_usage) {
       +        case WACOM_HID_WD_BATTERY_LEVEL:
       +        case WACOM_HID_WD_BATTERY_CHARGING:
       +                features->quirks |= WACOM_QUIRK_BATTERY;
       +                break;
       +        case WACOM_HID_WD_ACCELEROMETER_X:
       +                __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
       +                wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0);
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
       +        case WACOM_HID_WD_ACCELEROMETER_Y:
       +                __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
       +                wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 0);
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
       +        case WACOM_HID_WD_ACCELEROMETER_Z:
       +                __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
       +                wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
       +        case WACOM_HID_WD_BUTTONCENTER:
       +                wacom->generic_has_leds = true;
       +                /* fall through */
       +        case WACOM_HID_WD_BUTTONHOME:
       +        case WACOM_HID_WD_BUTTONUP:
       +        case WACOM_HID_WD_BUTTONDOWN:
       +        case WACOM_HID_WD_BUTTONLEFT:
       +        case WACOM_HID_WD_BUTTONRIGHT:
       +                wacom_map_usage(input, usage, field, EV_KEY,
       +                                wacom_numbered_button_to_key(features->numbered_buttons),
       +                                0);
       +                features->numbered_buttons++;
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
       +        case WACOM_HID_WD_TOUCHONOFF:
+++++++++++     case WACOM_HID_WD_MUTE_DEVICE:
       +                /*
       +                 * This usage, which is used to mute touch events, comes
       +                 * from the pad packet, but is reported on the touch
       +                 * interface. Because the touch interface may not have
       +                 * been created yet, we cannot call wacom_map_usage(). In
       +                 * order to process this usage when we receive it, we set
       +                 * the usage type and code directly.
       +                 */
       +                wacom_wac->has_mute_touch_switch = true;
       +                usage->type = EV_SW;
       +                usage->code = SW_MUTE_DEVICE;
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
       +        case WACOM_HID_WD_TOUCHSTRIP:
       +                wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, 0);
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
       +        case WACOM_HID_WD_TOUCHSTRIP2:
       +                wacom_map_usage(input, usage, field, EV_ABS, ABS_RY, 0);
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
       +        case WACOM_HID_WD_TOUCHRING:
       +                wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
       +        case WACOM_HID_WD_TOUCHRINGSTATUS:
       +                wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
+++++++++++     case WACOM_HID_WD_BUTTONCONFIG:
+++++++++++             wacom_map_usage(input, usage, field, EV_KEY, KEY_BUTTONCONFIG, 0);
+++++++++++             features->device_type |= WACOM_DEVICETYPE_PAD;
+++++++++++             break;
+++++++++++     case WACOM_HID_WD_ONSCREEN_KEYBOARD:
+++++++++++             wacom_map_usage(input, usage, field, EV_KEY, KEY_ONSCREEN_KEYBOARD, 0);
+++++++++++             features->device_type |= WACOM_DEVICETYPE_PAD;
+++++++++++             break;
+++++++++++     case WACOM_HID_WD_CONTROLPANEL:
+++++++++++             wacom_map_usage(input, usage, field, EV_KEY, KEY_CONTROLPANEL, 0);
+++++++++++             features->device_type |= WACOM_DEVICETYPE_PAD;
+++++++++++             break;
+++++++++++     case WACOM_HID_WD_MODE_CHANGE:
+++++++++++             /* do not overwrite previous data */
+++++++++++             if (!wacom_wac->has_mode_change) {
+++++++++++                     wacom_wac->has_mode_change = true;
+++++++++++                     wacom_wac->is_direct_mode = true;
+++++++++++             }
+++++++++++             features->device_type |= WACOM_DEVICETYPE_PAD;
+++++++++++             break;
       +        }
       +    
       +        switch (equivalent_usage & 0xfffffff0) {
       +        case WACOM_HID_WD_EXPRESSKEY00:
       +                wacom_map_usage(input, usage, field, EV_KEY,
       +                                wacom_numbered_button_to_key(features->numbered_buttons),
       +                                0);
       +                features->numbered_buttons++;
       +                features->device_type |= WACOM_DEVICETYPE_PAD;
       +                break;
       +        }
       +    }
       +    
       +    static void wacom_wac_pad_battery_event(struct hid_device *hdev, struct hid_field *field,
       +                struct hid_usage *usage, __s32 value)
       +    {
       +        struct wacom *wacom = hid_get_drvdata(hdev);
       +        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
       +        unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
       +    
       +        switch (equivalent_usage) {
       +        case WACOM_HID_WD_BATTERY_LEVEL:
       +                wacom_wac->hid_data.battery_capacity = value;
       +                wacom_wac->hid_data.bat_connected = 1;
       +                break;
       +    
       +        case WACOM_HID_WD_BATTERY_CHARGING:
       +                wacom_wac->hid_data.bat_charging = value;
       +                wacom_wac->hid_data.ps_connected = value;
       +                wacom_wac->hid_data.bat_connected = 1;
       +                break;
       +        }
       +    }
       +    
       +    static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field,
       +                struct hid_usage *usage, __s32 value)
       +    {
       +        struct wacom *wacom = hid_get_drvdata(hdev);
       +        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
       +        struct input_dev *input = wacom_wac->pad_input;
       +        struct wacom_features *features = &wacom_wac->features;
       +        unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
       +        int i;
+++++++++++     bool is_touch_on = value;
       +    
       +        /*
       +         * Avoid reporting this event and setting inrange_state if this usage
       +         * hasn't been mapped.
       +         */
------- ---                                         SW_MUTE_DEVICE, !value);
+++++++++++     if (!usage->type && equivalent_usage != WACOM_HID_WD_MODE_CHANGE)
       +                return;
       +    
       +        if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) {
       +                if (usage->hid != WACOM_HID_WD_TOUCHRING)
       +                        wacom_wac->hid_data.inrange_state |= value;
       +        }
       +    
       +        switch (equivalent_usage) {
       +        case WACOM_HID_WD_TOUCHRINGSTATUS:
       +                if (!value)
       +                        input_event(input, usage->type, usage->code, 0);
       +                break;
       +    
+++++++++++     case WACOM_HID_WD_MUTE_DEVICE:
+++++++++++             if (wacom_wac->shared->touch_input && value) {
+++++++++++                     wacom_wac->shared->is_touch_on = !wacom_wac->shared->is_touch_on;
+++++++++++                     is_touch_on = wacom_wac->shared->is_touch_on;
+++++++++++             }
+++++++++++ 
+++++++++++             /* fall through*/
       +        case WACOM_HID_WD_TOUCHONOFF:
       +                if (wacom_wac->shared->touch_input) {
       +                        input_report_switch(wacom_wac->shared->touch_input,
+++++++++++                                         SW_MUTE_DEVICE, !is_touch_on);
       +                        input_sync(wacom_wac->shared->touch_input);
       +                }
       +                break;
       +    
+++++++++++     case WACOM_HID_WD_MODE_CHANGE:
+++++++++++             if (wacom_wac->is_direct_mode != value) {
+++++++++++                     wacom_wac->is_direct_mode = value;
+++++++++++                     wacom_schedule_work(&wacom->wacom_wac, WACOM_WORKER_MODE_CHANGE);
+++++++++++             }
+++++++++++             break;
+++++++++++ 
       +        case WACOM_HID_WD_BUTTONCENTER:
       +                for (i = 0; i < wacom->led.count; i++)
       +                        wacom_update_led(wacom, features->numbered_buttons,
       +                                         value, i);
       +                 /* fall through*/
       +        default:
       +                input_event(input, usage->type, usage->code, value);
+++++++++++             if (value)
+++++++++++                     wacom_wac->hid_data.pad_input_event_flag = true;
       +                break;
       +        }
       +    }
       +    
       +    static void wacom_wac_pad_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;
       +    
       +        wacom_wac->hid_data.inrange_state = 0;
       +    }
       +    
       +    static void wacom_wac_pad_battery_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 wacom_features *features = &wacom_wac->features;
            
       -        usage->type = type;
       -        usage->code = code;
       +        if (features->quirks & WACOM_QUIRK_BATTERY) {
       +                int capacity = wacom_wac->hid_data.battery_capacity;
       +                bool charging = wacom_wac->hid_data.bat_charging;
       +                bool connected = wacom_wac->hid_data.bat_connected;
       +                bool powered = wacom_wac->hid_data.ps_connected;
            
       -        set_bit(type, input->evbit);
       +                wacom_notify_battery(wacom_wac, capacity, charging,
       +                                     connected, powered);
       +        }
       +    }
            
       -        switch (type) {
       -        case EV_ABS:
       -                input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
       -                input_abs_set_res(input, code,
       -                                  hidinput_calc_abs_res(field, code));
       -                break;
       -        case EV_KEY:
       -                input_set_capability(input, EV_KEY, code);
       -                break;
       -        case EV_MSC:
       -                input_set_capability(input, EV_MSC, code);
       -                break;
       +    static void wacom_wac_pad_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 input_dev *input = wacom_wac->pad_input;
       +        bool active = wacom_wac->hid_data.inrange_state != 0;
       +    
       +        /* report prox for expresskey events */
------- ---     if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) {
+++++++++++     if ((wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) &&
+++++++++++         wacom_wac->hid_data.pad_input_event_flag) {
       +                input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
       +                input_sync(input);
+++++++++++             if (!active)
+++++++++++                     wacom_wac->hid_data.pad_input_event_flag = false;
                }
       +    
            }
            
            static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
                case HID_DG_TOOLSERIALNUMBER:
                        wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
                        break;
 ------ ----            input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
 ------ ----            input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
       +        case WACOM_HID_WD_SENSE:
       +                features->quirks |= WACOM_QUIRK_SENSE;
       +                wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
       +                break;
       +        case WACOM_HID_WD_SERIALHI:
       +                wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0);
       +                set_bit(EV_KEY, input->evbit);
       +                input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
       +                input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
       +                input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH);
       +                input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL);
       +                input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH);
 +++++++++++            if (!(features->device_type & WACOM_DEVICETYPE_DIRECT)) {
 +++++++++++                    input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
 +++++++++++                    input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
 +++++++++++            }
       +                break;
       +        case WACOM_HID_WD_FINGERWHEEL:
       +                wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
       +                break;
                }
            }
            
@@@@@@@@@@@@@ -2003,77 -2001,77 -2001,77 -2001,77 -2001,77 -2001,77 -2001,77 -1493,16 -2001,77 -2001,77 -2001,77 -2042,77 +2044,77 @@@@@@@@@@@@@ static void wacom_wac_pen_event(struct 
                case HID_DG_ERASER:
                case HID_DG_TIPSWITCH:
                        wacom_wac->hid_data.tipswitch |= value;
       -                return 0;
       +                return;
       +        case HID_DG_TOOLSERIALNUMBER:
       +                wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
 ------ ----            wacom_wac->serial[0] |= value;
 +++++++++++            wacom_wac->serial[0] |= (__u32)value;
       +                return;
       +        case WACOM_HID_WD_SENSE:
       +                wacom_wac->hid_data.sense_state = value;
       +                return;
       +        case WACOM_HID_WD_SERIALHI:
       +                wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
       +                wacom_wac->serial[0] |= ((__u64)value) << 32;
       +                /*
       +                 * Non-USI EMR devices may contain additional tool type
       +                 * information here. See WACOM_HID_WD_TOOLTYPE case for
       +                 * more details.
       +                 */
       +                if (value >> 20 == 1) {
       +                        wacom_wac->id[0] |= value & 0xFFFFF;
       +                }
       +                return;
       +        case WACOM_HID_WD_TOOLTYPE:
       +                /*
       +                 * Some devices (MobileStudio Pro, and possibly later
       +                 * devices as well) do not return the complete tool
       +                 * type in their WACOM_HID_WD_TOOLTYPE usage. Use a
       +                 * bitwise OR so the complete value can be built
       +                 * up over time :(
       +                 */
       +                wacom_wac->id[0] |= value;
       +                return;
       +        case WACOM_HID_WD_OFFSETLEFT:
       +                if (features->offset_left && value != features->offset_left)
       +                        hid_warn(hdev, "%s: overriding exising left offset "
       +                                 "%d -> %d\n", __func__, value,
       +                                 features->offset_left);
       +                features->offset_left = value;
       +                return;
       +        case WACOM_HID_WD_OFFSETRIGHT:
       +                if (features->offset_right && value != features->offset_right)
       +                        hid_warn(hdev, "%s: overriding exising right offset "
       +                                 "%d -> %d\n", __func__, value,
       +                                 features->offset_right);
       +                features->offset_right = value;
       +                return;
       +        case WACOM_HID_WD_OFFSETTOP:
       +                if (features->offset_top && value != features->offset_top)
       +                        hid_warn(hdev, "%s: overriding exising top offset "
       +                                 "%d -> %d\n", __func__, value,
       +                                 features->offset_top);
       +                features->offset_top = value;
       +                return;
       +        case WACOM_HID_WD_OFFSETBOTTOM:
       +                if (features->offset_bottom && value != features->offset_bottom)
       +                        hid_warn(hdev, "%s: overriding exising bottom offset "
       +                                 "%d -> %d\n", __func__, value,
       +                                 features->offset_bottom);
       +                features->offset_bottom = value;
       +                return;
                }
            
       -        /* send pen events only when touch is up or forced out */
       -        if (!usage->type || wacom_wac->shared->touch_down)
       -                return 0;
       +        /* send pen events only when touch is up or forced out
       +         * or touch arbitration is off
       +         */
       +        if (!usage->type || delay_pen_events(wacom_wac))
       +                return;
            
       -        input_event(input, usage->type, usage->code, value);
       +        /* send pen events only when the pen is in/entering/leaving proximity */
       +        if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0])
       +                return;
            
       -        return 0;
       +        input_event(input, usage->type, usage->code, value);
            }
            
            static void wacom_wac_pen_pre_report(struct hid_device *hdev,
@@@@@@@@@@@@@ -2195,8 -2183,8 -2183,8 -2183,8 -2183,8 -2183,8 -2183,8 -1599,8 -2183,8 -2183,8 -2183,8 -2224,15 +2236,15 @@@@@@@@@@@@@ static void wacom_wac_finger_slot(struc
                struct hid_data *hid_data = &wacom_wac->hid_data;
                bool mt = wacom_wac->features.touch_max > 1;
                bool prox = hid_data->tipswitch &&
       -                    !wacom_wac->shared->stylus_in_proximity;
       +                    report_touch_events(wacom_wac);
       +    
+++++++++++     if (wacom_wac->shared->has_mute_touch_switch &&
+++++++++++         !wacom_wac->shared->is_touch_on) {
+++++++++++             if (!wacom_wac->shared->touch_down)
+++++++++++                     return;
+++++++++++             prox = 0;
+++++++++++     }
+++++++ +++ 
                wacom_wac->hid_data.num_received++;
                if (wacom_wac->hid_data.num_received > wacom_wac->hid_data.num_expected)
                        return;
@@@@@@@@@@@@@ -4203,19 -4191,19 -4191,19 -4191,19 -4191,19 -4191,19 -4191,19 -3398,12 -4191,19 -4191,19 -4191,19 -4239,19 +4251,19 @@@@@@@@@@@@@ static const struct wacom_features waco
                  INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
                  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
            static const struct wacom_features wacom_features_0x343 =
       -        { "Wacom DTK1651", 34616, 19559, 1023, 0,
       +        { "Wacom DTK1651", 34816, 19759, 1023, 0,
                  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
       +          WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
                  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 ------ ----      INTUOSP2_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 9, .touch_max = 10 };
       +    static const struct wacom_features wacom_features_0x360 =
       +        { "Wacom Intuos Pro M", 44800, 29600, 8191, 63,
 ------ ----      INTUOSP2_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 9, .touch_max = 10 };
 +++++++++++      INTUOSP2_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 10 };
       +    static const struct wacom_features wacom_features_0x361 =
       +        { "Wacom Intuos Pro L", 62200, 43200, 8191, 63,
 +++++++++++      INTUOSP2_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 10 };
            
            static const struct wacom_features wacom_features_HID_ANY_ID =
       -        { "Wacom HID", .type = HID_GENERIC };
       +        { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
            
            #define USB_DEVICE_WACOM(prod)                                              \
                HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
Simple merge