From: Jiri Kosina Date: Tue, 2 May 2017 09:01:10 +0000 (+0200) Subject: Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112... X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=18fc2163b8a410d4d36b8f44658580731c0afaa1;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112', 'for-4.12/hid-core-null-state-handling', 'for-4.12/hiddev', 'for-4.12/i2c-hid', 'for-4.12/innomedia', 'for-4.12/logitech-hidpp-battery-power-supply', 'for-4.12/multitouch', 'for-4.12/nti', 'for-4.12/upstream' and 'for-4.12/wacom' into for-linus --- 18fc2163b8a410d4d36b8f44658580731c0afaa1 diff --cc drivers/hid/Kconfig index 8c54cb8f5d6d,fb4cc0d28eea,00e2809724bd,1aeb80e52424,1aeb80e52424,1aeb80e52424,1aeb80e52424,820bc73ac058,1aeb80e52424,627452fe250d,1aeb80e52424,1aeb80e52424..816679150b35 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@@@@@@@@@@@@ -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 diff --cc drivers/hid/Makefile index 4d111f23e801,48be3ed9be4e,4d111f23e801,4d111f23e801,4d111f23e801,4d111f23e801,4d111f23e801,a2fb562de748,4d111f23e801,c0a844b43dcc,4d111f23e801,4d111f23e801..fef027bc7fa3 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@@@@@@@@@@@@ -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 diff --cc drivers/hid/hid-core.c index d162f0dc76e3,a4cb18ed7b01,e9e87d337446,e9e87d337446,1a0b91057484,e9e87d337446,e9e87d337446,8ea3a26360e9,e9e87d337446,e9a9d8a424d3,e9e87d337446,e9e87d337446..cd6eba051b97 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@@@@@@@@@@@@ -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) }, diff --cc drivers/hid/hid-ids.h index cac06b514455,af517973ec2c,86c95d30ac80,86c95d30ac80,86c95d30ac80,86c95d30ac80,758e16037869,3eec09a134cb,86c95d30ac80,026739d5ec42,86c95d30ac80,86c95d30ac80..4b07a467d7a3 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@@@@@@@@@@@@ -183,8 -183,7 -183,7 -183,7 -183,7 -183,7 -183,7 -172,6 -183,7 -183,7 -183,7 -183,7 +183,8 @@@@@@@@@@@@@ #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 @@@@@@@@@@@@@ -277,11 -276,8 -276,8 -276,8 -276,8 -276,8 -276,8 -264,7 -276,8 -276,8 -276,8 -276,8 +277,11 @@@@@@@@@@@@@ #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 @@@@@@@@@@@@@ -1024,14 -1020,11 -1019,11 -1019,11 -1019,11 -1019,11 -1022,11 -986,7 -1019,11 -1022,11 -1019,11 -1019,11 +1031,14 @@@@@@@@@@@@@ #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 diff --cc drivers/hid/i2c-hid/i2c-hid.c index ea3c3546cef7,ea3c3546cef7,ea3c3546cef7,ea3c3546cef7,042b90d451ee,a83814949467,ea3c3546cef7,2e021ba8ff05,ea3c3546cef7,ea3c3546cef7,ea3c3546cef7,ea3c3546cef7..8daa8ce64ebb --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@@@@@@@@@@@@ -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; @@@@@@@@@@@@@ -1125,7 -1125,7 -1125,7 -1125,7 -1062,7 -1148,10 -1125,7 -1069,10 -1125,7 -1125,7 -1125,7 -1125,7 +1085,10 @@@@@@@@@@@@@ err_pm 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 diff --cc drivers/hid/usbhid/hid-core.c index 961bc6fdd2d9,961bc6fdd2d9,961bc6fdd2d9,961bc6fdd2d9,00e72c6ffc76,961bc6fdd2d9,961bc6fdd2d9,ae83af649a60,961bc6fdd2d9,961bc6fdd2d9,9ef9c0837d95,961bc6fdd2d9..83772fa7d92a --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@@@@@@@@@@@@ -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); diff --cc drivers/hid/usbhid/hid-quirks.c index 8284781782cd,d6847a664446,d6847a664446,d6847a664446,ec4fdba39722,d6847a664446,f27921efe8fc,b4b8c6abb03e,d6847a664446,d6847a664446,9287ab03e117,d6847a664446..6316498b7812 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@@@@@@@@@@@@ -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 }, @@@@@@@@@@@@@ -80,10 -79,7 -79,7 -79,7 -79,7 -79,7 -79,7 -76,6 -79,7 -79,7 -79,7 -79,7 +80,10 @@@@@@@@@@@@@ { 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 }, diff --cc drivers/hid/wacom_sys.c index e2666ef84dc1,be8f7e2a026f,be8f7e2a026f,be8f7e2a026f,be8f7e2a026f,be8f7e2a026f,be8f7e2a026f,499cc8213cfe,be8f7e2a026f,be8f7e2a026f,be8f7e2a026f,037b9c04745a..0022c0dac88a --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@@@@@@@@@@@@ -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); } + 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) +++++++++++ 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; @@@@@@@@@@@@@ -2165,17 -2165,9 -2165,9 -2165,9 -2165,9 -2165,9 -2165,9 -1671,9 -2165,9 -2165,9 -2165,9 -2174,9 +2174,17 @@@@@@@@@@@@@ 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)) { @@@@@@@@@@@@@ -2216,10 -2208,16 -2208,16 -2208,16 -2208,16 -2208,16 -2208,16 -1704,16 -2208,16 -2208,16 -2208,16 -2217,16 +2225,10 @@@@@@@@@@@@@ /* 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) { @@@@@@@@@@@@@ -2530,10 -2528,10 -2528,10 -2528,10 -2528,10 -2528,10 -2528,10 -1867,7 -2528,10 -2528,10 -2528,10 -2577,11 +2579,11 @@@@@@@@@@@@@ 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 diff --cc drivers/hid/wacom_wac.c index c68ac65db7ff,4aa3de9f1163,4aa3de9f1163,4aa3de9f1163,4aa3de9f1163,4aa3de9f1163,4aa3de9f1163,1eae13cdc502,4aa3de9f1163,4aa3de9f1163,4aa3de9f1163,6b8f6b816195..4b225fb19a16 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@@@@@@@@@@@@ -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; + 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. + */ ------- --- if (!usage->type) +++++++++++ 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, !value); +++++++++++ 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, @@@@@@@@@@@@@ -1947,26 -1947,24 -1947,24 -1947,24 -1947,24 -1947,24 -1947,24 -1472,6 -1947,24 -1947,24 -1947,24 -1988,24 +1988,26 @@@@@@@@@@@@@ case HID_DG_TOOLSERIALNUMBER: wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0); break; + 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); ------ ---- input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE); ------ ---- input_set_capability(input, EV_KEY, BTN_TOOL_LENS); +++++++++++ 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 }; + 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_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_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),\