]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge branches 'for-3.19/upstream-fixes', 'for-3.20/apple', 'for-3.20/betop', 'for...
authorJiri Kosina <jkosina@suse.cz>
Mon, 9 Feb 2015 10:17:45 +0000 (11:17 +0100)
committerJiri Kosina <jkosina@suse.cz>
Mon, 9 Feb 2015 10:17:45 +0000 (11:17 +0100)
23 files changed:
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-betopff.c [new file with mode: 0644]
drivers/hid/hid-core.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-kye.c
drivers/hid/hid-lenovo.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-rmi.c
drivers/hid/hid-roccat-pyra.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/Makefile
drivers/hid/usbhid/hid-pidff.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hid/wacom_wac.h
include/linux/hid.h
include/uapi/linux/input.h

index 230b6f887cd86e9b4d3d4bf625166c878d5524ed..152b006833cda2518614f80b4cac15b518b0ef0b 100644 (file)
@@ -27,7 +27,8 @@ if HID
 
 config HID_BATTERY_STRENGTH
        bool "Battery level reporting for HID devices"
-       depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY
+       depends on HID
+       select POWER_SUPPLY
        default n
        ---help---
        This option adds support of reporting battery strength (for HID devices
@@ -146,6 +147,16 @@ config HID_BELKIN
        ---help---
        Support for Belkin Flip KVM and Wireless keyboard.
 
+config HID_BETOP_FF
+       tristate "Betop Production Inc. force feedback support"
+       depends on USB_HID
+       select INPUT_FF_MEMLESS
+       ---help---
+       Say Y here if you want to enable force feedback support for devices by
+       BETOP Production Ltd.
+       Currently the following devices are known to be supported:
+        - BETOP 2185 PC & BFM MODE
+
 config HID_CHERRY
        tristate "Cherry Cymotion keyboard" if EXPERT
        depends on HID
@@ -388,7 +399,7 @@ config HID_LOGITECH_HIDPP
        Say Y if you want support for Logitech devices relying on the HID++
        specification. Such devices are the various Logitech Touchpads (T650,
        T651, TK820), some mice (Zone Touch mouse), or even keyboards (Solar
-       Keayboard).
+       Keyboard).
 
 config LOGITECH_FF
        bool "Logitech force feedback support"
index debd15b44b591b12ad363a1cb50b21421889114c..6f19958dfc3876f26bed994e508f1e8845b69b4f 100644 (file)
@@ -2,10 +2,7 @@
 # Makefile for the HID driver
 #
 hid-y                  := hid-core.o hid-input.o
-
-ifdef CONFIG_DEBUG_FS
-       hid-objs                += hid-debug.o
-endif
+hid-$(CONFIG_DEBUG_FS)         += hid-debug.o
 
 obj-$(CONFIG_HID)              += hid.o
 obj-$(CONFIG_UHID)             += uhid.o
@@ -15,23 +12,13 @@ obj-$(CONFIG_HID_GENERIC)   += hid-generic.o
 hid-$(CONFIG_HIDRAW)           += hidraw.o
 
 hid-logitech-y         := hid-lg.o
-ifdef CONFIG_LOGITECH_FF
-       hid-logitech-y  += hid-lgff.o
-endif
-ifdef CONFIG_LOGIRUMBLEPAD2_FF
-       hid-logitech-y  += hid-lg2ff.o
-endif
-ifdef CONFIG_LOGIG940_FF
-       hid-logitech-y  += hid-lg3ff.o
-endif
-ifdef CONFIG_LOGIWHEELS_FF
-       hid-logitech-y  += hid-lg4ff.o
-endif
+hid-logitech-$(CONFIG_LOGITECH_FF)     += hid-lgff.o
+hid-logitech-$(CONFIG_LOGIRUMBLEPAD2_FF)       += hid-lg2ff.o
+hid-logitech-$(CONFIG_LOGIG940_FF)     += hid-lg3ff.o
+hid-logitech-$(CONFIG_LOGIWHEELS_FF)   += hid-lg4ff.o
 
 hid-wiimote-y          := hid-wiimote-core.o hid-wiimote-modules.o
-ifdef CONFIG_DEBUG_FS
-       hid-wiimote-y   += hid-wiimote-debug.o
-endif
+hid-wiimote-$(CONFIG_DEBUG_FS) += hid-wiimote-debug.o
 
 obj-$(CONFIG_HID_A4TECH)       += hid-a4tech.o
 obj-$(CONFIG_HID_ACRUX)                += hid-axff.o
@@ -39,6 +26,7 @@ obj-$(CONFIG_HID_APPLE)               += hid-apple.o
 obj-$(CONFIG_HID_APPLEIR)      += hid-appleir.o
 obj-$(CONFIG_HID_AUREAL)        += hid-aureal.o
 obj-$(CONFIG_HID_BELKIN)       += hid-belkin.o
+obj-$(CONFIG_HID_BETOP_FF)     += hid-betopff.o
 obj-$(CONFIG_HID_CHERRY)       += hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)      += hid-chicony.o
 obj-$(CONFIG_HID_CP2112)       += hid-cp2112.o
@@ -76,24 +64,12 @@ obj-$(CONFIG_HID_PENMOUNT)  += hid-penmount.o
 obj-$(CONFIG_HID_PETALYNX)     += hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)      += hid-picolcd.o
 hid-picolcd-y                  += hid-picolcd_core.o
-ifdef CONFIG_HID_PICOLCD_FB
-hid-picolcd-y                  += hid-picolcd_fb.o
-endif
-ifdef CONFIG_HID_PICOLCD_BACKLIGHT
-hid-picolcd-y                  += hid-picolcd_backlight.o
-endif
-ifdef CONFIG_HID_PICOLCD_LCD
-hid-picolcd-y                  += hid-picolcd_lcd.o
-endif
-ifdef CONFIG_HID_PICOLCD_LEDS
-hid-picolcd-y                  += hid-picolcd_leds.o
-endif
-ifdef CONFIG_HID_PICOLCD_CIR
-hid-picolcd-y                  += hid-picolcd_cir.o
-endif
-ifdef CONFIG_DEBUG_FS
-hid-picolcd-y                  += hid-picolcd_debugfs.o
-endif
+hid-picolcd-$(CONFIG_HID_PICOLCD_FB)   += hid-picolcd_fb.o
+hid-picolcd-$(CONFIG_HID_PICOLCD_BACKLIGHT)    += hid-picolcd_backlight.o
+hid-picolcd-$(CONFIG_HID_PICOLCD_LCD)  += hid-picolcd_lcd.o
+hid-picolcd-$(CONFIG_HID_PICOLCD_LEDS) += hid-picolcd_leds.o
+hid-picolcd-$(CONFIG_HID_PICOLCD_CIR)  += hid-picolcd_cir.o
+hid-picolcd-$(CONFIG_DEBUG_FS)         += hid-picolcd_debugfs.o
 
 obj-$(CONFIG_HID_PLANTRONICS)  += hid-plantronics.o
 obj-$(CONFIG_HID_PRIMAX)       += hid-primax.o
diff --git a/drivers/hid/hid-betopff.c b/drivers/hid/hid-betopff.c
new file mode 100644 (file)
index 0000000..69cfc8d
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ *  Force feedback support for Betop based devices
+ *
+ *  The devices are distributed under various names and the same USB device ID
+ *  can be used in both adapters and actual game controllers.
+ *
+ *  0x11c2:0x2208 "BTP2185 BFM mode Joystick"
+ *   - tested with BTP2185 BFM Mode.
+ *
+ *  0x11C0:0x5506 "BTP2185 PC mode Joystick"
+ *   - tested with BTP2185 PC Mode.
+ *
+ *  0x8380:0x1850 "BTP2185 V2 PC mode USB Gamepad"
+ *   - tested with BTP2185 PC Mode with another version.
+ *
+ *  0x20bc:0x5500 "BTP2185 V2 BFM mode Joystick"
+ *   - tested with BTP2171s.
+ *  Copyright (c) 2014 Huang Bo <huangbobupt@163.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/hid.h>
+
+#include "hid-ids.h"
+
+struct betopff_device {
+       struct hid_report *report;
+};
+
+static int hid_betopff_play(struct input_dev *dev, void *data,
+                        struct ff_effect *effect)
+{
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct betopff_device *betopff = data;
+       __u16 left, right;
+
+       left = effect->u.rumble.strong_magnitude;
+       right = effect->u.rumble.weak_magnitude;
+
+       betopff->report->field[2]->value[0] = left / 256;
+       betopff->report->field[3]->value[0] = right / 256;
+
+       hid_hw_request(hid, betopff->report, HID_REQ_SET_REPORT);
+
+       return 0;
+}
+
+static int betopff_init(struct hid_device *hid)
+{
+       struct betopff_device *betopff;
+       struct hid_report *report;
+       struct hid_input *hidinput =
+                       list_first_entry(&hid->inputs, struct hid_input, list);
+       struct list_head *report_list =
+                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct input_dev *dev = hidinput->input;
+       int field_count = 0;
+       int error;
+       int i, j;
+
+       if (list_empty(report_list)) {
+               hid_err(hid, "no output reports found\n");
+               return -ENODEV;
+       }
+
+       report = list_first_entry(report_list, struct hid_report, list);
+       /*
+        * Actually there are 4 fields for 4 Bytes as below:
+        * -----------------------------------------
+        * Byte0  Byte1  Byte2    Byte3
+        * 0x00   0x00   left_motor right_motor
+        * -----------------------------------------
+        * Do init them with default value.
+        */
+       for (i = 0; i < report->maxfield; i++) {
+               for (j = 0; j < report->field[i]->report_count; j++) {
+                       report->field[i]->value[j] = 0x00;
+                       field_count++;
+               }
+       }
+
+       if (field_count < 4) {
+               hid_err(hid, "not enough fields in the report: %d\n",
+                               field_count);
+               return -ENODEV;
+       }
+
+       betopff = kzalloc(sizeof(*betopff), GFP_KERNEL);
+       if (!betopff)
+               return -ENOMEM;
+
+       set_bit(FF_RUMBLE, dev->ffbit);
+
+       error = input_ff_create_memless(dev, betopff, hid_betopff_play);
+       if (error) {
+               kfree(betopff);
+               return error;
+       }
+
+       betopff->report = report;
+       hid_hw_request(hid, betopff->report, HID_REQ_SET_REPORT);
+
+       hid_info(hid, "Force feedback for betop devices by huangbo <huangbobupt@163.com>\n");
+
+       return 0;
+}
+
+static int betop_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+
+       if (id->driver_data)
+               hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               hid_err(hdev, "parse failed\n");
+               goto err;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+       if (ret) {
+               hid_err(hdev, "hw start failed\n");
+               goto err;
+       }
+
+       betopff_init(hdev);
+
+       return 0;
+err:
+       return ret;
+}
+
+static const struct hid_device_id betop_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185PC, 0x5506) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2PC, 0x1850) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2BFM, 0x5500) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, betop_devices);
+
+static struct hid_driver betop_driver = {
+       .name = "betop",
+       .id_table = betop_devices,
+       .probe = betop_probe,
+};
+module_hid_driver(betop_driver);
+
+MODULE_LICENSE("GPL");
index c3d0ac1a0988096eaacbe8063b354399b6a85e14..db4fb6e1cc5b3ca83d14d3f1e0e52e66fe75979a 100644 (file)
@@ -698,15 +698,25 @@ static void hid_scan_feature_usage(struct hid_parser *parser, u32 usage)
 static void hid_scan_collection(struct hid_parser *parser, unsigned type)
 {
        struct hid_device *hid = parser->device;
+       int i;
 
        if (((parser->global.usage_page << 16) == HID_UP_SENSOR) &&
            type == HID_COLLECTION_PHYSICAL)
                hid->group = HID_GROUP_SENSOR_HUB;
 
        if (hid->vendor == USB_VENDOR_ID_MICROSOFT &&
-           hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 &&
+           (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3_JP) &&
            hid->group == HID_GROUP_MULTITOUCH)
                hid->group = HID_GROUP_GENERIC;
+
+       if ((parser->global.usage_page << 16) == HID_UP_GENDESK)
+               for (i = 0; i < parser->local.usage_index; i++)
+                       if (parser->local.usage[i] == HID_GD_POINTER)
+                               parser->scan_flags |= HID_SCAN_FLAG_GD_POINTER;
+
+       if ((parser->global.usage_page << 16) >= HID_UP_MSVENDOR)
+               parser->scan_flags |= HID_SCAN_FLAG_VENDOR_SPECIFIC;
 }
 
 static int hid_scan_main(struct hid_parser *parser, struct hid_item *item)
@@ -792,11 +802,14 @@ static int hid_scan_report(struct hid_device *hid)
                hid->group = HID_GROUP_WACOM;
                break;
        case USB_VENDOR_ID_SYNAPTICS:
-               if ((hid->group == HID_GROUP_GENERIC) &&
-                   (hid->bus != BUS_USB || hid->type == HID_TYPE_USBMOUSE))
-                       /* hid-rmi should only bind to the mouse interface of
-                        * composite USB devices */
-                       hid->group = HID_GROUP_RMI;
+               if (hid->group == HID_GROUP_GENERIC)
+                       if ((parser->scan_flags & HID_SCAN_FLAG_VENDOR_SPECIFIC)
+                           && (parser->scan_flags & HID_SCAN_FLAG_GD_POINTER))
+                               /*
+                                * hid-rmi should take care of them,
+                                * not hid-generic
+                                */
+                               hid->group = HID_GROUP_RMI;
                break;
        }
 
@@ -1757,6 +1770,10 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185PC, 0x5506) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2PC, 0x1850) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2BFM, 0x5500) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
@@ -1805,6 +1822,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
@@ -1860,6 +1878,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
@@ -1970,6 +1989,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
        { }
 };
 
@@ -2327,6 +2347,7 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) },
index 31fad641b74417c9d6aabffbdd9f283b4fdf1f68..6039f071fab1370da4a684e801883ef23e9706d4 100644 (file)
@@ -381,7 +381,7 @@ static void mousevsc_on_channel_callback(void *context)
 static int mousevsc_connect_to_vsp(struct hv_device *device)
 {
        int ret = 0;
-       int t;
+       unsigned long t;
        struct mousevsc_dev *input_dev = hv_get_drvdata(device);
        struct mousevsc_prt_msg *request;
        struct mousevsc_prt_msg *response;
index 7460f3402298c2e1925059a1ef5cbf669e9d381b..46edb4d3ed28efc61582811ea6b5fdeac2a2808a 100644 (file)
 #define USB_VENDOR_ID_BERKSHIRE                0x0c98
 #define USB_DEVICE_ID_BERKSHIRE_PCWD   0x1140
 
+#define USB_VENDOR_ID_BETOP_2185BFM    0x11c2
+#define USB_VENDOR_ID_BETOP_2185PC     0x11c0
+#define USB_VENDOR_ID_BETOP_2185V2PC   0x8380
+#define USB_VENDOR_ID_BETOP_2185V2BFM  0x20bc
+
 #define USB_VENDOR_ID_BTC              0x046e
 #define USB_DEVICE_ID_BTC_EMPREX_REMOTE        0x5578
 #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2      0x5577
 #define USB_DEVICE_ID_KYE_GPEN_560     0x5003
 #define USB_DEVICE_ID_KYE_EASYPEN_I405X        0x5010
 #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X       0x5011
+#define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2     0x501a
 #define USB_DEVICE_ID_KYE_EASYPEN_M610X        0x5013
 
 #define USB_VENDOR_ID_LABTEC           0x1020
 #define USB_DEVICE_ID_PICKIT2          0x0033
 #define USB_DEVICE_ID_PICOLCD          0xc002
 #define USB_DEVICE_ID_PICOLCD_BOOTLOADER       0xf002
+#define USB_DEVICE_ID_PICK16F1454      0x0042
 
 #define USB_VENDOR_ID_MICROSOFT                0x045e
 #define USB_DEVICE_ID_SIDEWINDER_GV    0x003b
 #define USB_DEVICE_ID_MS_TOUCH_COVER_2   0x07a7
 #define USB_DEVICE_ID_MS_TYPE_COVER_2    0x07a9
 #define USB_DEVICE_ID_MS_TYPE_COVER_3    0x07dc
+#define USB_DEVICE_ID_MS_TYPE_COVER_3_JP 0x07dd
 
 #define USB_VENDOR_ID_MOJO             0x8282
 #define USB_DEVICE_ID_RETRO_ADAPTER    0x3201
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001                0x3001
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008                0x3008
 
+#define USB_VENDOR_ID_RAZER            0x1532
+#define USB_DEVICE_ID_RAZER_BLADE_14   0x011D
+
 #define USB_VENDOR_ID_REALTEK          0x0bda
 #define USB_DEVICE_ID_REALTEK_READER   0x0152
 
index e0a0f06ac5ef6168c8fcdd5c2462df3f3130c941..052869d0ab787da2a3d685c5c6bf905d05e047b8 100644 (file)
@@ -306,10 +306,16 @@ static enum power_supply_property hidinput_battery_props[] = {
 
 static const struct hid_device_id hid_battery_quirks[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
-                       USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
-       HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+               USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
+         HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+               USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
+         HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+               USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
+         HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
-                              USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
+                              USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
          HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
                USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
@@ -1101,6 +1107,23 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
                return;
        }
 
+       /*
+        * Ignore reports for absolute data if the data didn't change. This is
+        * not only an optimization but also fixes 'dead' key reports. Some
+        * RollOver implementations for localized keys (like BACKSLASH/PIPE; HID
+        * 0x31 and 0x32) report multiple keys, even though a localized keyboard
+        * can only have one of them physically available. The 'dead' keys
+        * report constant 0. As all map to the same keycode, they'd confuse
+        * the input layer. If we filter the 'dead' keys on the HID level, we
+        * skip the keycode translation and only forward real events.
+        */
+       if (!(field->flags & (HID_MAIN_ITEM_RELATIVE |
+                             HID_MAIN_ITEM_BUFFERED_BYTE)) &&
+                             (field->flags & HID_MAIN_ITEM_VARIABLE) &&
+           usage->usage_index < field->maxusage &&
+           value == field->value[usage->usage_index])
+               return;
+
        /* report the usage code as scancode if the key status has changed */
        if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
                input_event(input, EV_MSC, MSC_SCAN, usage->hid);
index b92bf01a1ae8122f486ea333288558f082162f5d..158fcf577fae570d331a37c46d650a151141c19c 100644 (file)
@@ -323,6 +323,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                }
                break;
        case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
+       case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2:
                if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) {
                        rdesc = mousepen_i608x_rdesc_fixed;
                        *rsize = sizeof(mousepen_i608x_rdesc_fixed);
@@ -415,6 +416,7 @@ static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
        switch (id->product) {
        case USB_DEVICE_ID_KYE_EASYPEN_I405X:
        case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
+       case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2:
        case USB_DEVICE_ID_KYE_EASYPEN_M610X:
                ret = kye_tablet_enable(hdev);
                if (ret) {
@@ -445,6 +447,8 @@ static const struct hid_device_id kye_devices[] = {
                                USB_DEVICE_ID_KYE_EASYPEN_I405X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
                                USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
+                               USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
                                USB_DEVICE_ID_KYE_EASYPEN_M610X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
index 4c55f4d95798794eed986c638c11b51d2e9d8375..c4c3f0952521f975fb914580f2fe0f086013038b 100644 (file)
@@ -38,6 +38,7 @@ struct lenovo_drvdata_tpkbd {
 
 struct lenovo_drvdata_cptkbd {
        bool fn_lock;
+       int sensitivity;
 };
 
 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
@@ -91,6 +92,38 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
                case 0x00fa: /* Fn-Esc: Fn-lock toggle */
                        map_key_clear(KEY_FN_ESC);
                        return 1;
+               case 0x00fb: /* Middle mouse button (in native mode) */
+                       map_key_clear(BTN_MIDDLE);
+                       return 1;
+               }
+       }
+
+       /* Compatibility middle/wheel mappings should be ignored */
+       if (usage->hid == HID_GD_WHEEL)
+               return -1;
+       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON &&
+                       (usage->hid & HID_USAGE) == 0x003)
+               return -1;
+       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER &&
+                       (usage->hid & HID_USAGE) == 0x238)
+               return -1;
+
+       /* Map wheel emulation reports: 0xffa1 = USB, 0xff10 = BT */
+       if ((usage->hid & HID_USAGE_PAGE) == 0xff100000 ||
+           (usage->hid & HID_USAGE_PAGE) == 0xffa10000) {
+               field->flags |= HID_MAIN_ITEM_RELATIVE | HID_MAIN_ITEM_VARIABLE;
+               field->logical_minimum = -127;
+               field->logical_maximum = 127;
+
+               switch (usage->hid & HID_USAGE) {
+               case 0x0000:
+                       hid_map_usage(hi, usage, bit, max, EV_REL, 0x06);
+                       return 1;
+               case 0x0001:
+                       hid_map_usage(hi, usage, bit, max, EV_REL, 0x08);
+                       return 1;
+               default:
+                       return -1;
                }
        }
 
@@ -145,6 +178,7 @@ static void lenovo_features_set_cptkbd(struct hid_device *hdev)
        struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
 
        ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
+       ret = lenovo_send_cmd_cptkbd(hdev, 0x02, cptkbd_data->sensitivity);
        if (ret)
                hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
 }
@@ -179,13 +213,50 @@ static ssize_t attr_fn_lock_store_cptkbd(struct device *dev,
        return count;
 }
 
+static ssize_t attr_sensitivity_show_cptkbd(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+               cptkbd_data->sensitivity);
+}
+
+static ssize_t attr_sensitivity_store_cptkbd(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
+       int value;
+
+       if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
+               return -EINVAL;
+
+       cptkbd_data->sensitivity = value;
+       lenovo_features_set_cptkbd(hdev);
+
+       return count;
+}
+
+
 static struct device_attribute dev_attr_fn_lock_cptkbd =
        __ATTR(fn_lock, S_IWUSR | S_IRUGO,
                        attr_fn_lock_show_cptkbd,
                        attr_fn_lock_store_cptkbd);
 
+static struct device_attribute dev_attr_sensitivity_cptkbd =
+       __ATTR(sensitivity, S_IWUSR | S_IRUGO,
+                       attr_sensitivity_show_cptkbd,
+                       attr_sensitivity_store_cptkbd);
+
+
 static struct attribute *lenovo_attributes_cptkbd[] = {
        &dev_attr_fn_lock_cptkbd.attr,
+       &dev_attr_sensitivity_cptkbd.attr,
        NULL
 };
 
@@ -594,8 +665,14 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
        if (ret)
                hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
 
-       /* Turn Fn-Lock on by default */
+       /* Switch middle button to native mode */
+       ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01);
+       if (ret)
+               hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
+
+       /* Set keyboard settings to known state */
        cptkbd_data->fn_lock = true;
+       cptkbd_data->sensitivity = 0x05;
        lenovo_features_set_cptkbd(hdev);
 
        ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd);
index c917ab61aafa6156b433ed3148a31384ac6d4292..5bc6d80d5be79f465f3cbbb686c471db6162eb63 100644 (file)
@@ -962,10 +962,24 @@ static int logi_dj_raw_event(struct hid_device *hdev,
 
        switch (data[0]) {
        case REPORT_ID_DJ_SHORT:
+               if (size != DJREPORT_SHORT_LENGTH) {
+                       dev_err(&hdev->dev, "DJ report of bad size (%d)", size);
+                       return false;
+               }
                return logi_dj_dj_event(hdev, report, data, size);
        case REPORT_ID_HIDPP_SHORT:
-               /* intentional fallthrough */
+               if (size != HIDPP_REPORT_SHORT_LENGTH) {
+                       dev_err(&hdev->dev,
+                               "Short HID++ report of bad size (%d)", size);
+                       return false;
+               }
+               return logi_dj_hidpp_event(hdev, report, data, size);
        case REPORT_ID_HIDPP_LONG:
+               if (size != HIDPP_REPORT_LONG_LENGTH) {
+                       dev_err(&hdev->dev,
+                               "Long HID++ report of bad size (%d)", size);
+                       return false;
+               }
                return logi_dj_hidpp_event(hdev, report, data, size);
        }
 
index acb632db3bb55a3e26893ad5fe3cebe5c1744e06..e77658cd037ca858270f8c238becbf93b7f22e8a 100644 (file)
@@ -840,18 +840,25 @@ static int wtp_raw_event(struct hid_device *hdev, u8 *data, int size)
 
        switch (data[0]) {
        case 0x02:
+               if (size < 2) {
+                       hid_err(hdev, "Received HID report of bad size (%d)",
+                               size);
+                       return 1;
+               }
                if (hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS) {
                        input_event(wd->input, EV_KEY, BTN_LEFT,
                                        !!(data[1] & 0x01));
                        input_event(wd->input, EV_KEY, BTN_RIGHT,
                                        !!(data[1] & 0x02));
                        input_sync(wd->input);
+                       return 0;
                } else {
                        if (size < 21)
                                return 1;
                        return wtp_mouse_raw_xy_event(hidpp, &data[7]);
                }
        case REPORT_ID_HIDPP_LONG:
+               /* size is already checked in hidpp_raw_event. */
                if ((report->fap.feature_index != wd->mt_feature_index) ||
                    (report->fap.funcindex_clientid != EVENT_TOUCHPAD_RAW_XY))
                        return 1;
index cacda43f6a6f0cacf3d1b2afc968de6f53b9b69e..fbaea6eb882e21afb6cba576279834a099780434 100644 (file)
@@ -276,6 +276,8 @@ static const struct hid_device_id ms_devices[] = {
                .driver_data = MS_DUPLICATE_USAGES },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
                .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP),
+               .driver_data = MS_HIDINPUT },
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
                .driver_data = MS_PRESENTER },
index b51200fe2f33444bd93649aa5205f261f76d0cf2..49d4fe4f5987e2e7074d6fa77cfd8974353c4a8a 100644 (file)
 #define RMI_READ_DATA_PENDING          BIT(1)
 #define RMI_STARTED                    BIT(2)
 
+/* device flags */
+#define RMI_DEVICE                     BIT(0)
+#define RMI_DEVICE_HAS_PHYS_BUTTONS    BIT(1)
+
 enum rmi_mode_type {
        RMI_MODE_OFF                    = 0,
        RMI_MODE_ATTN_REPORTS           = 1,
@@ -118,6 +122,8 @@ struct rmi_data {
 
        struct work_struct reset_work;
        struct hid_device *hdev;
+
+       unsigned long device_flags;
 };
 
 #define RMI_PAGE(addr) (((addr) >> 8) & 0xff)
@@ -452,9 +458,32 @@ static int rmi_raw_event(struct hid_device *hdev,
                return rmi_read_data_event(hdev, data, size);
        case RMI_ATTN_REPORT_ID:
                return rmi_input_event(hdev, data, size);
-       case RMI_MOUSE_REPORT_ID:
+       default:
+               return 1;
+       }
+
+       return 0;
+}
+
+static int rmi_event(struct hid_device *hdev, struct hid_field *field,
+                       struct hid_usage *usage, __s32 value)
+{
+       struct rmi_data *data = hid_get_drvdata(hdev);
+
+       if ((data->device_flags & RMI_DEVICE) &&
+           (field->application == HID_GD_POINTER ||
+           field->application == HID_GD_MOUSE)) {
+               if (data->device_flags & RMI_DEVICE_HAS_PHYS_BUTTONS) {
+                       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
+                               return 0;
+
+                       if ((usage->hid == HID_GD_X || usage->hid == HID_GD_Y)
+                           && !value)
+                               return 1;
+               }
+
                rmi_schedule_reset(hdev);
-               break;
+               return 1;
        }
 
        return 0;
@@ -856,6 +885,9 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
        if (ret)
                return;
 
+       if (!(data->device_flags & RMI_DEVICE))
+               return;
+
        /* Allow incoming hid reports */
        hid_device_io_start(hdev);
 
@@ -914,8 +946,38 @@ static int rmi_input_mapping(struct hid_device *hdev,
                struct hid_input *hi, struct hid_field *field,
                struct hid_usage *usage, unsigned long **bit, int *max)
 {
-       /* we want to make HID ignore the advertised HID collection */
-       return -1;
+       struct rmi_data *data = hid_get_drvdata(hdev);
+
+       /*
+        * we want to make HID ignore the advertised HID collection
+        * for RMI deivces
+        */
+       if (data->device_flags & RMI_DEVICE) {
+               if ((data->device_flags & RMI_DEVICE_HAS_PHYS_BUTTONS) &&
+                   ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON))
+                       return 0;
+
+               return -1;
+       }
+
+       return 0;
+}
+
+static int rmi_check_valid_report_id(struct hid_device *hdev, unsigned type,
+               unsigned id, struct hid_report **report)
+{
+       int i;
+
+       *report = hdev->report_enum[type].report_id_hash[id];
+       if (*report) {
+               for (i = 0; i < (*report)->maxfield; i++) {
+                       unsigned app = (*report)->field[i]->application;
+                       if ((app & HID_USAGE_PAGE) >= HID_UP_MSVENDOR)
+                               return 1;
+               }
+       }
+
+       return 0;
 }
 
 static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -925,6 +987,7 @@ static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
        size_t alloc_size;
        struct hid_report *input_report;
        struct hid_report *output_report;
+       struct hid_report *feature_report;
 
        data = devm_kzalloc(&hdev->dev, sizeof(struct rmi_data), GFP_KERNEL);
        if (!data)
@@ -943,27 +1006,37 @@ static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
                return ret;
        }
 
-       input_report = hdev->report_enum[HID_INPUT_REPORT]
-                       .report_id_hash[RMI_ATTN_REPORT_ID];
-       if (!input_report) {
-               hid_err(hdev, "device does not have expected input report\n");
-               ret = -ENODEV;
-               return ret;
+       if (id->driver_data)
+               data->device_flags = id->driver_data;
+
+       /*
+        * Check for the RMI specific report ids. If they are misisng
+        * simply return and let the events be processed by hid-input
+        */
+       if (!rmi_check_valid_report_id(hdev, HID_FEATURE_REPORT,
+           RMI_SET_RMI_MODE_REPORT_ID, &feature_report)) {
+               hid_dbg(hdev, "device does not have set mode feature report\n");
+               goto start;
        }
 
-       data->input_report_size = (input_report->size >> 3) + 1 /* report id */;
+       if (!rmi_check_valid_report_id(hdev, HID_INPUT_REPORT,
+           RMI_ATTN_REPORT_ID, &input_report)) {
+               hid_dbg(hdev, "device does not have attention input report\n");
+               goto start;
+       }
 
-       output_report = hdev->report_enum[HID_OUTPUT_REPORT]
-                       .report_id_hash[RMI_WRITE_REPORT_ID];
-       if (!output_report) {
-               hid_err(hdev, "device does not have expected output report\n");
-               ret = -ENODEV;
-               return ret;
+       data->input_report_size = hid_report_len(input_report);
+
+       if (!rmi_check_valid_report_id(hdev, HID_OUTPUT_REPORT,
+           RMI_WRITE_REPORT_ID, &output_report)) {
+               hid_dbg(hdev,
+                       "device does not have rmi write output report\n");
+               goto start;
        }
 
-       data->output_report_size = (output_report->size >> 3)
-                                       + 1 /* report id */;
+       data->output_report_size = hid_report_len(output_report);
 
+       data->device_flags |= RMI_DEVICE;
        alloc_size = data->output_report_size + data->input_report_size;
 
        data->writeReport = devm_kzalloc(&hdev->dev, alloc_size, GFP_KERNEL);
@@ -978,13 +1051,15 @@ static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        mutex_init(&data->page_mutex);
 
+start:
        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
        if (ret) {
                hid_err(hdev, "hw start failed\n");
                return ret;
        }
 
-       if (!test_bit(RMI_STARTED, &data->flags))
+       if ((data->device_flags & RMI_DEVICE) &&
+           !test_bit(RMI_STARTED, &data->flags))
                /*
                 * The device maybe in the bootloader if rmi_input_configured
                 * failed to find F11 in the PDT. Print an error, but don't
@@ -1007,6 +1082,8 @@ static void rmi_remove(struct hid_device *hdev)
 }
 
 static const struct hid_device_id rmi_id[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14),
+               .driver_data = RMI_DEVICE_HAS_PHYS_BUTTONS },
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_RMI, HID_ANY_ID, HID_ANY_ID) },
        { }
 };
@@ -1017,6 +1094,7 @@ static struct hid_driver rmi_driver = {
        .id_table               = rmi_id,
        .probe                  = rmi_probe,
        .remove                 = rmi_remove,
+       .event                  = rmi_event,
        .raw_event              = rmi_raw_event,
        .input_mapping          = rmi_input_mapping,
        .input_configured       = rmi_input_configured,
index 1a07e07d99a06c8972a2d80b8fefa8aa4f4b3848..47d7e74231e5a3245461eb5f34a3acecc5bd67d1 100644 (file)
@@ -35,6 +35,8 @@ static struct class *pyra_class;
 static void profile_activated(struct pyra_device *pyra,
                unsigned int new_profile)
 {
+       if (new_profile >= ARRAY_SIZE(pyra->profile_settings))
+               return;
        pyra->actual_profile = new_profile;
        pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi;
 }
@@ -257,9 +259,11 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
        if (off != 0 || count != PYRA_SIZE_SETTINGS)
                return -EINVAL;
 
-       mutex_lock(&pyra->pyra_lock);
-
        settings = (struct pyra_settings const *)buf;
+       if (settings->startup_profile >= ARRAY_SIZE(pyra->profile_settings))
+               return -EINVAL;
+
+       mutex_lock(&pyra->pyra_lock);
 
        retval = pyra_set_settings(usb_dev, settings);
        if (retval) {
index d32037cbf9db5e3bf9b1f4d96a3f8c98259a65a5..d43e967e75339ec7972e734e284c4356e31a4e38 100644 (file)
@@ -706,12 +706,7 @@ static int i2c_hid_start(struct hid_device *hid)
 
 static void i2c_hid_stop(struct hid_device *hid)
 {
-       struct i2c_client *client = hid->driver_data;
-       struct i2c_hid *ihid = i2c_get_clientdata(client);
-
        hid->claimed = 0;
-
-       i2c_hid_free_buffers(ihid);
 }
 
 static int i2c_hid_open(struct hid_device *hid)
index db3cf31c6fa133fb1356f1f4648291a4ea4b46a0..890f2914a8ff90a2b4c946b2d22ee8748e7855dc 100644 (file)
@@ -2,17 +2,9 @@
 # Makefile for the USB input drivers
 #
 
-# Multipart objects.
 usbhid-y       := hid-core.o hid-quirks.o
-
-# Optional parts of multipart objects.
-
-ifeq ($(CONFIG_USB_HIDDEV),y)
-       usbhid-y        += hiddev.o
-endif
-ifeq ($(CONFIG_HID_PID),y)
-       usbhid-y        += hid-pidff.o
-endif
+usbhid-$(CONFIG_USB_HIDDEV)    += hiddev.o
+usbhid-$(CONFIG_HID_PID)       += hid-pidff.o
 
 obj-$(CONFIG_USB_HID)          += usbhid.o
 obj-$(CONFIG_USB_KBD)          += usbkbd.o
index 10b6167027802abbc289466c00a74b6281e2b5f3..0b531c6a76a58871b9ea549367400c1a345cb6b8 100644 (file)
@@ -1252,6 +1252,8 @@ int hid_pidff_init(struct hid_device *hid)
 
        pidff->hid = hid;
 
+       hid_device_io_start(hid);
+
        pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff);
        pidff_find_reports(hid, HID_FEATURE_REPORT, pidff);
 
@@ -1315,9 +1317,13 @@ int hid_pidff_init(struct hid_device *hid)
 
        hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
 
+       hid_device_io_stop(hid);
+
        return 0;
 
  fail:
+       hid_device_io_stop(hid);
+
        kfree(pidff);
        return error;
 }
index dc89be90b35e80f7d14d5dcaa71dda082c8ab84b..9be99a67bfe2ec9f042e765904913628f8c2b654 100644 (file)
@@ -80,6 +80,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
@@ -124,6 +125,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD, HID_QUIRK_NO_INIT_REPORTS },
index 654202941d307bc5216e2772b609b15a30e4f5a3..f0568a7e6de9b88d04e8ccad812c21f032ab1762 100644 (file)
@@ -173,10 +173,8 @@ static void wacom_usage_mapping(struct hid_device *hdev,
 {
        struct wacom *wacom = hid_get_drvdata(hdev);
        struct wacom_features *features = &wacom->wacom_wac.features;
-       bool finger = (field->logical == HID_DG_FINGER) ||
-                     (field->physical == HID_DG_FINGER);
-       bool pen = (field->logical == HID_DG_STYLUS) ||
-                  (field->physical == HID_DG_STYLUS);
+       bool finger = WACOM_FINGER_FIELD(field);
+       bool pen = WACOM_PEN_FIELD(field);
 
        /*
        * Requiring Stylus Usage will ignore boot mouse
@@ -405,6 +403,9 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
                else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) {
                        return wacom_set_device_mode(hdev, 18, 3, 2);
                }
+               else if (features->type == WACOM_27QHDT) {
+                       return wacom_set_device_mode(hdev, 131, 3, 2);
+               }
        } else if (features->device_type == BTN_TOOL_PEN) {
                if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
                        return wacom_set_device_mode(hdev, 2, 2, 2);
index ac7447c7b82e35ff81209c31dd417fb8a53de112..1a6507999a6534f0b851e209bb702696d1f50e58 100644 (file)
@@ -15,7 +15,6 @@
 #include "wacom_wac.h"
 #include "wacom.h"
 #include <linux/input/mt.h>
-#include <linux/hid.h>
 
 /* resolution for penabled devices */
 #define WACOM_PL_RES           20
@@ -444,9 +443,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
        /* Enter report */
        if ((data[1] & 0xfc) == 0xc0) {
-               if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
-                       wacom->shared->stylus_in_proximity = true;
-
                /* serial number of the tool */
                wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
                        (data[4] << 20) + (data[5] << 12) +
@@ -535,24 +531,46 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                return 1;
        }
 
+       /*
+        * don't report events for invalid data
+        */
        /* older I4 styli don't work with new Cintiqs */
-       if (!((wacom->id[idx] >> 20) & 0x01) &&
-                       (features->type == WACOM_21UX2))
+       if ((!((wacom->id[idx] >> 20) & 0x01) &&
+                       (features->type == WACOM_21UX2)) ||
+           /* Only large Intuos support Lense Cursor */
+           (wacom->tool[idx] == BTN_TOOL_LENS &&
+               (features->type == INTUOS3 ||
+                features->type == INTUOS3S ||
+                features->type == INTUOS4 ||
+                features->type == INTUOS4S ||
+                features->type == INTUOS5 ||
+                features->type == INTUOS5S ||
+                features->type == INTUOSPM ||
+                features->type == INTUOSPS)) ||
+          /* Cintiq doesn't send data when RDY bit isn't set */
+          (features->type == CINTIQ && !(data[1] & 0x40)))
                return 1;
 
-       /* Range Report */
-       if ((data[1] & 0xfe) == 0x20) {
+       if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
+               wacom->shared->stylus_in_proximity = true;
+
+       /* in Range while exiting */
+       if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) {
                input_report_key(input, BTN_TOUCH, 0);
                input_report_abs(input, ABS_PRESSURE, 0);
                input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
-               if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
-                       wacom->shared->stylus_in_proximity = true;
+               return 2;
        }
 
        /* Exit report */
        if ((data[1] & 0xfe) == 0x80) {
                if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
                        wacom->shared->stylus_in_proximity = false;
+               wacom->reporting_data = false;
+
+               /* don't report exit if we don't know the ID */
+               if (!wacom->id[idx])
+                       return 1;
 
                /*
                 * Reset all states otherwise we lose the initial states
@@ -586,6 +604,11 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                wacom->id[idx] = 0;
                return 2;
        }
+
+       /* don't report other events if we don't know the ID */
+       if (!wacom->id[idx])
+               return 1;
+
        return 0;
 }
 
@@ -633,6 +656,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
            data[0] != WACOM_REPORT_INTUOSREAD &&
            data[0] != WACOM_REPORT_INTUOSWRITE &&
            data[0] != WACOM_REPORT_INTUOSPAD &&
+           data[0] != WACOM_REPORT_CINTIQ &&
+           data[0] != WACOM_REPORT_CINTIQPAD &&
            data[0] != WACOM_REPORT_INTUOS5PAD) {
                dev_dbg(input->dev.parent,
                        "%s: received unknown report #%d\n", __func__, data[0]);
@@ -644,7 +669,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                idx = data[1] & 0x01;
 
        /* pad packets. Works as a second tool and is always in prox */
-       if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) {
+       if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
+           data[0] == WACOM_REPORT_CINTIQPAD) {
                input = wacom->pad_input;
                if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
                        input_report_key(input, BTN_0, (data[2] & 0x01));
@@ -744,6 +770,14 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        } else {
                                input_report_abs(input, ABS_MISC, 0);
                        }
+               } else if (features->type == WACOM_27QHD) {
+                       input_report_key(input, KEY_PROG1, data[2] & 0x01);
+                       input_report_key(input, KEY_PROG2, data[2] & 0x02);
+                       input_report_key(input, KEY_PROG3, data[2] & 0x04);
+
+                       input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
+                       input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
+                       input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
                } else if (features->type == CINTIQ_HYBRID) {
                        /*
                         * Do not send hardware buttons under Android. They
@@ -760,6 +794,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        input_report_key(input, BTN_7, (data[4] & 0x40));  /* Left   */
                        input_report_key(input, BTN_8, (data[4] & 0x80));  /* Down   */
                        input_report_key(input, BTN_0, (data[3] & 0x01));  /* Center */
+
+                       if (data[4] | (data[3] & 0x01)) {
+                               input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+                       } else {
+                               input_report_abs(input, ABS_MISC, 0);
+                       }
                } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
                        int i;
 
@@ -843,28 +883,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
        if (result)
                 return result - 1;
 
-       /* don't proceed if we don't know the ID */
-       if (!wacom->id[idx])
-               return 0;
-
-       /* Only large Intuos support Lense Cursor */
-       if (wacom->tool[idx] == BTN_TOOL_LENS &&
-           (features->type == INTUOS3 ||
-            features->type == INTUOS3S ||
-            features->type == INTUOS4 ||
-            features->type == INTUOS4S ||
-            features->type == INTUOS5 ||
-            features->type == INTUOS5S ||
-            features->type == INTUOSPM ||
-            features->type == INTUOSPS)) {
-
-               return 0;
-       }
-
-       /* Cintiq doesn't send data when RDY bit isn't set */
-       if (features->type == CINTIQ && !(data[1] & 0x40))
-                 return 0;
-
        if (features->type >= INTUOS3S) {
                input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
                input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
@@ -951,6 +969,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
        input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
        input_report_key(input, wacom->tool[idx], 1);
        input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+       wacom->reporting_data = true;
        return 1;
 }
 
@@ -1019,8 +1038,20 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
        struct input_dev *input = wacom->input;
        unsigned char *data = wacom->data;
        int i;
-       int current_num_contacts = data[61];
+       int current_num_contacts = 0;
        int contacts_to_send = 0;
+       int num_contacts_left = 4; /* maximum contacts per packet */
+       int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
+       int y_offset = 2;
+
+       if (wacom->features.type == WACOM_27QHDT) {
+               current_num_contacts = data[63];
+               num_contacts_left = 10;
+               byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET;
+               y_offset = 0;
+       } else {
+               current_num_contacts = data[61];
+       }
 
        /*
         * First packet resets the counter since only the first
@@ -1029,12 +1060,11 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
        if (current_num_contacts)
                wacom->num_contacts_left = current_num_contacts;
 
-       /* There are at most 4 contacts per packet */
-       contacts_to_send = min(4, wacom->num_contacts_left);
+       contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);
 
        for (i = 0; i < contacts_to_send; i++) {
-               int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1;
-               bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity;
+               int offset = (byte_per_packet * i) + 1;
+               bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity;
                int slot = input_mt_get_slot_by_key(input, data[offset + 1]);
 
                if (slot < 0)
@@ -1044,18 +1074,23 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
 
                if (touch) {
                        int t_x = get_unaligned_le16(&data[offset + 2]);
-                       int c_x = get_unaligned_le16(&data[offset + 4]);
-                       int t_y = get_unaligned_le16(&data[offset + 6]);
-                       int c_y = get_unaligned_le16(&data[offset + 8]);
-                       int w = get_unaligned_le16(&data[offset + 10]);
-                       int h = get_unaligned_le16(&data[offset + 12]);
+                       int t_y = get_unaligned_le16(&data[offset + 4 + y_offset]);
 
                        input_report_abs(input, ABS_MT_POSITION_X, t_x);
                        input_report_abs(input, ABS_MT_POSITION_Y, t_y);
-                       input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
-                       input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y));
-                       input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
-                       input_report_abs(input, ABS_MT_ORIENTATION, w > h);
+
+                       if (wacom->features.type != WACOM_27QHDT) {
+                               int c_x = get_unaligned_le16(&data[offset + 4]);
+                               int c_y = get_unaligned_le16(&data[offset + 8]);
+                               int w = get_unaligned_le16(&data[offset + 10]);
+                               int h = get_unaligned_le16(&data[offset + 12]);
+
+                               input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
+                               input_report_abs(input, ABS_MT_WIDTH_MAJOR,
+                                                min(w, h) + int_dist(t_x, t_y, c_x, c_y));
+                               input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
+                               input_report_abs(input, ABS_MT_ORIENTATION, w > h);
+                       }
                }
        }
        input_mt_report_pointer_emulation(input, true);
@@ -1064,6 +1099,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
        if (wacom->num_contacts_left <= 0)
                wacom->num_contacts_left = 0;
 
+       wacom->shared->touch_down = (wacom->num_contacts_left > 0);
        return 1;
 }
 
@@ -1092,7 +1128,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
 
        for (i = 0; i < contacts_to_send; i++) {
                int offset = (WACOM_BYTES_PER_MT_PACKET + x_offset) * i + 3;
-               bool touch = data[offset] & 0x1;
+               bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity;
                int id = get_unaligned_le16(&data[offset + 1]);
                int slot = input_mt_get_slot_by_key(input, id);
 
@@ -1114,6 +1150,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
        if (wacom->num_contacts_left < 0)
                wacom->num_contacts_left = 0;
 
+       wacom->shared->touch_down = (wacom->num_contacts_left > 0);
        return 1;
 }
 
@@ -1514,13 +1551,6 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
        wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(hdev);
 }
 
-#define WACOM_PEN_FIELD(f)     (((f)->logical == HID_DG_STYLUS) || \
-                                ((f)->physical == HID_DG_STYLUS) || \
-                                ((f)->application == HID_DG_PEN))
-#define WACOM_FINGER_FIELD(f)  (((f)->logical == HID_DG_FINGER) || \
-                                ((f)->physical == HID_DG_FINGER) || \
-                                ((f)->application == HID_DG_TOUCHSCREEN))
-
 void wacom_wac_usage_mapping(struct hid_device *hdev,
                struct hid_field *field, struct hid_usage *usage)
 {
@@ -1891,6 +1921,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
        case WACOM_21UX2:
        case WACOM_22HD:
        case WACOM_24HD:
+       case WACOM_27QHD:
        case DTK:
        case CINTIQ_HYBRID:
                sync = wacom_intuos_irq(wacom_wac);
@@ -1901,6 +1932,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                break;
 
        case WACOM_24HDT:
+       case WACOM_27QHDT:
                sync = wacom_24hdt_irq(wacom_wac);
                break;
 
@@ -2086,32 +2118,17 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
        wacom_abs_set_axis(input_dev, wacom_wac);
 
        switch (features->type) {
-       case WACOM_MO:
-       case WACOM_G4:
-               /* fall through */
-
-       case GRAPHIRE:
-               input_set_capability(input_dev, EV_REL, REL_WHEEL);
-
-               __set_bit(BTN_LEFT, input_dev->keybit);
-               __set_bit(BTN_RIGHT, input_dev->keybit);
-               __set_bit(BTN_MIDDLE, input_dev->keybit);
-
-               __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
-               __set_bit(BTN_TOOL_PEN, input_dev->keybit);
-               __set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
-               __set_bit(BTN_STYLUS, input_dev->keybit);
-               __set_bit(BTN_STYLUS2, input_dev->keybit);
-
-               __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-               break;
-
        case GRAPHIRE_BT:
                __clear_bit(ABS_MISC, input_dev->absbit);
+
+       case WACOM_MO:
+       case WACOM_G4:
                input_set_abs_params(input_dev, ABS_DISTANCE, 0,
                                              features->distance_max,
                                              0, 0);
+               /* fall through */
 
+       case GRAPHIRE:
                input_set_capability(input_dev, EV_REL, REL_WHEEL);
 
                __set_bit(BTN_LEFT, input_dev->keybit);
@@ -2127,31 +2144,15 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
                break;
 
+       case WACOM_27QHD:
        case WACOM_24HD:
-               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-               input_abs_set_res(input_dev, ABS_Z, 287);
-               input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
-               /* fall through */
-
        case DTK:
-               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-               wacom_setup_cintiq(wacom_wac);
-               break;
-
        case WACOM_22HD:
        case WACOM_21UX2:
        case WACOM_BEE:
        case CINTIQ:
-               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-               input_abs_set_res(input_dev, ABS_Z, 287);
-
-               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-               wacom_setup_cintiq(wacom_wac);
-               break;
-
        case WACOM_13HD:
+       case CINTIQ_HYBRID:
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                input_abs_set_res(input_dev, ABS_Z, 287);
                __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
@@ -2161,6 +2162,10 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
        case INTUOS3:
        case INTUOS3L:
        case INTUOS3S:
+       case INTUOS4:
+       case INTUOS4WL:
+       case INTUOS4L:
+       case INTUOS4S:
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                input_abs_set_res(input_dev, ABS_Z, 287);
                /* fall through */
@@ -2199,17 +2204,6 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                }
                break;
 
-       case INTUOS4:
-       case INTUOS4WL:
-       case INTUOS4L:
-       case INTUOS4S:
-               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-               input_abs_set_res(input_dev, ABS_Z, 287);
-               wacom_setup_intuos(wacom_wac);
-
-               __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-               break;
-
        case WACOM_24HDT:
                if (features->device_type == BTN_TOOL_FINGER) {
                        input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0);
@@ -2219,6 +2213,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                }
                /* fall through */
 
+       case WACOM_27QHDT:
        case MTSCREEN:
        case MTTPC:
        case MTTPC_B:
@@ -2305,14 +2300,6 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                                              0, 0);
                }
                break;
-
-       case CINTIQ_HYBRID:
-               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-               input_abs_set_res(input_dev, ABS_Z, 287);
-               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-               wacom_setup_cintiq(wacom_wac);
-               break;
        }
        return 0;
 }
@@ -2374,6 +2361,19 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
                input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
                break;
 
+       case WACOM_27QHD:
+               __set_bit(KEY_PROG1, input_dev->keybit);
+               __set_bit(KEY_PROG2, input_dev->keybit);
+               __set_bit(KEY_PROG3, input_dev->keybit);
+               input_set_abs_params(input_dev, ABS_X, -2048, 2048, 0, 0);
+               input_abs_set_res(input_dev, ABS_X, 1024); /* points/g */
+               input_set_abs_params(input_dev, ABS_Y, -2048, 2048, 0, 0);
+               input_abs_set_res(input_dev, ABS_Y, 1024);
+               input_set_abs_params(input_dev, ABS_Z, -2048, 2048, 0, 0);
+               input_abs_set_res(input_dev, ABS_Z, 1024);
+               __set_bit(INPUT_PROP_ACCELEROMETER, input_dev->propbit);
+               break;
+
        case DTK:
                for (i = 0; i < 6; i++)
                        __set_bit(BTN_0 + i, input_dev->keybit);
@@ -2724,6 +2724,18 @@ static const struct wacom_features wacom_features_0xF6 =
        { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
          .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10,
          .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x32A =
+       { "Wacom Cintiq 27QHD", 119740, 67520, 2047,
+         63, WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+         WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0x32B =
+       { "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63,
+         WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+         WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C };
+static const struct wacom_features wacom_features_0x32C =
+       { "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32B, .touch_max = 10 };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX", 87200, 65600, 1023, 63,
          CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
@@ -3090,6 +3102,9 @@ const struct hid_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x315) },
        { USB_DEVICE_WACOM(0x317) },
        { USB_DEVICE_WACOM(0x323) },
+       { USB_DEVICE_WACOM(0x32A) },
+       { USB_DEVICE_WACOM(0x32B) },
+       { USB_DEVICE_WACOM(0x32C) },
        { USB_DEVICE_WACOM(0x32F) },
        { USB_DEVICE_WACOM(0x4001) },
        { USB_DEVICE_WACOM(0x4004) },
index bfad815cda8a98514904162c74ca29a163e7c9ce..021ee1c1980a832717f575d1fe50aa0df0071236 100644 (file)
 #define WACOM_WAC_H
 
 #include <linux/types.h>
+#include <linux/hid.h>
 
 /* maximum packet length for USB devices */
-#define WACOM_PKGLEN_MAX       68
+#define WACOM_PKGLEN_MAX       192
 
 #define WACOM_NAME_MAX         64
 
@@ -36,6 +37,7 @@
 /* wacom data size per MT contact */
 #define WACOM_BYTES_PER_MT_PACKET      11
 #define WACOM_BYTES_PER_24HDT_PACKET   14
+#define WACOM_BYTES_PER_QHDTHID_PACKET  6
 
 /* device IDs */
 #define STYLUS_DEVICE_ID       0x02
@@ -57,6 +59,8 @@
 #define WACOM_REPORT_TPCMT             13
 #define WACOM_REPORT_TPCMT2            3
 #define WACOM_REPORT_TPCHID            15
+#define WACOM_REPORT_CINTIQ            16
+#define WACOM_REPORT_CINTIQPAD         17
 #define WACOM_REPORT_TPCST             16
 #define WACOM_REPORT_DTUS              17
 #define WACOM_REPORT_TPC1FGE           18
 #define WACOM_QUIRK_MONITOR            0x0008
 #define WACOM_QUIRK_BATTERY            0x0010
 
+#define WACOM_PEN_FIELD(f)     (((f)->logical == HID_DG_STYLUS) || \
+                                ((f)->physical == HID_DG_STYLUS) || \
+                                ((f)->physical == HID_DG_PEN) || \
+                                ((f)->application == HID_DG_PEN))
+#define WACOM_FINGER_FIELD(f)  (((f)->logical == HID_DG_FINGER) || \
+                                ((f)->physical == HID_DG_FINGER) || \
+                                ((f)->application == HID_DG_TOUCHSCREEN))
+
 enum {
        PENPARTNER = 0,
        GRAPHIRE,
@@ -100,6 +112,7 @@ enum {
        WACOM_22HD,
        DTK,
        WACOM_24HD,
+       WACOM_27QHD,
        CINTIQ_HYBRID,
        CINTIQ,
        WACOM_BEE,
@@ -108,6 +121,7 @@ enum {
        WIRELESS,
        BAMBOO_PT,
        WACOM_24HDT,
+       WACOM_27QHDT,
        TABLETPC,   /* add new TPC below */
        TABLETPCE,
        TABLETPC2FG,
@@ -180,6 +194,7 @@ struct wacom_wac {
        int tool[2];
        int id[2];
        __u32 serial[2];
+       bool reporting_data;
        struct wacom_features features;
        struct wacom_shared *shared;
        struct input_dev *input;
index 06c4607744f637156d14a667b9b5b55f0a37b693..efc7787a41a8c75db5b89509e8ec4051d019038a 100644 (file)
@@ -574,7 +574,9 @@ static inline void hid_set_drvdata(struct hid_device *hdev, void *data)
 #define HID_GLOBAL_STACK_SIZE 4
 #define HID_COLLECTION_STACK_SIZE 4
 
-#define HID_SCAN_FLAG_MT_WIN_8                 0x00000001
+#define HID_SCAN_FLAG_MT_WIN_8                 BIT(0)
+#define HID_SCAN_FLAG_VENDOR_SPECIFIC          BIT(1)
+#define HID_SCAN_FLAG_GD_POINTER               BIT(2)
 
 struct hid_parser {
        struct hid_global     global;
index a1d7e931ab72cdfb93db7f434275492d99aca77d..b0a81307985282005ade90ee6da96e3048c405d3 100644 (file)
@@ -166,6 +166,7 @@ struct input_keymap_entry {
 #define INPUT_PROP_SEMI_MT             0x03    /* touch rectangle only */
 #define INPUT_PROP_TOPBUTTONPAD                0x04    /* softbuttons at top of pad */
 #define INPUT_PROP_POINTING_STICK      0x05    /* is a pointing stick */
+#define INPUT_PROP_ACCELEROMETER       0x06    /* has accelerometer */
 
 #define INPUT_PROP_MAX                 0x1f
 #define INPUT_PROP_CNT                 (INPUT_PROP_MAX + 1)