diff options
| -rw-r--r-- | MAINTAINERS | 6 | ||||
| -rw-r--r-- | drivers/hid/Kconfig | 19 | ||||
| -rw-r--r-- | drivers/hid/Makefile | 2 | ||||
| -rw-r--r-- | drivers/hid/hid-asus.c | 299 | ||||
| -rw-r--r-- | drivers/hid/hid-core.c | 14 | ||||
| -rw-r--r-- | drivers/hid/hid-cp2112.c | 205 | ||||
| -rw-r--r-- | drivers/hid/hid-ids.h | 19 | ||||
| -rw-r--r-- | drivers/hid/hid-input.c | 96 | ||||
| -rw-r--r-- | drivers/hid/hid-mf.c | 166 | ||||
| -rw-r--r-- | drivers/hid/hid-microsoft.c | 6 | ||||
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 88 | ||||
| -rw-r--r-- | drivers/hid/hid-sensor-hub.c | 6 | ||||
| -rw-r--r-- | drivers/hid/hid-sony.c | 445 | ||||
| -rw-r--r-- | drivers/hid/hid-udraw-ps3.c | 474 | ||||
| -rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 146 | ||||
| -rw-r--r-- | drivers/hid/intel-ish-hid/ipc/ipc.c | 67 | ||||
| -rw-r--r-- | drivers/hid/intel-ish-hid/ipc/utils.h | 64 | ||||
| -rw-r--r-- | drivers/hid/intel-ish-hid/ishtp/bus.c | 9 | ||||
| -rw-r--r-- | drivers/hid/intel-ish-hid/ishtp/hbm.c | 6 | ||||
| -rw-r--r-- | drivers/hid/usbhid/hid-core.c | 6 | ||||
| -rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 5 | ||||
| -rw-r--r-- | drivers/hid/wacom.h | 2 | ||||
| -rw-r--r-- | drivers/hid/wacom_sys.c | 92 | ||||
| -rw-r--r-- | drivers/hid/wacom_wac.c | 601 | ||||
| -rw-r--r-- | drivers/hid/wacom_wac.h | 76 | ||||
| -rw-r--r-- | include/linux/hid.h | 5 |
26 files changed, 2440 insertions, 484 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index e376bbd1c555..680625c2d8f6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -12488,6 +12488,12 @@ S: Maintained | |||
| 12488 | F: Documentation/filesystems/udf.txt | 12488 | F: Documentation/filesystems/udf.txt |
| 12489 | F: fs/udf/ | 12489 | F: fs/udf/ |
| 12490 | 12490 | ||
| 12491 | UDRAW TABLET | ||
| 12492 | M: Bastien Nocera <hadess@hadess.net> | ||
| 12493 | L: linux-input@vger.kernel.org | ||
| 12494 | S: Maintained | ||
| 12495 | F: drivers/hid/hid-udraw.c | ||
| 12496 | |||
| 12491 | UFS FILESYSTEM | 12497 | UFS FILESYSTEM |
| 12492 | M: Evgeniy Dushistov <dushistov@mail.ru> | 12498 | M: Evgeniy Dushistov <dushistov@mail.ru> |
| 12493 | S: Maintained | 12499 | S: Maintained |
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index cd4599c0523b..4070b7386e9d 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -138,7 +138,7 @@ config HID_ASUS | |||
| 138 | tristate "Asus" | 138 | tristate "Asus" |
| 139 | depends on I2C_HID | 139 | depends on I2C_HID |
| 140 | ---help--- | 140 | ---help--- |
| 141 | Support for Asus notebook built-in keyboard via i2c. | 141 | Support for Asus notebook built-in keyboard and touchpad via i2c. |
| 142 | 142 | ||
| 143 | Supported devices: | 143 | Supported devices: |
| 144 | - EeeBook X205TA | 144 | - EeeBook X205TA |
| @@ -214,7 +214,7 @@ config HID_CMEDIA | |||
| 214 | 214 | ||
| 215 | config HID_CP2112 | 215 | config HID_CP2112 |
| 216 | tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support" | 216 | tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support" |
| 217 | depends on USB_HID && I2C && GPIOLIB | 217 | depends on USB_HID && I2C && GPIOLIB && GPIOLIB_IRQCHIP |
| 218 | ---help--- | 218 | ---help--- |
| 219 | Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge. | 219 | Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge. |
| 220 | This is a HID device driver which registers as an i2c adapter | 220 | This is a HID device driver which registers as an i2c adapter |
| @@ -512,6 +512,14 @@ config HID_MAGICMOUSE | |||
| 512 | Say Y here if you want support for the multi-touch features of the | 512 | Say Y here if you want support for the multi-touch features of the |
| 513 | Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad. | 513 | Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad. |
| 514 | 514 | ||
| 515 | config HID_MAYFLASH | ||
| 516 | tristate "Mayflash game controller adapter force feedback" | ||
| 517 | depends on HID | ||
| 518 | select INPUT_FF_MEMLESS | ||
| 519 | ---help--- | ||
| 520 | Say Y here if you have HJZ Mayflash PS3 game controller adapters | ||
| 521 | and want to enable force feedback support. | ||
| 522 | |||
| 515 | config HID_MICROSOFT | 523 | config HID_MICROSOFT |
| 516 | tristate "Microsoft non-fully HID-compliant devices" | 524 | tristate "Microsoft non-fully HID-compliant devices" |
| 517 | depends on HID | 525 | depends on HID |
| @@ -861,6 +869,13 @@ config THRUSTMASTER_FF | |||
| 861 | a THRUSTMASTER Dual Trigger 3-in-1 or a THRUSTMASTER Ferrari GT | 869 | a THRUSTMASTER Dual Trigger 3-in-1 or a THRUSTMASTER Ferrari GT |
| 862 | Rumble Force or Force Feedback Wheel. | 870 | Rumble Force or Force Feedback Wheel. |
| 863 | 871 | ||
| 872 | config HID_UDRAW_PS3 | ||
| 873 | tristate "THQ PS3 uDraw tablet" | ||
| 874 | depends on HID | ||
| 875 | ---help--- | ||
| 876 | Say Y here if you want to use the THQ uDraw gaming tablet for | ||
| 877 | the PS3. | ||
| 878 | |||
| 864 | config HID_WACOM | 879 | config HID_WACOM |
| 865 | tristate "Wacom Intuos/Graphire tablet support (USB)" | 880 | tristate "Wacom Intuos/Graphire tablet support (USB)" |
| 866 | depends on HID | 881 | depends on HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 86b2b5785fd2..4d111f23e801 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
| @@ -58,6 +58,7 @@ obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | |||
| 58 | obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o | 58 | obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o |
| 59 | obj-$(CONFIG_HID_LOGITECH_HIDPP) += hid-logitech-hidpp.o | 59 | obj-$(CONFIG_HID_LOGITECH_HIDPP) += hid-logitech-hidpp.o |
| 60 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o | 60 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o |
| 61 | obj-$(CONFIG_HID_MAYFLASH) += hid-mf.o | ||
| 61 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 62 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
| 62 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o | 63 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
| 63 | obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o | 64 | obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o |
| @@ -96,6 +97,7 @@ obj-$(CONFIG_HID_TIVO) += hid-tivo.o | |||
| 96 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o | 97 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o |
| 97 | obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o | 98 | obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o |
| 98 | obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o | 99 | obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o |
| 100 | obj-$(CONFIG_HID_UDRAW_PS3) += hid-udraw-ps3.o | ||
| 99 | obj-$(CONFIG_HID_LED) += hid-led.o | 101 | obj-$(CONFIG_HID_LED) += hid-led.o |
| 100 | obj-$(CONFIG_HID_XINMO) += hid-xinmo.o | 102 | obj-$(CONFIG_HID_XINMO) += hid-xinmo.o |
| 101 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o | 103 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o |
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index 7a811ec4f2e1..d40ed9fdf68d 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c | |||
| @@ -11,6 +11,12 @@ | |||
| 11 | * This module based on hid-ortek by | 11 | * This module based on hid-ortek by |
| 12 | * Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com> | 12 | * Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com> |
| 13 | * Copyright (c) 2011 Jiri Kosina | 13 | * Copyright (c) 2011 Jiri Kosina |
| 14 | * | ||
| 15 | * This module has been updated to add support for Asus i2c touchpad. | ||
| 16 | * | ||
| 17 | * Copyright (c) 2016 Brendan McGrath <redmcg@redmandi.dyndns.org> | ||
| 18 | * Copyright (c) 2016 Victor Vlasenko <victor.vlasenko@sysgears.com> | ||
| 19 | * Copyright (c) 2016 Frederik Wenigwieser <frederik.wenigwieser@gmail.com> | ||
| 14 | */ | 20 | */ |
| 15 | 21 | ||
| 16 | /* | 22 | /* |
| @@ -20,16 +26,287 @@ | |||
| 20 | * any later version. | 26 | * any later version. |
| 21 | */ | 27 | */ |
| 22 | 28 | ||
| 23 | #include <linux/device.h> | ||
| 24 | #include <linux/hid.h> | 29 | #include <linux/hid.h> |
| 25 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 31 | #include <linux/input/mt.h> | ||
| 26 | 32 | ||
| 27 | #include "hid-ids.h" | 33 | #include "hid-ids.h" |
| 28 | 34 | ||
| 35 | MODULE_AUTHOR("Yusuke Fujimaki <usk.fujimaki@gmail.com>"); | ||
| 36 | MODULE_AUTHOR("Brendan McGrath <redmcg@redmandi.dyndns.org>"); | ||
| 37 | MODULE_AUTHOR("Victor Vlasenko <victor.vlasenko@sysgears.com>"); | ||
| 38 | MODULE_AUTHOR("Frederik Wenigwieser <frederik.wenigwieser@gmail.com>"); | ||
| 39 | MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); | ||
| 40 | |||
| 41 | #define FEATURE_REPORT_ID 0x0d | ||
| 42 | #define INPUT_REPORT_ID 0x5d | ||
| 43 | |||
| 44 | #define INPUT_REPORT_SIZE 28 | ||
| 45 | |||
| 46 | #define MAX_CONTACTS 5 | ||
| 47 | |||
| 48 | #define MAX_X 2794 | ||
| 49 | #define MAX_Y 1758 | ||
| 50 | #define MAX_TOUCH_MAJOR 8 | ||
| 51 | #define MAX_PRESSURE 128 | ||
| 52 | |||
| 53 | #define CONTACT_DATA_SIZE 5 | ||
| 54 | |||
| 55 | #define BTN_LEFT_MASK 0x01 | ||
| 56 | #define CONTACT_TOOL_TYPE_MASK 0x80 | ||
| 57 | #define CONTACT_X_MSB_MASK 0xf0 | ||
| 58 | #define CONTACT_Y_MSB_MASK 0x0f | ||
| 59 | #define CONTACT_TOUCH_MAJOR_MASK 0x07 | ||
| 60 | #define CONTACT_PRESSURE_MASK 0x7f | ||
| 61 | |||
| 62 | #define QUIRK_FIX_NOTEBOOK_REPORT BIT(0) | ||
| 63 | #define QUIRK_NO_INIT_REPORTS BIT(1) | ||
| 64 | #define QUIRK_SKIP_INPUT_MAPPING BIT(2) | ||
| 65 | #define QUIRK_IS_MULTITOUCH BIT(3) | ||
| 66 | |||
| 67 | #define NOTEBOOK_QUIRKS QUIRK_FIX_NOTEBOOK_REPORT | ||
| 68 | #define TOUCHPAD_QUIRKS (QUIRK_NO_INIT_REPORTS | \ | ||
| 69 | QUIRK_SKIP_INPUT_MAPPING | \ | ||
| 70 | QUIRK_IS_MULTITOUCH) | ||
| 71 | |||
| 72 | #define TRKID_SGN ((TRKID_MAX + 1) >> 1) | ||
| 73 | |||
| 74 | struct asus_drvdata { | ||
| 75 | unsigned long quirks; | ||
| 76 | struct input_dev *input; | ||
| 77 | }; | ||
| 78 | |||
| 79 | static void asus_report_contact_down(struct input_dev *input, | ||
| 80 | int toolType, u8 *data) | ||
| 81 | { | ||
| 82 | int touch_major, pressure; | ||
| 83 | int x = (data[0] & CONTACT_X_MSB_MASK) << 4 | data[1]; | ||
| 84 | int y = MAX_Y - ((data[0] & CONTACT_Y_MSB_MASK) << 8 | data[2]); | ||
| 85 | |||
| 86 | if (toolType == MT_TOOL_PALM) { | ||
| 87 | touch_major = MAX_TOUCH_MAJOR; | ||
| 88 | pressure = MAX_PRESSURE; | ||
| 89 | } else { | ||
| 90 | touch_major = (data[3] >> 4) & CONTACT_TOUCH_MAJOR_MASK; | ||
| 91 | pressure = data[4] & CONTACT_PRESSURE_MASK; | ||
| 92 | } | ||
| 93 | |||
| 94 | input_report_abs(input, ABS_MT_POSITION_X, x); | ||
| 95 | input_report_abs(input, ABS_MT_POSITION_Y, y); | ||
| 96 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major); | ||
| 97 | input_report_abs(input, ABS_MT_PRESSURE, pressure); | ||
| 98 | } | ||
| 99 | |||
| 100 | /* Required for Synaptics Palm Detection */ | ||
| 101 | static void asus_report_tool_width(struct input_dev *input) | ||
| 102 | { | ||
| 103 | struct input_mt *mt = input->mt; | ||
| 104 | struct input_mt_slot *oldest; | ||
| 105 | int oldid, count, i; | ||
| 106 | |||
| 107 | oldest = NULL; | ||
| 108 | oldid = mt->trkid; | ||
| 109 | count = 0; | ||
| 110 | |||
| 111 | for (i = 0; i < mt->num_slots; ++i) { | ||
| 112 | struct input_mt_slot *ps = &mt->slots[i]; | ||
| 113 | int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID); | ||
| 114 | |||
| 115 | if (id < 0) | ||
| 116 | continue; | ||
| 117 | if ((id - oldid) & TRKID_SGN) { | ||
| 118 | oldest = ps; | ||
| 119 | oldid = id; | ||
| 120 | } | ||
| 121 | count++; | ||
| 122 | } | ||
| 123 | |||
| 124 | if (oldest) { | ||
| 125 | input_report_abs(input, ABS_TOOL_WIDTH, | ||
| 126 | input_mt_get_value(oldest, ABS_MT_TOUCH_MAJOR)); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | static void asus_report_input(struct input_dev *input, u8 *data) | ||
| 131 | { | ||
| 132 | int i; | ||
| 133 | u8 *contactData = data + 2; | ||
| 134 | |||
| 135 | for (i = 0; i < MAX_CONTACTS; i++) { | ||
| 136 | bool down = !!(data[1] & BIT(i+3)); | ||
| 137 | int toolType = contactData[3] & CONTACT_TOOL_TYPE_MASK ? | ||
| 138 | MT_TOOL_PALM : MT_TOOL_FINGER; | ||
| 139 | |||
| 140 | input_mt_slot(input, i); | ||
| 141 | input_mt_report_slot_state(input, toolType, down); | ||
| 142 | |||
| 143 | if (down) { | ||
| 144 | asus_report_contact_down(input, toolType, contactData); | ||
| 145 | contactData += CONTACT_DATA_SIZE; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | input_report_key(input, BTN_LEFT, data[1] & BTN_LEFT_MASK); | ||
| 150 | asus_report_tool_width(input); | ||
| 151 | |||
| 152 | input_mt_sync_frame(input); | ||
| 153 | input_sync(input); | ||
| 154 | } | ||
| 155 | |||
| 156 | static int asus_raw_event(struct hid_device *hdev, | ||
| 157 | struct hid_report *report, u8 *data, int size) | ||
| 158 | { | ||
| 159 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | ||
| 160 | |||
| 161 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH && | ||
| 162 | data[0] == INPUT_REPORT_ID && | ||
| 163 | size == INPUT_REPORT_SIZE) { | ||
| 164 | asus_report_input(drvdata->input, data); | ||
| 165 | return 1; | ||
| 166 | } | ||
| 167 | |||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi) | ||
| 172 | { | ||
| 173 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | ||
| 174 | |||
| 175 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH) { | ||
| 176 | int ret; | ||
| 177 | struct input_dev *input = hi->input; | ||
| 178 | |||
| 179 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, MAX_X, 0, 0); | ||
| 180 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0); | ||
| 181 | input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MAX_TOUCH_MAJOR, 0, 0); | ||
| 182 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0); | ||
| 183 | input_set_abs_params(input, ABS_MT_PRESSURE, 0, MAX_PRESSURE, 0, 0); | ||
| 184 | |||
| 185 | __set_bit(BTN_LEFT, input->keybit); | ||
| 186 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); | ||
| 187 | |||
| 188 | ret = input_mt_init_slots(input, MAX_CONTACTS, INPUT_MT_POINTER); | ||
| 189 | |||
| 190 | if (ret) { | ||
| 191 | hid_err(hdev, "Asus input mt init slots failed: %d\n", ret); | ||
| 192 | return ret; | ||
| 193 | } | ||
| 194 | |||
| 195 | drvdata->input = input; | ||
| 196 | } | ||
| 197 | |||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static int asus_input_mapping(struct hid_device *hdev, | ||
| 202 | struct hid_input *hi, struct hid_field *field, | ||
| 203 | struct hid_usage *usage, unsigned long **bit, | ||
| 204 | int *max) | ||
| 205 | { | ||
| 206 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | ||
| 207 | |||
| 208 | if (drvdata->quirks & QUIRK_SKIP_INPUT_MAPPING) { | ||
| 209 | /* Don't map anything from the HID report. | ||
| 210 | * We do it all manually in asus_input_configured | ||
| 211 | */ | ||
| 212 | return -1; | ||
| 213 | } | ||
| 214 | |||
| 215 | return 0; | ||
| 216 | } | ||
| 217 | |||
| 218 | static int asus_start_multitouch(struct hid_device *hdev) | ||
| 219 | { | ||
| 220 | int ret; | ||
| 221 | const unsigned char buf[] = { FEATURE_REPORT_ID, 0x00, 0x03, 0x01, 0x00 }; | ||
| 222 | unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL); | ||
| 223 | |||
| 224 | if (!dmabuf) { | ||
| 225 | ret = -ENOMEM; | ||
| 226 | hid_err(hdev, "Asus failed to alloc dma buf: %d\n", ret); | ||
| 227 | return ret; | ||
| 228 | } | ||
| 229 | |||
| 230 | ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, sizeof(buf), | ||
| 231 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); | ||
| 232 | |||
| 233 | kfree(dmabuf); | ||
| 234 | |||
| 235 | if (ret != sizeof(buf)) { | ||
| 236 | hid_err(hdev, "Asus failed to start multitouch: %d\n", ret); | ||
| 237 | return ret; | ||
| 238 | } | ||
| 239 | |||
| 240 | return 0; | ||
| 241 | } | ||
| 242 | |||
| 243 | static int __maybe_unused asus_reset_resume(struct hid_device *hdev) | ||
| 244 | { | ||
| 245 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | ||
| 246 | |||
| 247 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH) | ||
| 248 | return asus_start_multitouch(hdev); | ||
| 249 | |||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
| 254 | { | ||
| 255 | int ret; | ||
| 256 | struct asus_drvdata *drvdata; | ||
| 257 | |||
| 258 | drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
| 259 | if (drvdata == NULL) { | ||
| 260 | hid_err(hdev, "Can't alloc Asus descriptor\n"); | ||
| 261 | return -ENOMEM; | ||
| 262 | } | ||
| 263 | |||
| 264 | hid_set_drvdata(hdev, drvdata); | ||
| 265 | |||
| 266 | drvdata->quirks = id->driver_data; | ||
| 267 | |||
| 268 | if (drvdata->quirks & QUIRK_NO_INIT_REPORTS) | ||
| 269 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; | ||
| 270 | |||
| 271 | ret = hid_parse(hdev); | ||
| 272 | if (ret) { | ||
| 273 | hid_err(hdev, "Asus hid parse failed: %d\n", ret); | ||
| 274 | return ret; | ||
| 275 | } | ||
| 276 | |||
| 277 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 278 | if (ret) { | ||
| 279 | hid_err(hdev, "Asus hw start failed: %d\n", ret); | ||
| 280 | return ret; | ||
| 281 | } | ||
| 282 | |||
| 283 | if (!drvdata->input) { | ||
| 284 | hid_err(hdev, "Asus input not registered\n"); | ||
| 285 | ret = -ENOMEM; | ||
| 286 | goto err_stop_hw; | ||
| 287 | } | ||
| 288 | |||
| 289 | drvdata->input->name = "Asus TouchPad"; | ||
| 290 | |||
| 291 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH) { | ||
| 292 | ret = asus_start_multitouch(hdev); | ||
| 293 | if (ret) | ||
| 294 | goto err_stop_hw; | ||
| 295 | } | ||
| 296 | |||
| 297 | return 0; | ||
| 298 | err_stop_hw: | ||
| 299 | hid_hw_stop(hdev); | ||
| 300 | return ret; | ||
| 301 | } | ||
| 302 | |||
| 29 | static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 303 | static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 30 | unsigned int *rsize) | 304 | unsigned int *rsize) |
| 31 | { | 305 | { |
| 32 | if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x65) { | 306 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); |
| 307 | |||
| 308 | if (drvdata->quirks & QUIRK_FIX_NOTEBOOK_REPORT && | ||
| 309 | *rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x65) { | ||
| 33 | hid_info(hdev, "Fixing up Asus notebook report descriptor\n"); | 310 | hid_info(hdev, "Fixing up Asus notebook report descriptor\n"); |
| 34 | rdesc[55] = 0xdd; | 311 | rdesc[55] = 0xdd; |
| 35 | } | 312 | } |
| @@ -37,15 +314,25 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 37 | } | 314 | } |
| 38 | 315 | ||
| 39 | static const struct hid_device_id asus_devices[] = { | 316 | static const struct hid_device_id asus_devices[] = { |
| 40 | { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) }, | 317 | { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 318 | USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD), NOTEBOOK_QUIRKS}, | ||
| 319 | { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, | ||
| 320 | USB_DEVICE_ID_ASUSTEK_TOUCHPAD), TOUCHPAD_QUIRKS }, | ||
| 41 | { } | 321 | { } |
| 42 | }; | 322 | }; |
| 43 | MODULE_DEVICE_TABLE(hid, asus_devices); | 323 | MODULE_DEVICE_TABLE(hid, asus_devices); |
| 44 | 324 | ||
| 45 | static struct hid_driver asus_driver = { | 325 | static struct hid_driver asus_driver = { |
| 46 | .name = "asus", | 326 | .name = "asus", |
| 47 | .id_table = asus_devices, | 327 | .id_table = asus_devices, |
| 48 | .report_fixup = asus_report_fixup | 328 | .report_fixup = asus_report_fixup, |
| 329 | .probe = asus_probe, | ||
| 330 | .input_mapping = asus_input_mapping, | ||
| 331 | .input_configured = asus_input_configured, | ||
| 332 | #ifdef CONFIG_PM | ||
| 333 | .reset_resume = asus_reset_resume, | ||
| 334 | #endif | ||
| 335 | .raw_event = asus_raw_event | ||
| 49 | }; | 336 | }; |
| 50 | module_hid_driver(asus_driver); | 337 | module_hid_driver(asus_driver); |
| 51 | 338 | ||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2b89c701076f..cff060b56da9 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -727,8 +727,9 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type) | |||
| 727 | (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 || | 727 | (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 || |
| 728 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 || | 728 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 || |
| 729 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP || | 729 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP || |
| 730 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4 || | ||
| 731 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2 || | ||
| 730 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP || | 732 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP || |
| 731 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 || | ||
| 732 | hid->product == USB_DEVICE_ID_MS_POWER_COVER) && | 733 | hid->product == USB_DEVICE_ID_MS_POWER_COVER) && |
| 733 | hid->group == HID_GROUP_MULTITOUCH) | 734 | hid->group == HID_GROUP_MULTITOUCH) |
| 734 | hid->group = HID_GROUP_GENERIC; | 735 | hid->group = HID_GROUP_GENERIC; |
| @@ -1857,6 +1858,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1857 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1858 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1858 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1859 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1859 | { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) }, | 1860 | { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) }, |
| 1861 | { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_TOUCHPAD) }, | ||
| 1860 | { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, | 1862 | { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, |
| 1861 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1863 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
| 1862 | { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, | 1864 | { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, |
| @@ -1883,6 +1885,9 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1883 | { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) }, | 1885 | { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) }, |
| 1884 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | 1886 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, |
| 1885 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, | 1887 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, |
| 1888 | #if IS_ENABLED(CONFIG_HID_MAYFLASH) | ||
| 1889 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) }, | ||
| 1890 | #endif | ||
| 1886 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) }, | 1891 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) }, |
| 1887 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) }, | 1892 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) }, |
| 1888 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, | 1893 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
| @@ -1983,8 +1988,9 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1983 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) }, | 1988 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) }, |
| 1984 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) }, | 1989 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) }, |
| 1985 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) }, | 1990 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) }, |
| 1991 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4) }, | ||
| 1992 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2) }, | ||
| 1986 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP) }, | 1993 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP) }, |
| 1987 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) }, | ||
| 1988 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) }, | 1994 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) }, |
| 1989 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) }, | 1995 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) }, |
| 1990 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) }, | 1996 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) }, |
| @@ -2059,6 +2065,9 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 2059 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 2065 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, |
| 2060 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, | 2066 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, |
| 2061 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, | 2067 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, |
| 2068 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) }, | ||
| 2069 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) }, | ||
| 2070 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) }, | ||
| 2062 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, | 2071 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, |
| 2063 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) }, | 2072 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) }, |
| 2064 | { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) }, | 2073 | { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) }, |
| @@ -2086,6 +2095,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 2086 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, | 2095 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, |
| 2087 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, | 2096 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, |
| 2088 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) }, | 2097 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) }, |
| 2098 | { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) }, | ||
| 2089 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) }, | 2099 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) }, |
| 2090 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) }, | 2100 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) }, |
| 2091 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) }, | 2101 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) }, |
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index 60d30203a5fa..f31a778b0851 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | * http://www.silabs.com/Support%20Documents/TechnicalDocs/AN495.pdf | 24 | * http://www.silabs.com/Support%20Documents/TechnicalDocs/AN495.pdf |
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | #include <linux/gpio.h> | ||
| 27 | #include <linux/gpio/driver.h> | 28 | #include <linux/gpio/driver.h> |
| 28 | #include <linux/hid.h> | 29 | #include <linux/hid.h> |
| 29 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
| @@ -168,6 +169,12 @@ struct cp2112_device { | |||
| 168 | struct gpio_chip gc; | 169 | struct gpio_chip gc; |
| 169 | u8 *in_out_buffer; | 170 | u8 *in_out_buffer; |
| 170 | spinlock_t lock; | 171 | spinlock_t lock; |
| 172 | |||
| 173 | struct gpio_desc *desc[8]; | ||
| 174 | bool gpio_poll; | ||
| 175 | struct delayed_work gpio_poll_worker; | ||
| 176 | unsigned long irq_mask; | ||
| 177 | u8 gpio_prev_state; | ||
| 171 | }; | 178 | }; |
| 172 | 179 | ||
| 173 | static int gpio_push_pull = 0xFF; | 180 | static int gpio_push_pull = 0xFF; |
| @@ -233,7 +240,7 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
| 233 | spin_unlock_irqrestore(&dev->lock, flags); | 240 | spin_unlock_irqrestore(&dev->lock, flags); |
| 234 | } | 241 | } |
| 235 | 242 | ||
| 236 | static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset) | 243 | static int cp2112_gpio_get_all(struct gpio_chip *chip) |
| 237 | { | 244 | { |
| 238 | struct cp2112_device *dev = gpiochip_get_data(chip); | 245 | struct cp2112_device *dev = gpiochip_get_data(chip); |
| 239 | struct hid_device *hdev = dev->hdev; | 246 | struct hid_device *hdev = dev->hdev; |
| @@ -252,7 +259,7 @@ static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset) | |||
| 252 | goto exit; | 259 | goto exit; |
| 253 | } | 260 | } |
| 254 | 261 | ||
| 255 | ret = (buf[1] >> offset) & 1; | 262 | ret = buf[1]; |
| 256 | 263 | ||
| 257 | exit: | 264 | exit: |
| 258 | spin_unlock_irqrestore(&dev->lock, flags); | 265 | spin_unlock_irqrestore(&dev->lock, flags); |
| @@ -260,6 +267,17 @@ exit: | |||
| 260 | return ret; | 267 | return ret; |
| 261 | } | 268 | } |
| 262 | 269 | ||
| 270 | static int cp2112_gpio_get(struct gpio_chip *chip, unsigned int offset) | ||
| 271 | { | ||
| 272 | int ret; | ||
| 273 | |||
| 274 | ret = cp2112_gpio_get_all(chip); | ||
| 275 | if (ret < 0) | ||
| 276 | return ret; | ||
| 277 | |||
| 278 | return (ret >> offset) & 1; | ||
| 279 | } | ||
| 280 | |||
| 263 | static int cp2112_gpio_direction_output(struct gpio_chip *chip, | 281 | static int cp2112_gpio_direction_output(struct gpio_chip *chip, |
| 264 | unsigned offset, int value) | 282 | unsigned offset, int value) |
| 265 | { | 283 | { |
| @@ -1041,6 +1059,166 @@ static void chmod_sysfs_attrs(struct hid_device *hdev) | |||
| 1041 | } | 1059 | } |
| 1042 | } | 1060 | } |
| 1043 | 1061 | ||
| 1062 | static void cp2112_gpio_irq_ack(struct irq_data *d) | ||
| 1063 | { | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | static void cp2112_gpio_irq_mask(struct irq_data *d) | ||
| 1067 | { | ||
| 1068 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
| 1069 | struct cp2112_device *dev = gpiochip_get_data(gc); | ||
| 1070 | |||
| 1071 | __clear_bit(d->hwirq, &dev->irq_mask); | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static void cp2112_gpio_irq_unmask(struct irq_data *d) | ||
| 1075 | { | ||
| 1076 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
| 1077 | struct cp2112_device *dev = gpiochip_get_data(gc); | ||
| 1078 | |||
| 1079 | __set_bit(d->hwirq, &dev->irq_mask); | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | static void cp2112_gpio_poll_callback(struct work_struct *work) | ||
| 1083 | { | ||
| 1084 | struct cp2112_device *dev = container_of(work, struct cp2112_device, | ||
| 1085 | gpio_poll_worker.work); | ||
| 1086 | struct irq_data *d; | ||
| 1087 | u8 gpio_mask; | ||
| 1088 | u8 virqs = (u8)dev->irq_mask; | ||
| 1089 | u32 irq_type; | ||
| 1090 | int irq, virq, ret; | ||
| 1091 | |||
| 1092 | ret = cp2112_gpio_get_all(&dev->gc); | ||
| 1093 | if (ret == -ENODEV) /* the hardware has been disconnected */ | ||
| 1094 | return; | ||
| 1095 | if (ret < 0) | ||
| 1096 | goto exit; | ||
| 1097 | |||
| 1098 | gpio_mask = ret; | ||
| 1099 | |||
| 1100 | while (virqs) { | ||
| 1101 | virq = ffs(virqs) - 1; | ||
| 1102 | virqs &= ~BIT(virq); | ||
| 1103 | |||
| 1104 | if (!dev->gc.to_irq) | ||
| 1105 | break; | ||
| 1106 | |||
| 1107 | irq = dev->gc.to_irq(&dev->gc, virq); | ||
| 1108 | |||
| 1109 | d = irq_get_irq_data(irq); | ||
| 1110 | if (!d) | ||
| 1111 | continue; | ||
| 1112 | |||
| 1113 | irq_type = irqd_get_trigger_type(d); | ||
| 1114 | |||
| 1115 | if (gpio_mask & BIT(virq)) { | ||
| 1116 | /* Level High */ | ||
| 1117 | |||
| 1118 | if (irq_type & IRQ_TYPE_LEVEL_HIGH) | ||
| 1119 | handle_nested_irq(irq); | ||
| 1120 | |||
| 1121 | if ((irq_type & IRQ_TYPE_EDGE_RISING) && | ||
| 1122 | !(dev->gpio_prev_state & BIT(virq))) | ||
| 1123 | handle_nested_irq(irq); | ||
| 1124 | } else { | ||
| 1125 | /* Level Low */ | ||
| 1126 | |||
| 1127 | if (irq_type & IRQ_TYPE_LEVEL_LOW) | ||
| 1128 | handle_nested_irq(irq); | ||
| 1129 | |||
| 1130 | if ((irq_type & IRQ_TYPE_EDGE_FALLING) && | ||
| 1131 | (dev->gpio_prev_state & BIT(virq))) | ||
| 1132 | handle_nested_irq(irq); | ||
| 1133 | } | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | dev->gpio_prev_state = gpio_mask; | ||
| 1137 | |||
| 1138 | exit: | ||
| 1139 | if (dev->gpio_poll) | ||
| 1140 | schedule_delayed_work(&dev->gpio_poll_worker, 10); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | |||
| 1144 | static unsigned int cp2112_gpio_irq_startup(struct irq_data *d) | ||
| 1145 | { | ||
| 1146 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
| 1147 | struct cp2112_device *dev = gpiochip_get_data(gc); | ||
| 1148 | |||
| 1149 | INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback); | ||
| 1150 | |||
| 1151 | cp2112_gpio_direction_input(gc, d->hwirq); | ||
| 1152 | |||
| 1153 | if (!dev->gpio_poll) { | ||
| 1154 | dev->gpio_poll = true; | ||
| 1155 | schedule_delayed_work(&dev->gpio_poll_worker, 0); | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | cp2112_gpio_irq_unmask(d); | ||
| 1159 | return 0; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | static void cp2112_gpio_irq_shutdown(struct irq_data *d) | ||
| 1163 | { | ||
| 1164 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
| 1165 | struct cp2112_device *dev = gpiochip_get_data(gc); | ||
| 1166 | |||
| 1167 | cancel_delayed_work_sync(&dev->gpio_poll_worker); | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | static int cp2112_gpio_irq_type(struct irq_data *d, unsigned int type) | ||
| 1171 | { | ||
| 1172 | return 0; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | static struct irq_chip cp2112_gpio_irqchip = { | ||
| 1176 | .name = "cp2112-gpio", | ||
| 1177 | .irq_startup = cp2112_gpio_irq_startup, | ||
| 1178 | .irq_shutdown = cp2112_gpio_irq_shutdown, | ||
| 1179 | .irq_ack = cp2112_gpio_irq_ack, | ||
| 1180 | .irq_mask = cp2112_gpio_irq_mask, | ||
| 1181 | .irq_unmask = cp2112_gpio_irq_unmask, | ||
| 1182 | .irq_set_type = cp2112_gpio_irq_type, | ||
| 1183 | }; | ||
| 1184 | |||
| 1185 | static int __maybe_unused cp2112_allocate_irq(struct cp2112_device *dev, | ||
| 1186 | int pin) | ||
| 1187 | { | ||
| 1188 | int ret; | ||
| 1189 | |||
| 1190 | if (dev->desc[pin]) | ||
| 1191 | return -EINVAL; | ||
| 1192 | |||
| 1193 | dev->desc[pin] = gpiochip_request_own_desc(&dev->gc, pin, | ||
| 1194 | "HID/I2C:Event"); | ||
| 1195 | if (IS_ERR(dev->desc[pin])) { | ||
| 1196 | dev_err(dev->gc.parent, "Failed to request GPIO\n"); | ||
| 1197 | return PTR_ERR(dev->desc[pin]); | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | ret = gpiochip_lock_as_irq(&dev->gc, pin); | ||
| 1201 | if (ret) { | ||
| 1202 | dev_err(dev->gc.parent, "Failed to lock GPIO as interrupt\n"); | ||
| 1203 | goto err_desc; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | ret = gpiod_to_irq(dev->desc[pin]); | ||
| 1207 | if (ret < 0) { | ||
| 1208 | dev_err(dev->gc.parent, "Failed to translate GPIO to IRQ\n"); | ||
| 1209 | goto err_lock; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | return ret; | ||
| 1213 | |||
| 1214 | err_lock: | ||
| 1215 | gpiochip_unlock_as_irq(&dev->gc, pin); | ||
| 1216 | err_desc: | ||
| 1217 | gpiochip_free_own_desc(dev->desc[pin]); | ||
| 1218 | dev->desc[pin] = NULL; | ||
| 1219 | return ret; | ||
| 1220 | } | ||
| 1221 | |||
| 1044 | static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) | 1222 | static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 1045 | { | 1223 | { |
| 1046 | struct cp2112_device *dev; | 1224 | struct cp2112_device *dev; |
| @@ -1163,8 +1341,17 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1163 | chmod_sysfs_attrs(hdev); | 1341 | chmod_sysfs_attrs(hdev); |
| 1164 | hid_hw_power(hdev, PM_HINT_NORMAL); | 1342 | hid_hw_power(hdev, PM_HINT_NORMAL); |
| 1165 | 1343 | ||
| 1344 | ret = gpiochip_irqchip_add(&dev->gc, &cp2112_gpio_irqchip, 0, | ||
| 1345 | handle_simple_irq, IRQ_TYPE_NONE); | ||
| 1346 | if (ret) { | ||
| 1347 | dev_err(dev->gc.parent, "failed to add IRQ chip\n"); | ||
| 1348 | goto err_sysfs_remove; | ||
| 1349 | } | ||
| 1350 | |||
| 1166 | return ret; | 1351 | return ret; |
| 1167 | 1352 | ||
| 1353 | err_sysfs_remove: | ||
| 1354 | sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group); | ||
| 1168 | err_gpiochip_remove: | 1355 | err_gpiochip_remove: |
| 1169 | gpiochip_remove(&dev->gc); | 1356 | gpiochip_remove(&dev->gc); |
| 1170 | err_free_i2c: | 1357 | err_free_i2c: |
| @@ -1181,10 +1368,22 @@ err_hid_stop: | |||
| 1181 | static void cp2112_remove(struct hid_device *hdev) | 1368 | static void cp2112_remove(struct hid_device *hdev) |
| 1182 | { | 1369 | { |
| 1183 | struct cp2112_device *dev = hid_get_drvdata(hdev); | 1370 | struct cp2112_device *dev = hid_get_drvdata(hdev); |
| 1371 | int i; | ||
| 1184 | 1372 | ||
| 1185 | sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group); | 1373 | sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group); |
| 1186 | gpiochip_remove(&dev->gc); | ||
| 1187 | i2c_del_adapter(&dev->adap); | 1374 | i2c_del_adapter(&dev->adap); |
| 1375 | |||
| 1376 | if (dev->gpio_poll) { | ||
| 1377 | dev->gpio_poll = false; | ||
| 1378 | cancel_delayed_work_sync(&dev->gpio_poll_worker); | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | for (i = 0; i < ARRAY_SIZE(dev->desc); i++) { | ||
| 1382 | gpiochip_unlock_as_irq(&dev->gc, i); | ||
| 1383 | gpiochip_free_own_desc(dev->desc[i]); | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | gpiochip_remove(&dev->gc); | ||
| 1188 | /* i2c_del_adapter has finished removing all i2c devices from our | 1387 | /* i2c_del_adapter has finished removing all i2c devices from our |
| 1189 | * adapter. Well behaved devices should no longer call our cp2112_xfer | 1388 | * adapter. Well behaved devices should no longer call our cp2112_xfer |
| 1190 | * and should have waited for any pending calls to finish. It has also | 1389 | * and should have waited for any pending calls to finish. It has also |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 575aa65436d1..ec277b96eaa1 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -171,6 +171,7 @@ | |||
| 171 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 | 171 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 |
| 172 | #define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b | 172 | #define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b |
| 173 | #define USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD 0x8585 | 173 | #define USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD 0x8585 |
| 174 | #define USB_DEVICE_ID_ASUSTEK_TOUCHPAD 0x0101 | ||
| 174 | 175 | ||
| 175 | #define USB_VENDOR_ID_ATEN 0x0557 | 176 | #define USB_VENDOR_ID_ATEN 0x0557 |
| 176 | #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 | 177 | #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 |
| @@ -315,8 +316,10 @@ | |||
| 315 | #define USB_VENDOR_ID_DMI 0x0c0b | 316 | #define USB_VENDOR_ID_DMI 0x0c0b |
| 316 | #define USB_DEVICE_ID_DMI_ENC 0x5fab | 317 | #define USB_DEVICE_ID_DMI_ENC 0x5fab |
| 317 | 318 | ||
| 318 | #define USB_VENDOR_ID_DRAGONRISE 0x0079 | 319 | #define USB_VENDOR_ID_DRAGONRISE 0x0079 |
| 319 | #define USB_DEVICE_ID_DRAGONRISE_WIIU 0x1800 | 320 | #define USB_DEVICE_ID_DRAGONRISE_WIIU 0x1800 |
| 321 | #define USB_DEVICE_ID_DRAGONRISE_PS3 0x1801 | ||
| 322 | #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE 0x1843 | ||
| 320 | 323 | ||
| 321 | #define USB_VENDOR_ID_DWAV 0x0eef | 324 | #define USB_VENDOR_ID_DWAV 0x0eef |
| 322 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 | 325 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 |
| @@ -718,8 +721,9 @@ | |||
| 718 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc | 721 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc |
| 719 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 0x07e2 | 722 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 0x07e2 |
| 720 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd | 723 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd |
| 724 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4 0x07e4 | ||
| 725 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2 0x07e8 | ||
| 721 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP 0x07e9 | 726 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP 0x07e9 |
| 722 | #define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de | ||
| 723 | #define USB_DEVICE_ID_MS_POWER_COVER 0x07da | 727 | #define USB_DEVICE_ID_MS_POWER_COVER 0x07da |
| 724 | 728 | ||
| 725 | #define USB_VENDOR_ID_MOJO 0x8282 | 729 | #define USB_VENDOR_ID_MOJO 0x8282 |
| @@ -903,6 +907,8 @@ | |||
| 903 | #define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 | 907 | #define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 |
| 904 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 | 908 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 |
| 905 | #define USB_DEVICE_ID_SONY_PS4_CONTROLLER 0x05c4 | 909 | #define USB_DEVICE_ID_SONY_PS4_CONTROLLER 0x05c4 |
| 910 | #define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 0x09cc | ||
| 911 | #define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0 | ||
| 906 | #define USB_DEVICE_ID_SONY_MOTION_CONTROLLER 0x03d5 | 912 | #define USB_DEVICE_ID_SONY_MOTION_CONTROLLER 0x03d5 |
| 907 | #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f | 913 | #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f |
| 908 | #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 | 914 | #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 |
| @@ -959,6 +965,9 @@ | |||
| 959 | #define USB_VENDOR_ID_THINGM 0x27b8 | 965 | #define USB_VENDOR_ID_THINGM 0x27b8 |
| 960 | #define USB_DEVICE_ID_BLINK1 0x01ed | 966 | #define USB_DEVICE_ID_BLINK1 0x01ed |
| 961 | 967 | ||
| 968 | #define USB_VENDOR_ID_THQ 0x20d6 | ||
| 969 | #define USB_DEVICE_ID_THQ_PS3_UDRAW 0xcb17 | ||
| 970 | |||
| 962 | #define USB_VENDOR_ID_THRUSTMASTER 0x044f | 971 | #define USB_VENDOR_ID_THRUSTMASTER 0x044f |
| 963 | 972 | ||
| 964 | #define USB_VENDOR_ID_TIVO 0x150a | 973 | #define USB_VENDOR_ID_TIVO 0x150a |
| @@ -1034,6 +1043,10 @@ | |||
| 1034 | #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH 0x0500 | 1043 | #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH 0x0500 |
| 1035 | #define USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET 0x0502 | 1044 | #define USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET 0x0502 |
| 1036 | 1045 | ||
| 1046 | #define USB_VENDOR_ID_WEIDA 0x2575 | ||
| 1047 | #define USB_DEVICE_ID_WEIDA_8752 0xC300 | ||
| 1048 | #define USB_DEVICE_ID_WEIDA_8755 0xC301 | ||
| 1049 | |||
| 1037 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | 1050 | #define USB_VENDOR_ID_WISEGROUP 0x0925 |
| 1038 | #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 | 1051 | #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 |
| 1039 | #define USB_DEVICE_ID_SUPER_JOY_BOX_3 0x8888 | 1052 | #define USB_DEVICE_ID_SUPER_JOY_BOX_3 0x8888 |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index fb9ace1cef8b..d05f903c7614 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
| @@ -253,6 +253,7 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) | |||
| 253 | case ABS_RX: | 253 | case ABS_RX: |
| 254 | case ABS_RY: | 254 | case ABS_RY: |
| 255 | case ABS_RZ: | 255 | case ABS_RZ: |
| 256 | case ABS_WHEEL: | ||
| 256 | case ABS_TILT_X: | 257 | case ABS_TILT_X: |
| 257 | case ABS_TILT_Y: | 258 | case ABS_TILT_Y: |
| 258 | if (field->unit == 0x14) { /* If degrees */ | 259 | if (field->unit == 0x14) { /* If degrees */ |
| @@ -1468,6 +1469,31 @@ static void hidinput_cleanup_hidinput(struct hid_device *hid, | |||
| 1468 | kfree(hidinput); | 1469 | kfree(hidinput); |
| 1469 | } | 1470 | } |
| 1470 | 1471 | ||
| 1472 | static struct hid_input *hidinput_match(struct hid_report *report) | ||
| 1473 | { | ||
| 1474 | struct hid_device *hid = report->device; | ||
| 1475 | struct hid_input *hidinput; | ||
| 1476 | |||
| 1477 | list_for_each_entry(hidinput, &hid->inputs, list) { | ||
| 1478 | if (hidinput->report && | ||
| 1479 | hidinput->report->id == report->id) | ||
| 1480 | return hidinput; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | return NULL; | ||
| 1484 | } | ||
| 1485 | |||
| 1486 | static inline void hidinput_configure_usages(struct hid_input *hidinput, | ||
| 1487 | struct hid_report *report) | ||
| 1488 | { | ||
| 1489 | int i, j; | ||
| 1490 | |||
| 1491 | for (i = 0; i < report->maxfield; i++) | ||
| 1492 | for (j = 0; j < report->field[i]->maxusage; j++) | ||
| 1493 | hidinput_configure_usage(hidinput, report->field[i], | ||
| 1494 | report->field[i]->usage + j); | ||
| 1495 | } | ||
| 1496 | |||
| 1471 | /* | 1497 | /* |
| 1472 | * Register the input device; print a message. | 1498 | * Register the input device; print a message. |
| 1473 | * Configure the input layer interface | 1499 | * Configure the input layer interface |
| @@ -1478,8 +1504,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
| 1478 | { | 1504 | { |
| 1479 | struct hid_driver *drv = hid->driver; | 1505 | struct hid_driver *drv = hid->driver; |
| 1480 | struct hid_report *report; | 1506 | struct hid_report *report; |
| 1481 | struct hid_input *hidinput = NULL; | 1507 | struct hid_input *next, *hidinput = NULL; |
| 1482 | int i, j, k; | 1508 | int i, k; |
| 1483 | 1509 | ||
| 1484 | INIT_LIST_HEAD(&hid->inputs); | 1510 | INIT_LIST_HEAD(&hid->inputs); |
| 1485 | INIT_WORK(&hid->led_work, hidinput_led_worker); | 1511 | INIT_WORK(&hid->led_work, hidinput_led_worker); |
| @@ -1509,43 +1535,40 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
| 1509 | if (!report->maxfield) | 1535 | if (!report->maxfield) |
| 1510 | continue; | 1536 | continue; |
| 1511 | 1537 | ||
| 1538 | /* | ||
| 1539 | * Find the previous hidinput report attached | ||
| 1540 | * to this report id. | ||
| 1541 | */ | ||
| 1542 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) | ||
| 1543 | hidinput = hidinput_match(report); | ||
| 1544 | |||
| 1512 | if (!hidinput) { | 1545 | if (!hidinput) { |
| 1513 | hidinput = hidinput_allocate(hid); | 1546 | hidinput = hidinput_allocate(hid); |
| 1514 | if (!hidinput) | 1547 | if (!hidinput) |
| 1515 | goto out_unwind; | 1548 | goto out_unwind; |
| 1516 | } | 1549 | } |
| 1517 | 1550 | ||
| 1518 | for (i = 0; i < report->maxfield; i++) | 1551 | hidinput_configure_usages(hidinput, report); |
| 1519 | for (j = 0; j < report->field[i]->maxusage; j++) | ||
| 1520 | hidinput_configure_usage(hidinput, report->field[i], | ||
| 1521 | report->field[i]->usage + j); | ||
| 1522 | |||
| 1523 | if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) && | ||
| 1524 | !hidinput_has_been_populated(hidinput)) | ||
| 1525 | continue; | ||
| 1526 | 1552 | ||
| 1527 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) { | 1553 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) |
| 1528 | /* This will leave hidinput NULL, so that it | ||
| 1529 | * allocates another one if we have more inputs on | ||
| 1530 | * the same interface. Some devices (e.g. Happ's | ||
| 1531 | * UGCI) cram a lot of unrelated inputs into the | ||
| 1532 | * same interface. */ | ||
| 1533 | hidinput->report = report; | 1554 | hidinput->report = report; |
| 1534 | if (drv->input_configured && | ||
| 1535 | drv->input_configured(hid, hidinput)) | ||
| 1536 | goto out_cleanup; | ||
| 1537 | if (input_register_device(hidinput->input)) | ||
| 1538 | goto out_cleanup; | ||
| 1539 | hidinput = NULL; | ||
| 1540 | } | ||
| 1541 | } | 1555 | } |
| 1542 | } | 1556 | } |
| 1543 | 1557 | ||
| 1544 | if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) && | 1558 | list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { |
| 1545 | !hidinput_has_been_populated(hidinput)) { | 1559 | if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) && |
| 1546 | /* no need to register an input device not populated */ | 1560 | !hidinput_has_been_populated(hidinput)) { |
| 1547 | hidinput_cleanup_hidinput(hid, hidinput); | 1561 | /* no need to register an input device not populated */ |
| 1548 | hidinput = NULL; | 1562 | hidinput_cleanup_hidinput(hid, hidinput); |
| 1563 | continue; | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | if (drv->input_configured && | ||
| 1567 | drv->input_configured(hid, hidinput)) | ||
| 1568 | goto out_unwind; | ||
| 1569 | if (input_register_device(hidinput->input)) | ||
| 1570 | goto out_unwind; | ||
| 1571 | hidinput->registered = true; | ||
| 1549 | } | 1572 | } |
| 1550 | 1573 | ||
| 1551 | if (list_empty(&hid->inputs)) { | 1574 | if (list_empty(&hid->inputs)) { |
| @@ -1553,20 +1576,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
| 1553 | goto out_unwind; | 1576 | goto out_unwind; |
| 1554 | } | 1577 | } |
| 1555 | 1578 | ||
| 1556 | if (hidinput) { | ||
| 1557 | if (drv->input_configured && | ||
| 1558 | drv->input_configured(hid, hidinput)) | ||
| 1559 | goto out_cleanup; | ||
| 1560 | if (input_register_device(hidinput->input)) | ||
| 1561 | goto out_cleanup; | ||
| 1562 | } | ||
| 1563 | |||
| 1564 | return 0; | 1579 | return 0; |
| 1565 | 1580 | ||
| 1566 | out_cleanup: | ||
| 1567 | list_del(&hidinput->list); | ||
| 1568 | input_free_device(hidinput->input); | ||
| 1569 | kfree(hidinput); | ||
| 1570 | out_unwind: | 1581 | out_unwind: |
| 1571 | /* unwind the ones we already registered */ | 1582 | /* unwind the ones we already registered */ |
| 1572 | hidinput_disconnect(hid); | 1583 | hidinput_disconnect(hid); |
| @@ -1583,7 +1594,10 @@ void hidinput_disconnect(struct hid_device *hid) | |||
| 1583 | 1594 | ||
| 1584 | list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { | 1595 | list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { |
| 1585 | list_del(&hidinput->list); | 1596 | list_del(&hidinput->list); |
| 1586 | input_unregister_device(hidinput->input); | 1597 | if (hidinput->registered) |
| 1598 | input_unregister_device(hidinput->input); | ||
| 1599 | else | ||
| 1600 | input_free_device(hidinput->input); | ||
| 1587 | kfree(hidinput); | 1601 | kfree(hidinput); |
| 1588 | } | 1602 | } |
| 1589 | 1603 | ||
diff --git a/drivers/hid/hid-mf.c b/drivers/hid/hid-mf.c new file mode 100644 index 000000000000..d9090765a6e5 --- /dev/null +++ b/drivers/hid/hid-mf.c | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | /* | ||
| 2 | * Force feedback support for Mayflash game controller adapters. | ||
| 3 | * | ||
| 4 | * These devices are manufactured by Mayflash but identify themselves | ||
| 5 | * using the vendor ID of DragonRise Inc. | ||
| 6 | * | ||
| 7 | * Tested with: | ||
| 8 | * 0079:1801 "DragonRise Inc. Mayflash PS3 Game Controller Adapter" | ||
| 9 | * | ||
| 10 | * The following adapters probably work too, but need to be tested: | ||
| 11 | * 0079:1800 "DragonRise Inc. Mayflash WIIU Game Controller Adapter" | ||
| 12 | * 0079:1843 "DragonRise Inc. Mayflash GameCube Game Controller Adapter" | ||
| 13 | * | ||
| 14 | * Copyright (c) 2016 Marcel Hasler <mahasler@gmail.com> | ||
| 15 | */ | ||
| 16 | |||
| 17 | /* | ||
| 18 | * This program is free software; you can redistribute it and/or modify | ||
| 19 | * it under the terms of the GNU General Public License as published by | ||
| 20 | * the Free Software Foundation; either version 2 of the License, or | ||
| 21 | * (at your option) any later version. | ||
| 22 | * | ||
| 23 | * This program is distributed in the hope that it will be useful, | ||
| 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 26 | * GNU General Public License for more details. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include <linux/input.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <linux/hid.h> | ||
| 32 | #include <linux/module.h> | ||
| 33 | |||
| 34 | #include "hid-ids.h" | ||
| 35 | |||
| 36 | struct mf_device { | ||
| 37 | struct hid_report *report; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int mf_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
| 41 | { | ||
| 42 | struct hid_device *hid = input_get_drvdata(dev); | ||
| 43 | struct mf_device *mf = data; | ||
| 44 | int strong, weak; | ||
| 45 | |||
| 46 | strong = effect->u.rumble.strong_magnitude; | ||
| 47 | weak = effect->u.rumble.weak_magnitude; | ||
| 48 | |||
| 49 | dbg_hid("Called with 0x%04x 0x%04x.\n", strong, weak); | ||
| 50 | |||
| 51 | strong = strong * 0xff / 0xffff; | ||
| 52 | weak = weak * 0xff / 0xffff; | ||
| 53 | |||
| 54 | dbg_hid("Running with 0x%02x 0x%02x.\n", strong, weak); | ||
| 55 | |||
| 56 | mf->report->field[0]->value[0] = weak; | ||
| 57 | mf->report->field[0]->value[1] = strong; | ||
| 58 | hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT); | ||
| 59 | |||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | static int mf_init(struct hid_device *hid) | ||
| 64 | { | ||
| 65 | struct mf_device *mf; | ||
| 66 | |||
| 67 | struct list_head *report_list = | ||
| 68 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 69 | |||
| 70 | struct list_head *report_ptr; | ||
| 71 | struct hid_report *report; | ||
| 72 | |||
| 73 | struct list_head *input_ptr = &hid->inputs; | ||
| 74 | struct hid_input *input; | ||
| 75 | |||
| 76 | struct input_dev *dev; | ||
| 77 | |||
| 78 | int error; | ||
| 79 | |||
| 80 | /* Setup each of the four inputs */ | ||
| 81 | list_for_each(report_ptr, report_list) { | ||
| 82 | report = list_entry(report_ptr, struct hid_report, list); | ||
| 83 | |||
| 84 | if (report->maxfield < 1 || report->field[0]->report_count < 2) { | ||
| 85 | hid_err(hid, "Invalid report, this should never happen!\n"); | ||
| 86 | return -ENODEV; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (list_is_last(input_ptr, &hid->inputs)) { | ||
| 90 | hid_err(hid, "Missing input, this should never happen!\n"); | ||
| 91 | return -ENODEV; | ||
| 92 | } | ||
| 93 | |||
| 94 | input_ptr = input_ptr->next; | ||
| 95 | input = list_entry(input_ptr, struct hid_input, list); | ||
| 96 | |||
| 97 | mf = kzalloc(sizeof(struct mf_device), GFP_KERNEL); | ||
| 98 | if (!mf) | ||
| 99 | return -ENOMEM; | ||
| 100 | |||
| 101 | dev = input->input; | ||
| 102 | set_bit(FF_RUMBLE, dev->ffbit); | ||
| 103 | |||
| 104 | error = input_ff_create_memless(dev, mf, mf_play); | ||
| 105 | if (error) { | ||
| 106 | kfree(mf); | ||
| 107 | return error; | ||
| 108 | } | ||
| 109 | |||
| 110 | mf->report = report; | ||
| 111 | mf->report->field[0]->value[0] = 0x00; | ||
| 112 | mf->report->field[0]->value[1] = 0x00; | ||
| 113 | hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT); | ||
| 114 | } | ||
| 115 | |||
| 116 | hid_info(hid, "Force feedback for HJZ Mayflash game controller " | ||
| 117 | "adapters by Marcel Hasler <mahasler@gmail.com>\n"); | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int mf_probe(struct hid_device *hid, const struct hid_device_id *id) | ||
| 123 | { | ||
| 124 | int error; | ||
| 125 | |||
| 126 | dev_dbg(&hid->dev, "Mayflash HID hardware probe...\n"); | ||
| 127 | |||
| 128 | /* Split device into four inputs */ | ||
| 129 | hid->quirks |= HID_QUIRK_MULTI_INPUT; | ||
| 130 | |||
| 131 | error = hid_parse(hid); | ||
| 132 | if (error) { | ||
| 133 | hid_err(hid, "HID parse failed.\n"); | ||
| 134 | return error; | ||
| 135 | } | ||
| 136 | |||
| 137 | error = hid_hw_start(hid, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | ||
| 138 | if (error) { | ||
| 139 | hid_err(hid, "HID hw start failed\n"); | ||
| 140 | return error; | ||
| 141 | } | ||
| 142 | |||
| 143 | error = mf_init(hid); | ||
| 144 | if (error) { | ||
| 145 | hid_err(hid, "Force feedback init failed.\n"); | ||
| 146 | hid_hw_stop(hid); | ||
| 147 | return error; | ||
| 148 | } | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static const struct hid_device_id mf_devices[] = { | ||
| 154 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), }, | ||
| 155 | { } | ||
| 156 | }; | ||
| 157 | MODULE_DEVICE_TABLE(hid, mf_devices); | ||
| 158 | |||
| 159 | static struct hid_driver mf_driver = { | ||
| 160 | .name = "hid_mf", | ||
| 161 | .id_table = mf_devices, | ||
| 162 | .probe = mf_probe, | ||
| 163 | }; | ||
| 164 | module_hid_driver(mf_driver); | ||
| 165 | |||
| 166 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index c6cd392e9f99..74b7b84a0420 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c | |||
| @@ -280,9 +280,11 @@ static const struct hid_device_id ms_devices[] = { | |||
| 280 | .driver_data = MS_HIDINPUT }, | 280 | .driver_data = MS_HIDINPUT }, |
| 281 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP), | 281 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP), |
| 282 | .driver_data = MS_HIDINPUT }, | 282 | .driver_data = MS_HIDINPUT }, |
| 283 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP), | 283 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4), |
| 284 | .driver_data = MS_HIDINPUT }, | ||
| 285 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2), | ||
| 284 | .driver_data = MS_HIDINPUT }, | 286 | .driver_data = MS_HIDINPUT }, |
| 285 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), | 287 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP), |
| 286 | .driver_data = MS_HIDINPUT }, | 288 | .driver_data = MS_HIDINPUT }, |
| 287 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), | 289 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), |
| 288 | .driver_data = MS_HIDINPUT }, | 290 | .driver_data = MS_HIDINPUT }, |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index fb6f1f447279..6dca66806844 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -108,6 +108,7 @@ struct mt_device { | |||
| 108 | int cc_value_index; /* contact count value index in the field */ | 108 | int cc_value_index; /* contact count value index in the field */ |
| 109 | unsigned last_slot_field; /* the last field of a slot */ | 109 | unsigned last_slot_field; /* the last field of a slot */ |
| 110 | unsigned mt_report_id; /* the report ID of the multitouch device */ | 110 | unsigned mt_report_id; /* the report ID of the multitouch device */ |
| 111 | unsigned long initial_quirks; /* initial quirks state */ | ||
| 111 | __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ | 112 | __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ |
| 112 | __s16 inputmode_index; /* InputMode HID feature index in the report */ | 113 | __s16 inputmode_index; /* InputMode HID feature index in the report */ |
| 113 | __s16 maxcontact_report_id; /* Maximum Contact Number HID feature, | 114 | __s16 maxcontact_report_id; /* Maximum Contact Number HID feature, |
| @@ -318,13 +319,10 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) | |||
| 318 | u8 *buf; | 319 | u8 *buf; |
| 319 | 320 | ||
| 320 | /* | 321 | /* |
| 321 | * Only fetch the feature report if initial reports are not already | 322 | * Do not fetch the feature report if the device has been explicitly |
| 322 | * been retrieved. Currently this is only done for Windows 8 touch | 323 | * marked as non-capable. |
| 323 | * devices. | ||
| 324 | */ | 324 | */ |
| 325 | if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS)) | 325 | if (td->initial_quirks & HID_QUIRK_NO_INIT_REPORTS) |
| 326 | return; | ||
| 327 | if (td->mtclass.name != MT_CLS_WIN_8) | ||
| 328 | return; | 326 | return; |
| 329 | 327 | ||
| 330 | buf = hid_alloc_report_buf(report, GFP_KERNEL); | 328 | buf = hid_alloc_report_buf(report, GFP_KERNEL); |
| @@ -567,6 +565,14 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 567 | 565 | ||
| 568 | case HID_UP_BUTTON: | 566 | case HID_UP_BUTTON: |
| 569 | code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE); | 567 | code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE); |
| 568 | /* | ||
| 569 | * MS PTP spec says that external buttons left and right have | ||
| 570 | * usages 2 and 3. | ||
| 571 | */ | ||
| 572 | if (cls->name == MT_CLS_WIN_8 && | ||
| 573 | field->application == HID_DG_TOUCHPAD && | ||
| 574 | (usage->hid & HID_USAGE) > 1) | ||
| 575 | code--; | ||
| 570 | hid_map_usage(hi, usage, bit, max, EV_KEY, code); | 576 | hid_map_usage(hi, usage, bit, max, EV_KEY, code); |
| 571 | input_set_capability(hi->input, EV_KEY, code); | 577 | input_set_capability(hi->input, EV_KEY, code); |
| 572 | return 1; | 578 | return 1; |
| @@ -842,7 +848,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 842 | if (!td->mtclass.export_all_inputs && | 848 | if (!td->mtclass.export_all_inputs && |
| 843 | field->application != HID_DG_TOUCHSCREEN && | 849 | field->application != HID_DG_TOUCHSCREEN && |
| 844 | field->application != HID_DG_PEN && | 850 | field->application != HID_DG_PEN && |
| 845 | field->application != HID_DG_TOUCHPAD) | 851 | field->application != HID_DG_TOUCHPAD && |
| 852 | field->application != HID_GD_KEYBOARD && | ||
| 853 | field->application != HID_CP_CONSUMER_CONTROL) | ||
| 846 | return -1; | 854 | return -1; |
| 847 | 855 | ||
| 848 | /* | 856 | /* |
| @@ -1083,36 +1091,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1083 | } | 1091 | } |
| 1084 | } | 1092 | } |
| 1085 | 1093 | ||
| 1086 | /* This allows the driver to correctly support devices | ||
| 1087 | * that emit events over several HID messages. | ||
| 1088 | */ | ||
| 1089 | hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; | ||
| 1090 | |||
| 1091 | /* | ||
| 1092 | * This allows the driver to handle different input sensors | ||
| 1093 | * that emits events through different reports on the same HID | ||
| 1094 | * device. | ||
| 1095 | */ | ||
| 1096 | hdev->quirks |= HID_QUIRK_MULTI_INPUT; | ||
| 1097 | hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT; | ||
| 1098 | |||
| 1099 | /* | ||
| 1100 | * Handle special quirks for Windows 8 certified devices. | ||
| 1101 | */ | ||
| 1102 | if (id->group == HID_GROUP_MULTITOUCH_WIN_8) | ||
| 1103 | /* | ||
| 1104 | * Some multitouch screens do not like to be polled for input | ||
| 1105 | * reports. Fortunately, the Win8 spec says that all touches | ||
| 1106 | * should be sent during each report, making the initialization | ||
| 1107 | * of input reports unnecessary. | ||
| 1108 | * | ||
| 1109 | * In addition some touchpads do not behave well if we read | ||
| 1110 | * all feature reports from them. Instead we prevent | ||
| 1111 | * initial report fetching and then selectively fetch each | ||
| 1112 | * report we are interested in. | ||
| 1113 | */ | ||
| 1114 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; | ||
| 1115 | |||
| 1116 | td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL); | 1094 | td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL); |
| 1117 | if (!td) { | 1095 | if (!td) { |
| 1118 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); | 1096 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); |
| @@ -1136,6 +1114,39 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1136 | if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) | 1114 | if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) |
| 1137 | td->serial_maybe = true; | 1115 | td->serial_maybe = true; |
| 1138 | 1116 | ||
| 1117 | /* | ||
| 1118 | * Store the initial quirk state | ||
| 1119 | */ | ||
| 1120 | td->initial_quirks = hdev->quirks; | ||
| 1121 | |||
| 1122 | /* This allows the driver to correctly support devices | ||
| 1123 | * that emit events over several HID messages. | ||
| 1124 | */ | ||
| 1125 | hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; | ||
| 1126 | |||
| 1127 | /* | ||
| 1128 | * This allows the driver to handle different input sensors | ||
| 1129 | * that emits events through different reports on the same HID | ||
| 1130 | * device. | ||
| 1131 | */ | ||
| 1132 | hdev->quirks |= HID_QUIRK_MULTI_INPUT; | ||
| 1133 | hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT; | ||
| 1134 | |||
| 1135 | /* | ||
| 1136 | * Some multitouch screens do not like to be polled for input | ||
| 1137 | * reports. Fortunately, the Win8 spec says that all touches | ||
| 1138 | * should be sent during each report, making the initialization | ||
| 1139 | * of input reports unnecessary. For Win7 devices, well, let's hope | ||
| 1140 | * they will still be happy (this is only be a problem if a touch | ||
| 1141 | * was already there while probing the device). | ||
| 1142 | * | ||
| 1143 | * In addition some touchpads do not behave well if we read | ||
| 1144 | * all feature reports from them. Instead we prevent | ||
| 1145 | * initial report fetching and then selectively fetch each | ||
| 1146 | * report we are interested in. | ||
| 1147 | */ | ||
| 1148 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; | ||
| 1149 | |||
| 1139 | ret = hid_parse(hdev); | 1150 | ret = hid_parse(hdev); |
| 1140 | if (ret != 0) | 1151 | if (ret != 0) |
| 1141 | return ret; | 1152 | return ret; |
| @@ -1204,8 +1215,11 @@ static int mt_resume(struct hid_device *hdev) | |||
| 1204 | 1215 | ||
| 1205 | static void mt_remove(struct hid_device *hdev) | 1216 | static void mt_remove(struct hid_device *hdev) |
| 1206 | { | 1217 | { |
| 1218 | struct mt_device *td = hid_get_drvdata(hdev); | ||
| 1219 | |||
| 1207 | sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); | 1220 | sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); |
| 1208 | hid_hw_stop(hdev); | 1221 | hid_hw_stop(hdev); |
| 1222 | hdev->quirks = td->initial_quirks; | ||
| 1209 | } | 1223 | } |
| 1210 | 1224 | ||
| 1211 | /* | 1225 | /* |
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 60875625cbdf..5c925228847c 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c | |||
| @@ -795,6 +795,12 @@ static const struct hid_device_id sensor_hub_devices[] = { | |||
| 795 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT, | 795 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT, |
| 796 | USB_DEVICE_ID_MS_TYPE_COVER_2), | 796 | USB_DEVICE_ID_MS_TYPE_COVER_2), |
| 797 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, | 797 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, |
| 798 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT, | ||
| 799 | 0x07bd), /* Microsoft Surface 3 */ | ||
| 800 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, | ||
| 801 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROCHIP, | ||
| 802 | 0x0f01), /* MM7150 */ | ||
| 803 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, | ||
| 798 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0, | 804 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0, |
| 799 | USB_DEVICE_ID_STM_HID_SENSOR), | 805 | USB_DEVICE_ID_STM_HID_SENSOR), |
| 800 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, | 806 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, |
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index b0bb99a821bd..7687c0875395 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
| @@ -36,6 +36,8 @@ | |||
| 36 | #include <linux/list.h> | 36 | #include <linux/list.h> |
| 37 | #include <linux/idr.h> | 37 | #include <linux/idr.h> |
| 38 | #include <linux/input/mt.h> | 38 | #include <linux/input/mt.h> |
| 39 | #include <linux/crc32.h> | ||
| 40 | #include <asm/unaligned.h> | ||
| 39 | 41 | ||
| 40 | #include "hid-ids.h" | 42 | #include "hid-ids.h" |
| 41 | 43 | ||
| @@ -374,7 +376,7 @@ static u8 dualshock4_usb_rdesc[] = { | |||
| 374 | 0x65, 0x00, /* Unit, */ | 376 | 0x65, 0x00, /* Unit, */ |
| 375 | 0x05, 0x09, /* Usage Page (Button), */ | 377 | 0x05, 0x09, /* Usage Page (Button), */ |
| 376 | 0x19, 0x01, /* Usage Minimum (01h), */ | 378 | 0x19, 0x01, /* Usage Minimum (01h), */ |
| 377 | 0x29, 0x0E, /* Usage Maximum (0Eh), */ | 379 | 0x29, 0x0D, /* Usage Maximum (0Dh), */ |
| 378 | 0x15, 0x00, /* Logical Minimum (0), */ | 380 | 0x15, 0x00, /* Logical Minimum (0), */ |
| 379 | 0x25, 0x01, /* Logical Maximum (1), */ | 381 | 0x25, 0x01, /* Logical Maximum (1), */ |
| 380 | 0x75, 0x01, /* Report Size (1), */ | 382 | 0x75, 0x01, /* Report Size (1), */ |
| @@ -403,14 +405,14 @@ static u8 dualshock4_usb_rdesc[] = { | |||
| 403 | 0x19, 0x40, /* Usage Minimum (40h), */ | 405 | 0x19, 0x40, /* Usage Minimum (40h), */ |
| 404 | 0x29, 0x42, /* Usage Maximum (42h), */ | 406 | 0x29, 0x42, /* Usage Maximum (42h), */ |
| 405 | 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ | 407 | 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ |
| 406 | 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ | 408 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ |
| 407 | 0x75, 0x10, /* Report Size (16), */ | 409 | 0x75, 0x10, /* Report Size (16), */ |
| 408 | 0x95, 0x03, /* Report Count (3), */ | 410 | 0x95, 0x03, /* Report Count (3), */ |
| 409 | 0x81, 0x02, /* Input (Variable), */ | 411 | 0x81, 0x02, /* Input (Variable), */ |
| 410 | 0x19, 0x43, /* Usage Minimum (43h), */ | 412 | 0x19, 0x43, /* Usage Minimum (43h), */ |
| 411 | 0x29, 0x45, /* Usage Maximum (45h), */ | 413 | 0x29, 0x45, /* Usage Maximum (45h), */ |
| 412 | 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ | 414 | 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ |
| 413 | 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ | 415 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ |
| 414 | 0x95, 0x03, /* Report Count (3), */ | 416 | 0x95, 0x03, /* Report Count (3), */ |
| 415 | 0x81, 0x02, /* Input (Variable), */ | 417 | 0x81, 0x02, /* Input (Variable), */ |
| 416 | 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | 418 | 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ |
| @@ -687,7 +689,7 @@ static u8 dualshock4_bt_rdesc[] = { | |||
| 687 | 0x81, 0x42, /* Input (Variable, Null State), */ | 689 | 0x81, 0x42, /* Input (Variable, Null State), */ |
| 688 | 0x05, 0x09, /* Usage Page (Button), */ | 690 | 0x05, 0x09, /* Usage Page (Button), */ |
| 689 | 0x19, 0x01, /* Usage Minimum (01h), */ | 691 | 0x19, 0x01, /* Usage Minimum (01h), */ |
| 690 | 0x29, 0x0E, /* Usage Maximum (0Eh), */ | 692 | 0x29, 0x0D, /* Usage Maximum (0Dh), */ |
| 691 | 0x15, 0x00, /* Logical Minimum (0), */ | 693 | 0x15, 0x00, /* Logical Minimum (0), */ |
| 692 | 0x25, 0x01, /* Logical Maximum (1), */ | 694 | 0x25, 0x01, /* Logical Maximum (1), */ |
| 693 | 0x75, 0x01, /* Report Size (1), */ | 695 | 0x75, 0x01, /* Report Size (1), */ |
| @@ -712,14 +714,14 @@ static u8 dualshock4_bt_rdesc[] = { | |||
| 712 | 0x19, 0x40, /* Usage Minimum (40h), */ | 714 | 0x19, 0x40, /* Usage Minimum (40h), */ |
| 713 | 0x29, 0x42, /* Usage Maximum (42h), */ | 715 | 0x29, 0x42, /* Usage Maximum (42h), */ |
| 714 | 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ | 716 | 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ |
| 715 | 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ | 717 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ |
| 716 | 0x75, 0x10, /* Report Size (16), */ | 718 | 0x75, 0x10, /* Report Size (16), */ |
| 717 | 0x95, 0x03, /* Report Count (3), */ | 719 | 0x95, 0x03, /* Report Count (3), */ |
| 718 | 0x81, 0x02, /* Input (Variable), */ | 720 | 0x81, 0x02, /* Input (Variable), */ |
| 719 | 0x19, 0x43, /* Usage Minimum (43h), */ | 721 | 0x19, 0x43, /* Usage Minimum (43h), */ |
| 720 | 0x29, 0x45, /* Usage Maximum (45h), */ | 722 | 0x29, 0x45, /* Usage Maximum (45h), */ |
| 721 | 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ | 723 | 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ |
| 722 | 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ | 724 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ |
| 723 | 0x95, 0x03, /* Report Count (3), */ | 725 | 0x95, 0x03, /* Report Count (3), */ |
| 724 | 0x81, 0x02, /* Input (Variable), */ | 726 | 0x81, 0x02, /* Input (Variable), */ |
| 725 | 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | 727 | 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ |
| @@ -975,6 +977,32 @@ static const unsigned int buzz_keymap[] = { | |||
| 975 | [20] = BTN_TRIGGER_HAPPY20, | 977 | [20] = BTN_TRIGGER_HAPPY20, |
| 976 | }; | 978 | }; |
| 977 | 979 | ||
| 980 | static const unsigned int ds4_absmap[] = { | ||
| 981 | [0x30] = ABS_X, | ||
| 982 | [0x31] = ABS_Y, | ||
| 983 | [0x32] = ABS_RX, /* right stick X */ | ||
| 984 | [0x33] = ABS_Z, /* L2 */ | ||
| 985 | [0x34] = ABS_RZ, /* R2 */ | ||
| 986 | [0x35] = ABS_RY, /* right stick Y */ | ||
| 987 | }; | ||
| 988 | |||
| 989 | static const unsigned int ds4_keymap[] = { | ||
| 990 | [0x1] = BTN_WEST, /* Square */ | ||
| 991 | [0x2] = BTN_SOUTH, /* Cross */ | ||
| 992 | [0x3] = BTN_EAST, /* Circle */ | ||
| 993 | [0x4] = BTN_NORTH, /* Triangle */ | ||
| 994 | [0x5] = BTN_TL, /* L1 */ | ||
| 995 | [0x6] = BTN_TR, /* R1 */ | ||
| 996 | [0x7] = BTN_TL2, /* L2 */ | ||
| 997 | [0x8] = BTN_TR2, /* R2 */ | ||
| 998 | [0x9] = BTN_SELECT, /* Share */ | ||
| 999 | [0xa] = BTN_START, /* Options */ | ||
| 1000 | [0xb] = BTN_THUMBL, /* L3 */ | ||
| 1001 | [0xc] = BTN_THUMBR, /* R3 */ | ||
| 1002 | [0xd] = BTN_MODE, /* PS */ | ||
| 1003 | }; | ||
| 1004 | |||
| 1005 | |||
| 978 | static enum power_supply_property sony_battery_props[] = { | 1006 | static enum power_supply_property sony_battery_props[] = { |
| 979 | POWER_SUPPLY_PROP_PRESENT, | 1007 | POWER_SUPPLY_PROP_PRESENT, |
| 980 | POWER_SUPPLY_PROP_CAPACITY, | 1008 | POWER_SUPPLY_PROP_CAPACITY, |
| @@ -1019,14 +1047,24 @@ struct motion_output_report_02 { | |||
| 1019 | u8 rumble; | 1047 | u8 rumble; |
| 1020 | }; | 1048 | }; |
| 1021 | 1049 | ||
| 1022 | #define DS4_REPORT_0x02_SIZE 37 | 1050 | #define DS4_FEATURE_REPORT_0x02_SIZE 37 |
| 1023 | #define DS4_REPORT_0x05_SIZE 32 | 1051 | #define DS4_FEATURE_REPORT_0x81_SIZE 7 |
| 1024 | #define DS4_REPORT_0x11_SIZE 78 | 1052 | #define DS4_INPUT_REPORT_0x11_SIZE 78 |
| 1025 | #define DS4_REPORT_0x81_SIZE 7 | 1053 | #define DS4_OUTPUT_REPORT_0x05_SIZE 32 |
| 1054 | #define DS4_OUTPUT_REPORT_0x11_SIZE 78 | ||
| 1026 | #define SIXAXIS_REPORT_0xF2_SIZE 17 | 1055 | #define SIXAXIS_REPORT_0xF2_SIZE 17 |
| 1027 | #define SIXAXIS_REPORT_0xF5_SIZE 8 | 1056 | #define SIXAXIS_REPORT_0xF5_SIZE 8 |
| 1028 | #define MOTION_REPORT_0x02_SIZE 49 | 1057 | #define MOTION_REPORT_0x02_SIZE 49 |
| 1029 | 1058 | ||
| 1059 | /* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an | ||
| 1060 | * additional +2. | ||
| 1061 | */ | ||
| 1062 | #define DS4_INPUT_REPORT_BUTTON_OFFSET 5 | ||
| 1063 | #define DS4_INPUT_REPORT_BATTERY_OFFSET 30 | ||
| 1064 | #define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33 | ||
| 1065 | |||
| 1066 | #define DS4_TOUCHPAD_SUFFIX " Touchpad" | ||
| 1067 | |||
| 1030 | static DEFINE_SPINLOCK(sony_dev_list_lock); | 1068 | static DEFINE_SPINLOCK(sony_dev_list_lock); |
| 1031 | static LIST_HEAD(sony_device_list); | 1069 | static LIST_HEAD(sony_device_list); |
| 1032 | static DEFINE_IDA(sony_device_id_allocator); | 1070 | static DEFINE_IDA(sony_device_id_allocator); |
| @@ -1035,6 +1073,7 @@ struct sony_sc { | |||
| 1035 | spinlock_t lock; | 1073 | spinlock_t lock; |
| 1036 | struct list_head list_node; | 1074 | struct list_head list_node; |
| 1037 | struct hid_device *hdev; | 1075 | struct hid_device *hdev; |
| 1076 | struct input_dev *touchpad; | ||
| 1038 | struct led_classdev *leds[MAX_LEDS]; | 1077 | struct led_classdev *leds[MAX_LEDS]; |
| 1039 | unsigned long quirks; | 1078 | unsigned long quirks; |
| 1040 | struct work_struct state_worker; | 1079 | struct work_struct state_worker; |
| @@ -1130,6 +1169,37 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 1130 | return 1; | 1169 | return 1; |
| 1131 | } | 1170 | } |
| 1132 | 1171 | ||
| 1172 | static int ds4_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
| 1173 | struct hid_field *field, struct hid_usage *usage, | ||
| 1174 | unsigned long **bit, int *max) | ||
| 1175 | { | ||
| 1176 | if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { | ||
| 1177 | unsigned int key = usage->hid & HID_USAGE; | ||
| 1178 | |||
| 1179 | if (key >= ARRAY_SIZE(ds4_keymap)) | ||
| 1180 | return -1; | ||
| 1181 | |||
| 1182 | key = ds4_keymap[key]; | ||
| 1183 | hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); | ||
| 1184 | return 1; | ||
| 1185 | } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { | ||
| 1186 | unsigned int abs = usage->hid & HID_USAGE; | ||
| 1187 | |||
| 1188 | /* Let the HID parser deal with the HAT. */ | ||
| 1189 | if (usage->hid == HID_GD_HATSWITCH) | ||
| 1190 | return 0; | ||
| 1191 | |||
| 1192 | if (abs >= ARRAY_SIZE(ds4_absmap)) | ||
| 1193 | return -1; | ||
| 1194 | |||
| 1195 | abs = ds4_absmap[abs]; | ||
| 1196 | hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); | ||
| 1197 | return 1; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | return 0; | ||
| 1201 | } | ||
| 1202 | |||
| 1133 | static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, | 1203 | static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, |
| 1134 | unsigned int *rsize) | 1204 | unsigned int *rsize) |
| 1135 | { | 1205 | { |
| @@ -1219,23 +1289,22 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) | |||
| 1219 | 1289 | ||
| 1220 | static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) | 1290 | static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) |
| 1221 | { | 1291 | { |
| 1222 | struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, | ||
| 1223 | struct hid_input, list); | ||
| 1224 | struct input_dev *input_dev = hidinput->input; | ||
| 1225 | unsigned long flags; | 1292 | unsigned long flags; |
| 1226 | int n, offset; | 1293 | int n, m, offset, num_touch_data, max_touch_data; |
| 1227 | u8 cable_state, battery_capacity, battery_charging; | 1294 | u8 cable_state, battery_capacity, battery_charging; |
| 1228 | 1295 | ||
| 1229 | /* | 1296 | /* When using Bluetooth the header is 2 bytes longer, so skip these. */ |
| 1230 | * Battery and touchpad data starts at byte 30 in the USB report and | 1297 | int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2; |
| 1231 | * 32 in Bluetooth report. | 1298 | |
| 1232 | */ | 1299 | /* Second bit of third button byte is for the touchpad button. */ |
| 1233 | offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32; | 1300 | offset = data_offset + DS4_INPUT_REPORT_BUTTON_OFFSET; |
| 1301 | input_report_key(sc->touchpad, BTN_LEFT, rd[offset+2] & 0x2); | ||
| 1234 | 1302 | ||
| 1235 | /* | 1303 | /* |
| 1236 | * The lower 4 bits of byte 30 contain the battery level | 1304 | * The lower 4 bits of byte 30 (or 32 for BT) contain the battery level |
| 1237 | * and the 5th bit contains the USB cable state. | 1305 | * and the 5th bit contains the USB cable state. |
| 1238 | */ | 1306 | */ |
| 1307 | offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET; | ||
| 1239 | cable_state = (rd[offset] >> 4) & 0x01; | 1308 | cable_state = (rd[offset] >> 4) & 0x01; |
| 1240 | battery_capacity = rd[offset] & 0x0F; | 1309 | battery_capacity = rd[offset] & 0x0F; |
| 1241 | 1310 | ||
| @@ -1262,30 +1331,52 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) | |||
| 1262 | sc->battery_charging = battery_charging; | 1331 | sc->battery_charging = battery_charging; |
| 1263 | spin_unlock_irqrestore(&sc->lock, flags); | 1332 | spin_unlock_irqrestore(&sc->lock, flags); |
| 1264 | 1333 | ||
| 1265 | offset += 5; | ||
| 1266 | |||
| 1267 | /* | 1334 | /* |
| 1268 | * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB | 1335 | * The Dualshock 4 multi-touch trackpad data starts at offset 33 on USB |
| 1269 | * and 37 on Bluetooth. | 1336 | * and 35 on Bluetooth. |
| 1270 | * The first 7 bits of the first byte is a counter and bit 8 is a touch | 1337 | * The first byte indicates the number of touch data in the report. |
| 1271 | * indicator that is 0 when pressed and 1 when not pressed. | 1338 | * Trackpad data starts 2 bytes later (e.g. 35 for USB). |
| 1272 | * The next 3 bytes are two 12 bit touch coordinates, X and Y. | ||
| 1273 | * The data for the second touch is in the same format and immediatly | ||
| 1274 | * follows the data for the first. | ||
| 1275 | */ | 1339 | */ |
| 1276 | for (n = 0; n < 2; n++) { | 1340 | offset = data_offset + DS4_INPUT_REPORT_TOUCHPAD_OFFSET; |
| 1277 | u16 x, y; | 1341 | max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 3 : 4; |
| 1342 | if (rd[offset] > 0 && rd[offset] <= max_touch_data) | ||
| 1343 | num_touch_data = rd[offset]; | ||
| 1344 | else | ||
| 1345 | num_touch_data = 1; | ||
| 1346 | offset += 1; | ||
| 1347 | |||
| 1348 | for (m = 0; m < num_touch_data; m++) { | ||
| 1349 | /* Skip past timestamp */ | ||
| 1350 | offset += 1; | ||
| 1351 | |||
| 1352 | /* | ||
| 1353 | * The first 7 bits of the first byte is a counter and bit 8 is | ||
| 1354 | * a touch indicator that is 0 when pressed and 1 when not | ||
| 1355 | * pressed. | ||
| 1356 | * The next 3 bytes are two 12 bit touch coordinates, X and Y. | ||
| 1357 | * The data for the second touch is in the same format and | ||
| 1358 | * immediately follows the data for the first. | ||
| 1359 | */ | ||
| 1360 | for (n = 0; n < 2; n++) { | ||
| 1361 | u16 x, y; | ||
| 1362 | bool active; | ||
| 1278 | 1363 | ||
| 1279 | x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); | 1364 | x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); |
| 1280 | y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); | 1365 | y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); |
| 1281 | 1366 | ||
| 1282 | input_mt_slot(input_dev, n); | 1367 | active = !(rd[offset] >> 7); |
| 1283 | input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, | 1368 | input_mt_slot(sc->touchpad, n); |
| 1284 | !(rd[offset] >> 7)); | 1369 | input_mt_report_slot_state(sc->touchpad, MT_TOOL_FINGER, active); |
| 1285 | input_report_abs(input_dev, ABS_MT_POSITION_X, x); | ||
| 1286 | input_report_abs(input_dev, ABS_MT_POSITION_Y, y); | ||
| 1287 | 1370 | ||
| 1288 | offset += 4; | 1371 | if (active) { |
| 1372 | input_report_abs(sc->touchpad, ABS_MT_POSITION_X, x); | ||
| 1373 | input_report_abs(sc->touchpad, ABS_MT_POSITION_Y, y); | ||
| 1374 | } | ||
| 1375 | |||
| 1376 | offset += 4; | ||
| 1377 | } | ||
| 1378 | input_mt_sync_frame(sc->touchpad); | ||
| 1379 | input_sync(sc->touchpad); | ||
| 1289 | } | 1380 | } |
| 1290 | } | 1381 | } |
| 1291 | 1382 | ||
| @@ -1324,6 +1415,21 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
| 1324 | } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && | 1415 | } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && |
| 1325 | size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) | 1416 | size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) |
| 1326 | && rd[0] == 0x11 && size == 78)) { | 1417 | && rd[0] == 0x11 && size == 78)) { |
| 1418 | if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { | ||
| 1419 | /* CRC check */ | ||
| 1420 | u8 bthdr = 0xA1; | ||
| 1421 | u32 crc; | ||
| 1422 | u32 report_crc; | ||
| 1423 | |||
| 1424 | crc = crc32_le(0xFFFFFFFF, &bthdr, 1); | ||
| 1425 | crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4); | ||
| 1426 | report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]); | ||
| 1427 | if (crc != report_crc) { | ||
| 1428 | hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n", | ||
| 1429 | report_crc, crc); | ||
| 1430 | return -EILSEQ; | ||
| 1431 | } | ||
| 1432 | } | ||
| 1327 | dualshock4_parse_report(sc, rd, size); | 1433 | dualshock4_parse_report(sc, rd, size); |
| 1328 | } | 1434 | } |
| 1329 | 1435 | ||
| @@ -1367,47 +1473,84 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 1367 | if (sc->quirks & PS3REMOTE) | 1473 | if (sc->quirks & PS3REMOTE) |
| 1368 | return ps3remote_mapping(hdev, hi, field, usage, bit, max); | 1474 | return ps3remote_mapping(hdev, hi, field, usage, bit, max); |
| 1369 | 1475 | ||
| 1476 | |||
| 1477 | if (sc->quirks & DUALSHOCK4_CONTROLLER) | ||
| 1478 | return ds4_mapping(hdev, hi, field, usage, bit, max); | ||
| 1479 | |||
| 1370 | /* Let hid-core decide for the others */ | 1480 | /* Let hid-core decide for the others */ |
| 1371 | return 0; | 1481 | return 0; |
| 1372 | } | 1482 | } |
| 1373 | 1483 | ||
| 1374 | static int sony_register_touchpad(struct hid_input *hi, int touch_count, | 1484 | static int sony_register_touchpad(struct sony_sc *sc, int touch_count, |
| 1375 | int w, int h) | 1485 | int w, int h) |
| 1376 | { | 1486 | { |
| 1377 | struct input_dev *input_dev = hi->input; | 1487 | size_t name_sz; |
| 1488 | char *name; | ||
| 1378 | int ret; | 1489 | int ret; |
| 1379 | 1490 | ||
| 1380 | ret = input_mt_init_slots(input_dev, touch_count, 0); | 1491 | sc->touchpad = input_allocate_device(); |
| 1492 | if (!sc->touchpad) | ||
| 1493 | return -ENOMEM; | ||
| 1494 | |||
| 1495 | input_set_drvdata(sc->touchpad, sc); | ||
| 1496 | sc->touchpad->dev.parent = &sc->hdev->dev; | ||
| 1497 | sc->touchpad->phys = sc->hdev->phys; | ||
| 1498 | sc->touchpad->uniq = sc->hdev->uniq; | ||
| 1499 | sc->touchpad->id.bustype = sc->hdev->bus; | ||
| 1500 | sc->touchpad->id.vendor = sc->hdev->vendor; | ||
| 1501 | sc->touchpad->id.product = sc->hdev->product; | ||
| 1502 | sc->touchpad->id.version = sc->hdev->version; | ||
| 1503 | |||
| 1504 | /* Append a suffix to the controller name as there are various | ||
| 1505 | * DS4 compatible non-Sony devices with different names. | ||
| 1506 | */ | ||
| 1507 | name_sz = strlen(sc->hdev->name) + sizeof(DS4_TOUCHPAD_SUFFIX); | ||
| 1508 | name = kzalloc(name_sz, GFP_KERNEL); | ||
| 1509 | if (!name) { | ||
| 1510 | ret = -ENOMEM; | ||
| 1511 | goto err; | ||
| 1512 | } | ||
| 1513 | snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name); | ||
| 1514 | sc->touchpad->name = name; | ||
| 1515 | |||
| 1516 | ret = input_mt_init_slots(sc->touchpad, touch_count, 0); | ||
| 1381 | if (ret < 0) | 1517 | if (ret < 0) |
| 1382 | return ret; | 1518 | goto err; |
| 1519 | |||
| 1520 | /* We map the button underneath the touchpad to BTN_LEFT. */ | ||
| 1521 | __set_bit(EV_KEY, sc->touchpad->evbit); | ||
| 1522 | __set_bit(BTN_LEFT, sc->touchpad->keybit); | ||
| 1523 | __set_bit(INPUT_PROP_BUTTONPAD, sc->touchpad->propbit); | ||
| 1383 | 1524 | ||
| 1384 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0); | 1525 | input_set_abs_params(sc->touchpad, ABS_MT_POSITION_X, 0, w, 0, 0); |
| 1385 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0); | 1526 | input_set_abs_params(sc->touchpad, ABS_MT_POSITION_Y, 0, h, 0, 0); |
| 1527 | |||
| 1528 | ret = input_register_device(sc->touchpad); | ||
| 1529 | if (ret < 0) | ||
| 1530 | goto err; | ||
| 1386 | 1531 | ||
| 1387 | return 0; | 1532 | return 0; |
| 1533 | |||
| 1534 | err: | ||
| 1535 | kfree(sc->touchpad->name); | ||
| 1536 | sc->touchpad->name = NULL; | ||
| 1537 | |||
| 1538 | input_free_device(sc->touchpad); | ||
| 1539 | sc->touchpad = NULL; | ||
| 1540 | |||
| 1541 | return ret; | ||
| 1388 | } | 1542 | } |
| 1389 | 1543 | ||
| 1390 | static int sony_input_configured(struct hid_device *hdev, | 1544 | static void sony_unregister_touchpad(struct sony_sc *sc) |
| 1391 | struct hid_input *hidinput) | ||
| 1392 | { | 1545 | { |
| 1393 | struct sony_sc *sc = hid_get_drvdata(hdev); | 1546 | if (!sc->touchpad) |
| 1394 | int ret; | 1547 | return; |
| 1395 | 1548 | ||
| 1396 | /* | 1549 | kfree(sc->touchpad->name); |
| 1397 | * The Dualshock 4 touchpad supports 2 touches and has a | 1550 | sc->touchpad->name = NULL; |
| 1398 | * resolution of 1920x942 (44.86 dots/mm). | ||
| 1399 | */ | ||
| 1400 | if (sc->quirks & DUALSHOCK4_CONTROLLER) { | ||
| 1401 | ret = sony_register_touchpad(hidinput, 2, 1920, 942); | ||
| 1402 | if (ret) { | ||
| 1403 | hid_err(sc->hdev, | ||
| 1404 | "Unable to initialize multi-touch slots: %d\n", | ||
| 1405 | ret); | ||
| 1406 | return ret; | ||
| 1407 | } | ||
| 1408 | } | ||
| 1409 | 1551 | ||
| 1410 | return 0; | 1552 | input_unregister_device(sc->touchpad); |
| 1553 | sc->touchpad = NULL; | ||
| 1411 | } | 1554 | } |
| 1412 | 1555 | ||
| 1413 | /* | 1556 | /* |
| @@ -1483,11 +1626,11 @@ static int dualshock4_set_operational_bt(struct hid_device *hdev) | |||
| 1483 | u8 *buf; | 1626 | u8 *buf; |
| 1484 | int ret; | 1627 | int ret; |
| 1485 | 1628 | ||
| 1486 | buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL); | 1629 | buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL); |
| 1487 | if (!buf) | 1630 | if (!buf) |
| 1488 | return -ENOMEM; | 1631 | return -ENOMEM; |
| 1489 | 1632 | ||
| 1490 | ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE, | 1633 | ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_FEATURE_REPORT_0x02_SIZE, |
| 1491 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | 1634 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
| 1492 | 1635 | ||
| 1493 | kfree(buf); | 1636 | kfree(buf); |
| @@ -1892,14 +2035,14 @@ static void dualshock4_send_output_report(struct sony_sc *sc) | |||
| 1892 | * 0xD0 - 66hz | 2035 | * 0xD0 - 66hz |
| 1893 | */ | 2036 | */ |
| 1894 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | 2037 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { |
| 1895 | memset(buf, 0, DS4_REPORT_0x05_SIZE); | 2038 | memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE); |
| 1896 | buf[0] = 0x05; | 2039 | buf[0] = 0x05; |
| 1897 | buf[1] = 0xFF; | 2040 | buf[1] = 0xFF; |
| 1898 | offset = 4; | 2041 | offset = 4; |
| 1899 | } else { | 2042 | } else { |
| 1900 | memset(buf, 0, DS4_REPORT_0x11_SIZE); | 2043 | memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE); |
| 1901 | buf[0] = 0x11; | 2044 | buf[0] = 0x11; |
| 1902 | buf[1] = 0x80; | 2045 | buf[1] = 0xC0; /* HID + CRC */ |
| 1903 | buf[3] = 0x0F; | 2046 | buf[3] = 0x0F; |
| 1904 | offset = 6; | 2047 | offset = 6; |
| 1905 | } | 2048 | } |
| @@ -1925,10 +2068,17 @@ static void dualshock4_send_output_report(struct sony_sc *sc) | |||
| 1925 | buf[offset++] = sc->led_delay_off[3]; | 2068 | buf[offset++] = sc->led_delay_off[3]; |
| 1926 | 2069 | ||
| 1927 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | 2070 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) |
| 1928 | hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE); | 2071 | hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE); |
| 1929 | else | 2072 | else { |
| 1930 | hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE, | 2073 | /* CRC generation */ |
| 1931 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | 2074 | u8 bthdr = 0xA2; |
| 2075 | u32 crc; | ||
| 2076 | |||
| 2077 | crc = crc32_le(0xFFFFFFFF, &bthdr, 1); | ||
| 2078 | crc = ~crc32_le(crc, buf, DS4_OUTPUT_REPORT_0x11_SIZE-4); | ||
| 2079 | put_unaligned_le32(crc, &buf[74]); | ||
| 2080 | hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x11_SIZE); | ||
| 2081 | } | ||
| 1932 | } | 2082 | } |
| 1933 | 2083 | ||
| 1934 | static void motion_send_output_report(struct sony_sc *sc) | 2084 | static void motion_send_output_report(struct sony_sc *sc) |
| @@ -1972,10 +2122,10 @@ static int sony_allocate_output_report(struct sony_sc *sc) | |||
| 1972 | kmalloc(sizeof(union sixaxis_output_report_01), | 2122 | kmalloc(sizeof(union sixaxis_output_report_01), |
| 1973 | GFP_KERNEL); | 2123 | GFP_KERNEL); |
| 1974 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) | 2124 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) |
| 1975 | sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE, | 2125 | sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE, |
| 1976 | GFP_KERNEL); | 2126 | GFP_KERNEL); |
| 1977 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | 2127 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) |
| 1978 | sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, | 2128 | sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE, |
| 1979 | GFP_KERNEL); | 2129 | GFP_KERNEL); |
| 1980 | else if (sc->quirks & MOTION_CONTROLLER) | 2130 | else if (sc->quirks & MOTION_CONTROLLER) |
| 1981 | sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE, | 2131 | sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE, |
| @@ -2220,7 +2370,7 @@ static int sony_check_add(struct sony_sc *sc) | |||
| 2220 | return 0; | 2370 | return 0; |
| 2221 | } | 2371 | } |
| 2222 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | 2372 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { |
| 2223 | buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL); | 2373 | buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL); |
| 2224 | if (!buf) | 2374 | if (!buf) |
| 2225 | return -ENOMEM; | 2375 | return -ENOMEM; |
| 2226 | 2376 | ||
| @@ -2230,10 +2380,10 @@ static int sony_check_add(struct sony_sc *sc) | |||
| 2230 | * offset 1. | 2380 | * offset 1. |
| 2231 | */ | 2381 | */ |
| 2232 | ret = hid_hw_raw_request(sc->hdev, 0x81, buf, | 2382 | ret = hid_hw_raw_request(sc->hdev, 0x81, buf, |
| 2233 | DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT, | 2383 | DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT, |
| 2234 | HID_REQ_GET_REPORT); | 2384 | HID_REQ_GET_REPORT); |
| 2235 | 2385 | ||
| 2236 | if (ret != DS4_REPORT_0x81_SIZE) { | 2386 | if (ret != DS4_FEATURE_REPORT_0x81_SIZE) { |
| 2237 | hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); | 2387 | hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); |
| 2238 | ret = ret < 0 ? ret : -EINVAL; | 2388 | ret = ret < 0 ? ret : -EINVAL; |
| 2239 | goto out_free; | 2389 | goto out_free; |
| @@ -2329,45 +2479,12 @@ static inline void sony_cancel_work_sync(struct sony_sc *sc) | |||
| 2329 | cancel_work_sync(&sc->state_worker); | 2479 | cancel_work_sync(&sc->state_worker); |
| 2330 | } | 2480 | } |
| 2331 | 2481 | ||
| 2332 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | 2482 | static int sony_input_configured(struct hid_device *hdev, |
| 2483 | struct hid_input *hidinput) | ||
| 2333 | { | 2484 | { |
| 2334 | int ret; | 2485 | struct sony_sc *sc = hid_get_drvdata(hdev); |
| 2335 | int append_dev_id; | 2486 | int append_dev_id; |
| 2336 | unsigned long quirks = id->driver_data; | 2487 | int ret; |
| 2337 | struct sony_sc *sc; | ||
| 2338 | unsigned int connect_mask = HID_CONNECT_DEFAULT; | ||
| 2339 | |||
| 2340 | if (!strcmp(hdev->name, "FutureMax Dance Mat")) | ||
| 2341 | quirks |= FUTUREMAX_DANCE_MAT; | ||
| 2342 | |||
| 2343 | sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); | ||
| 2344 | if (sc == NULL) { | ||
| 2345 | hid_err(hdev, "can't alloc sony descriptor\n"); | ||
| 2346 | return -ENOMEM; | ||
| 2347 | } | ||
| 2348 | |||
| 2349 | spin_lock_init(&sc->lock); | ||
| 2350 | |||
| 2351 | sc->quirks = quirks; | ||
| 2352 | hid_set_drvdata(hdev, sc); | ||
| 2353 | sc->hdev = hdev; | ||
| 2354 | |||
| 2355 | ret = hid_parse(hdev); | ||
| 2356 | if (ret) { | ||
| 2357 | hid_err(hdev, "parse failed\n"); | ||
| 2358 | return ret; | ||
| 2359 | } | ||
| 2360 | |||
| 2361 | if (sc->quirks & VAIO_RDESC_CONSTANT) | ||
| 2362 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; | ||
| 2363 | else if (sc->quirks & SIXAXIS_CONTROLLER) | ||
| 2364 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; | ||
| 2365 | |||
| 2366 | ret = hid_hw_start(hdev, connect_mask); | ||
| 2367 | if (ret) { | ||
| 2368 | hid_err(hdev, "hw start failed\n"); | ||
| 2369 | return ret; | ||
| 2370 | } | ||
| 2371 | 2488 | ||
| 2372 | ret = sony_set_device_id(sc); | 2489 | ret = sony_set_device_id(sc); |
| 2373 | if (ret < 0) { | 2490 | if (ret < 0) { |
| @@ -2415,11 +2532,6 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 2415 | sony_init_output_report(sc, sixaxis_send_output_report); | 2532 | sony_init_output_report(sc, sixaxis_send_output_report); |
| 2416 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { | 2533 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { |
| 2417 | if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { | 2534 | if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { |
| 2418 | /* | ||
| 2419 | * The DualShock 4 wants output reports sent on the ctrl | ||
| 2420 | * endpoint when connected via Bluetooth. | ||
| 2421 | */ | ||
| 2422 | hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; | ||
| 2423 | ret = dualshock4_set_operational_bt(hdev); | 2535 | ret = dualshock4_set_operational_bt(hdev); |
| 2424 | if (ret < 0) { | 2536 | if (ret < 0) { |
| 2425 | hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); | 2537 | hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); |
| @@ -2427,6 +2539,18 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 2427 | } | 2539 | } |
| 2428 | } | 2540 | } |
| 2429 | 2541 | ||
| 2542 | /* | ||
| 2543 | * The Dualshock 4 touchpad supports 2 touches and has a | ||
| 2544 | * resolution of 1920x942 (44.86 dots/mm). | ||
| 2545 | */ | ||
| 2546 | ret = sony_register_touchpad(sc, 2, 1920, 942); | ||
| 2547 | if (ret) { | ||
| 2548 | hid_err(sc->hdev, | ||
| 2549 | "Unable to initialize multi-touch slots: %d\n", | ||
| 2550 | ret); | ||
| 2551 | return ret; | ||
| 2552 | } | ||
| 2553 | |||
| 2430 | sony_init_output_report(sc, dualshock4_send_output_report); | 2554 | sony_init_output_report(sc, dualshock4_send_output_report); |
| 2431 | } else if (sc->quirks & MOTION_CONTROLLER) { | 2555 | } else if (sc->quirks & MOTION_CONTROLLER) { |
| 2432 | sony_init_output_report(sc, motion_send_output_report); | 2556 | sony_init_output_report(sc, motion_send_output_report); |
| @@ -2482,17 +2606,84 @@ err_stop: | |||
| 2482 | return ret; | 2606 | return ret; |
| 2483 | } | 2607 | } |
| 2484 | 2608 | ||
| 2609 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
| 2610 | { | ||
| 2611 | int ret; | ||
| 2612 | unsigned long quirks = id->driver_data; | ||
| 2613 | struct sony_sc *sc; | ||
| 2614 | unsigned int connect_mask = HID_CONNECT_DEFAULT; | ||
| 2615 | |||
| 2616 | if (!strcmp(hdev->name, "FutureMax Dance Mat")) | ||
| 2617 | quirks |= FUTUREMAX_DANCE_MAT; | ||
| 2618 | |||
| 2619 | sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); | ||
| 2620 | if (sc == NULL) { | ||
| 2621 | hid_err(hdev, "can't alloc sony descriptor\n"); | ||
| 2622 | return -ENOMEM; | ||
| 2623 | } | ||
| 2624 | |||
| 2625 | spin_lock_init(&sc->lock); | ||
| 2626 | |||
| 2627 | sc->quirks = quirks; | ||
| 2628 | hid_set_drvdata(hdev, sc); | ||
| 2629 | sc->hdev = hdev; | ||
| 2630 | |||
| 2631 | ret = hid_parse(hdev); | ||
| 2632 | if (ret) { | ||
| 2633 | hid_err(hdev, "parse failed\n"); | ||
| 2634 | return ret; | ||
| 2635 | } | ||
| 2636 | |||
| 2637 | if (sc->quirks & VAIO_RDESC_CONSTANT) | ||
| 2638 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; | ||
| 2639 | else if (sc->quirks & SIXAXIS_CONTROLLER) | ||
| 2640 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; | ||
| 2641 | |||
| 2642 | /* Patch the hw version on DS4 compatible devices, so applications can | ||
| 2643 | * distinguish between the default HID mappings and the mappings defined | ||
| 2644 | * by the Linux game controller spec. This is important for the SDL2 | ||
| 2645 | * library, which has a game controller database, which uses device ids | ||
| 2646 | * in combination with version as a key. | ||
| 2647 | */ | ||
| 2648 | if (sc->quirks & DUALSHOCK4_CONTROLLER) | ||
| 2649 | hdev->version |= 0x8000; | ||
| 2650 | |||
| 2651 | ret = hid_hw_start(hdev, connect_mask); | ||
| 2652 | if (ret) { | ||
| 2653 | hid_err(hdev, "hw start failed\n"); | ||
| 2654 | return ret; | ||
| 2655 | } | ||
| 2656 | |||
| 2657 | /* sony_input_configured can fail, but this doesn't result | ||
| 2658 | * in hid_hw_start failures (intended). Check whether | ||
| 2659 | * the HID layer claimed the device else fail. | ||
| 2660 | * We don't know the actual reason for the failure, most | ||
| 2661 | * likely it is due to EEXIST in case of double connection | ||
| 2662 | * of USB and Bluetooth, but could have been due to ENOMEM | ||
| 2663 | * or other reasons as well. | ||
| 2664 | */ | ||
| 2665 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) { | ||
| 2666 | hid_err(hdev, "failed to claim input\n"); | ||
| 2667 | return -ENODEV; | ||
| 2668 | } | ||
| 2669 | |||
| 2670 | return ret; | ||
| 2671 | } | ||
| 2672 | |||
| 2485 | static void sony_remove(struct hid_device *hdev) | 2673 | static void sony_remove(struct hid_device *hdev) |
| 2486 | { | 2674 | { |
| 2487 | struct sony_sc *sc = hid_get_drvdata(hdev); | 2675 | struct sony_sc *sc = hid_get_drvdata(hdev); |
| 2488 | 2676 | ||
| 2677 | hid_hw_close(hdev); | ||
| 2678 | |||
| 2489 | if (sc->quirks & SONY_LED_SUPPORT) | 2679 | if (sc->quirks & SONY_LED_SUPPORT) |
| 2490 | sony_leds_remove(sc); | 2680 | sony_leds_remove(sc); |
| 2491 | 2681 | ||
| 2492 | if (sc->quirks & SONY_BATTERY_SUPPORT) { | 2682 | if (sc->quirks & SONY_BATTERY_SUPPORT) |
| 2493 | hid_hw_close(hdev); | ||
| 2494 | sony_battery_remove(sc); | 2683 | sony_battery_remove(sc); |
| 2495 | } | 2684 | |
| 2685 | if (sc->touchpad) | ||
| 2686 | sony_unregister_touchpad(sc); | ||
| 2496 | 2687 | ||
| 2497 | sony_cancel_work_sync(sc); | 2688 | sony_cancel_work_sync(sc); |
| 2498 | 2689 | ||
| @@ -2596,6 +2787,12 @@ static const struct hid_device_id sony_devices[] = { | |||
| 2596 | .driver_data = DUALSHOCK4_CONTROLLER_USB }, | 2787 | .driver_data = DUALSHOCK4_CONTROLLER_USB }, |
| 2597 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), | 2788 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), |
| 2598 | .driver_data = DUALSHOCK4_CONTROLLER_BT }, | 2789 | .driver_data = DUALSHOCK4_CONTROLLER_BT }, |
| 2790 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), | ||
| 2791 | .driver_data = DUALSHOCK4_CONTROLLER_USB }, | ||
| 2792 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), | ||
| 2793 | .driver_data = DUALSHOCK4_CONTROLLER_BT }, | ||
| 2794 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE), | ||
| 2795 | .driver_data = DUALSHOCK4_CONTROLLER_USB }, | ||
| 2599 | /* Nyko Core Controller for PS3 */ | 2796 | /* Nyko Core Controller for PS3 */ |
| 2600 | { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER), | 2797 | { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER), |
| 2601 | .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER }, | 2798 | .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER }, |
diff --git a/drivers/hid/hid-udraw-ps3.c b/drivers/hid/hid-udraw-ps3.c new file mode 100644 index 000000000000..88ea390c10ad --- /dev/null +++ b/drivers/hid/hid-udraw-ps3.c | |||
| @@ -0,0 +1,474 @@ | |||
| 1 | /* | ||
| 2 | * HID driver for THQ PS3 uDraw tablet | ||
| 3 | * | ||
| 4 | * Copyright (C) 2016 Red Hat Inc. All Rights Reserved | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/hid.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include "hid-ids.h" | ||
| 20 | |||
| 21 | MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>"); | ||
| 22 | MODULE_DESCRIPTION("PS3 uDraw tablet driver"); | ||
| 23 | MODULE_LICENSE("GPL"); | ||
| 24 | |||
| 25 | /* | ||
| 26 | * Protocol information from: | ||
| 27 | * http://brandonw.net/udraw/ | ||
| 28 | * and the source code of: | ||
| 29 | * https://vvvv.org/contribution/udraw-hid | ||
| 30 | */ | ||
| 31 | |||
| 32 | /* | ||
| 33 | * The device is setup with multiple input devices: | ||
| 34 | * - the touch area which works as a touchpad | ||
| 35 | * - the tablet area which works as a touchpad/drawing tablet | ||
| 36 | * - a joypad with a d-pad, and 7 buttons | ||
| 37 | * - an accelerometer device | ||
| 38 | */ | ||
| 39 | |||
| 40 | enum { | ||
| 41 | TOUCH_NONE, | ||
| 42 | TOUCH_PEN, | ||
| 43 | TOUCH_FINGER, | ||
| 44 | TOUCH_TWOFINGER | ||
| 45 | }; | ||
| 46 | |||
| 47 | enum { | ||
| 48 | AXIS_X, | ||
| 49 | AXIS_Y, | ||
| 50 | AXIS_Z | ||
| 51 | }; | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Accelerometer min/max values | ||
| 55 | * in order, X, Y and Z | ||
| 56 | */ | ||
| 57 | static struct { | ||
| 58 | int min; | ||
| 59 | int max; | ||
| 60 | } accel_limits[] = { | ||
| 61 | [AXIS_X] = { 490, 534 }, | ||
| 62 | [AXIS_Y] = { 490, 534 }, | ||
| 63 | [AXIS_Z] = { 492, 536 } | ||
| 64 | }; | ||
| 65 | |||
| 66 | #define DEVICE_NAME "THQ uDraw Game Tablet for PS3" | ||
| 67 | /* resolution in pixels */ | ||
| 68 | #define RES_X 1920 | ||
| 69 | #define RES_Y 1080 | ||
| 70 | /* size in mm */ | ||
| 71 | #define WIDTH 160 | ||
| 72 | #define HEIGHT 90 | ||
| 73 | #define PRESSURE_OFFSET 113 | ||
| 74 | #define MAX_PRESSURE (255 - PRESSURE_OFFSET) | ||
| 75 | |||
| 76 | struct udraw { | ||
| 77 | struct input_dev *joy_input_dev; | ||
| 78 | struct input_dev *touch_input_dev; | ||
| 79 | struct input_dev *pen_input_dev; | ||
| 80 | struct input_dev *accel_input_dev; | ||
| 81 | struct hid_device *hdev; | ||
| 82 | |||
| 83 | /* | ||
| 84 | * The device's two-finger support is pretty unreliable, as | ||
| 85 | * the device could report a single touch when the two fingers | ||
| 86 | * are too close together, and the distance between fingers, even | ||
| 87 | * though reported is not in the same unit as the touches. | ||
| 88 | * | ||
| 89 | * We'll make do without it, and try to report the first touch | ||
| 90 | * as reliably as possible. | ||
| 91 | */ | ||
| 92 | int last_one_finger_x; | ||
| 93 | int last_one_finger_y; | ||
| 94 | int last_two_finger_x; | ||
| 95 | int last_two_finger_y; | ||
| 96 | }; | ||
| 97 | |||
| 98 | static int clamp_accel(int axis, int offset) | ||
| 99 | { | ||
| 100 | axis = clamp(axis, | ||
| 101 | accel_limits[offset].min, | ||
| 102 | accel_limits[offset].max); | ||
| 103 | axis = (axis - accel_limits[offset].min) / | ||
| 104 | ((accel_limits[offset].max - | ||
| 105 | accel_limits[offset].min) * 0xFF); | ||
| 106 | return axis; | ||
| 107 | } | ||
| 108 | |||
| 109 | static int udraw_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
| 110 | u8 *data, int len) | ||
| 111 | { | ||
| 112 | struct udraw *udraw = hid_get_drvdata(hdev); | ||
| 113 | int touch; | ||
| 114 | int x, y, z; | ||
| 115 | |||
| 116 | if (len != 27) | ||
| 117 | return 0; | ||
| 118 | |||
| 119 | if (data[11] == 0x00) | ||
| 120 | touch = TOUCH_NONE; | ||
| 121 | else if (data[11] == 0x40) | ||
| 122 | touch = TOUCH_PEN; | ||
| 123 | else if (data[11] == 0x80) | ||
| 124 | touch = TOUCH_FINGER; | ||
| 125 | else | ||
| 126 | touch = TOUCH_TWOFINGER; | ||
| 127 | |||
| 128 | /* joypad */ | ||
| 129 | input_report_key(udraw->joy_input_dev, BTN_WEST, data[0] & 1); | ||
| 130 | input_report_key(udraw->joy_input_dev, BTN_SOUTH, !!(data[0] & 2)); | ||
| 131 | input_report_key(udraw->joy_input_dev, BTN_EAST, !!(data[0] & 4)); | ||
| 132 | input_report_key(udraw->joy_input_dev, BTN_NORTH, !!(data[0] & 8)); | ||
| 133 | |||
| 134 | input_report_key(udraw->joy_input_dev, BTN_SELECT, !!(data[1] & 1)); | ||
| 135 | input_report_key(udraw->joy_input_dev, BTN_START, !!(data[1] & 2)); | ||
| 136 | input_report_key(udraw->joy_input_dev, BTN_MODE, !!(data[1] & 16)); | ||
| 137 | |||
| 138 | x = y = 0; | ||
| 139 | switch (data[2]) { | ||
| 140 | case 0x0: | ||
| 141 | y = -127; | ||
| 142 | break; | ||
| 143 | case 0x1: | ||
| 144 | y = -127; | ||
| 145 | x = 127; | ||
| 146 | break; | ||
| 147 | case 0x2: | ||
| 148 | x = 127; | ||
| 149 | break; | ||
| 150 | case 0x3: | ||
| 151 | y = 127; | ||
| 152 | x = 127; | ||
| 153 | break; | ||
| 154 | case 0x4: | ||
| 155 | y = 127; | ||
| 156 | break; | ||
| 157 | case 0x5: | ||
| 158 | y = 127; | ||
| 159 | x = -127; | ||
| 160 | break; | ||
| 161 | case 0x6: | ||
| 162 | x = -127; | ||
| 163 | break; | ||
| 164 | case 0x7: | ||
| 165 | y = -127; | ||
| 166 | x = -127; | ||
| 167 | break; | ||
| 168 | default: | ||
| 169 | break; | ||
| 170 | } | ||
| 171 | |||
| 172 | input_report_abs(udraw->joy_input_dev, ABS_X, x); | ||
| 173 | input_report_abs(udraw->joy_input_dev, ABS_Y, y); | ||
| 174 | |||
| 175 | input_sync(udraw->joy_input_dev); | ||
| 176 | |||
| 177 | /* For pen and touchpad */ | ||
| 178 | x = y = 0; | ||
| 179 | if (touch != TOUCH_NONE) { | ||
| 180 | if (data[15] != 0x0F) | ||
| 181 | x = data[15] * 256 + data[17]; | ||
| 182 | if (data[16] != 0x0F) | ||
| 183 | y = data[16] * 256 + data[18]; | ||
| 184 | } | ||
| 185 | |||
| 186 | if (touch == TOUCH_FINGER) { | ||
| 187 | /* Save the last one-finger touch */ | ||
| 188 | udraw->last_one_finger_x = x; | ||
| 189 | udraw->last_one_finger_y = y; | ||
| 190 | udraw->last_two_finger_x = -1; | ||
| 191 | udraw->last_two_finger_y = -1; | ||
| 192 | } else if (touch == TOUCH_TWOFINGER) { | ||
| 193 | /* | ||
| 194 | * We have a problem because x/y is the one for the | ||
| 195 | * second finger but we want the first finger given | ||
| 196 | * to user-space otherwise it'll look as if it jumped. | ||
| 197 | * | ||
| 198 | * See the udraw struct definition for why this was | ||
| 199 | * implemented this way. | ||
| 200 | */ | ||
| 201 | if (udraw->last_two_finger_x == -1) { | ||
| 202 | /* Save the position of the 2nd finger */ | ||
| 203 | udraw->last_two_finger_x = x; | ||
| 204 | udraw->last_two_finger_y = y; | ||
| 205 | |||
| 206 | x = udraw->last_one_finger_x; | ||
| 207 | y = udraw->last_one_finger_y; | ||
| 208 | } else { | ||
| 209 | /* | ||
| 210 | * Offset the 2-finger coords using the | ||
| 211 | * saved data from the first finger | ||
| 212 | */ | ||
| 213 | x = x - (udraw->last_two_finger_x | ||
| 214 | - udraw->last_one_finger_x); | ||
| 215 | y = y - (udraw->last_two_finger_y | ||
| 216 | - udraw->last_one_finger_y); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | /* touchpad */ | ||
| 221 | if (touch == TOUCH_FINGER || touch == TOUCH_TWOFINGER) { | ||
| 222 | input_report_key(udraw->touch_input_dev, BTN_TOUCH, 1); | ||
| 223 | input_report_key(udraw->touch_input_dev, BTN_TOOL_FINGER, | ||
| 224 | touch == TOUCH_FINGER); | ||
| 225 | input_report_key(udraw->touch_input_dev, BTN_TOOL_DOUBLETAP, | ||
| 226 | touch == TOUCH_TWOFINGER); | ||
| 227 | |||
| 228 | input_report_abs(udraw->touch_input_dev, ABS_X, x); | ||
| 229 | input_report_abs(udraw->touch_input_dev, ABS_Y, y); | ||
| 230 | } else { | ||
| 231 | input_report_key(udraw->touch_input_dev, BTN_TOUCH, 0); | ||
| 232 | input_report_key(udraw->touch_input_dev, BTN_TOOL_FINGER, 0); | ||
| 233 | input_report_key(udraw->touch_input_dev, BTN_TOOL_DOUBLETAP, 0); | ||
| 234 | } | ||
| 235 | input_sync(udraw->touch_input_dev); | ||
| 236 | |||
| 237 | /* pen */ | ||
| 238 | if (touch == TOUCH_PEN) { | ||
| 239 | int level; | ||
| 240 | |||
| 241 | level = clamp(data[13] - PRESSURE_OFFSET, | ||
| 242 | 0, MAX_PRESSURE); | ||
| 243 | |||
| 244 | input_report_key(udraw->pen_input_dev, BTN_TOUCH, (level != 0)); | ||
| 245 | input_report_key(udraw->pen_input_dev, BTN_TOOL_PEN, 1); | ||
| 246 | input_report_abs(udraw->pen_input_dev, ABS_PRESSURE, level); | ||
| 247 | input_report_abs(udraw->pen_input_dev, ABS_X, x); | ||
| 248 | input_report_abs(udraw->pen_input_dev, ABS_Y, y); | ||
| 249 | } else { | ||
| 250 | input_report_key(udraw->pen_input_dev, BTN_TOUCH, 0); | ||
| 251 | input_report_key(udraw->pen_input_dev, BTN_TOOL_PEN, 0); | ||
| 252 | input_report_abs(udraw->pen_input_dev, ABS_PRESSURE, 0); | ||
| 253 | } | ||
| 254 | input_sync(udraw->pen_input_dev); | ||
| 255 | |||
| 256 | /* accel */ | ||
| 257 | x = (data[19] + (data[20] << 8)); | ||
| 258 | x = clamp_accel(x, AXIS_X); | ||
| 259 | y = (data[21] + (data[22] << 8)); | ||
| 260 | y = clamp_accel(y, AXIS_Y); | ||
| 261 | z = (data[23] + (data[24] << 8)); | ||
| 262 | z = clamp_accel(z, AXIS_Z); | ||
| 263 | input_report_abs(udraw->accel_input_dev, ABS_X, x); | ||
| 264 | input_report_abs(udraw->accel_input_dev, ABS_Y, y); | ||
| 265 | input_report_abs(udraw->accel_input_dev, ABS_Z, z); | ||
| 266 | input_sync(udraw->accel_input_dev); | ||
| 267 | |||
| 268 | /* let hidraw and hiddev handle the report */ | ||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | |||
| 272 | static int udraw_open(struct input_dev *dev) | ||
| 273 | { | ||
| 274 | struct udraw *udraw = input_get_drvdata(dev); | ||
| 275 | |||
| 276 | return hid_hw_open(udraw->hdev); | ||
| 277 | } | ||
| 278 | |||
| 279 | static void udraw_close(struct input_dev *dev) | ||
| 280 | { | ||
| 281 | struct udraw *udraw = input_get_drvdata(dev); | ||
| 282 | |||
| 283 | hid_hw_close(udraw->hdev); | ||
| 284 | } | ||
| 285 | |||
| 286 | static struct input_dev *allocate_and_setup(struct hid_device *hdev, | ||
| 287 | const char *name) | ||
| 288 | { | ||
| 289 | struct input_dev *input_dev; | ||
| 290 | |||
| 291 | input_dev = devm_input_allocate_device(&hdev->dev); | ||
| 292 | if (!input_dev) | ||
| 293 | return NULL; | ||
| 294 | |||
| 295 | input_dev->name = name; | ||
| 296 | input_dev->phys = hdev->phys; | ||
| 297 | input_dev->dev.parent = &hdev->dev; | ||
| 298 | input_dev->open = udraw_open; | ||
| 299 | input_dev->close = udraw_close; | ||
| 300 | input_dev->uniq = hdev->uniq; | ||
| 301 | input_dev->id.bustype = hdev->bus; | ||
| 302 | input_dev->id.vendor = hdev->vendor; | ||
| 303 | input_dev->id.product = hdev->product; | ||
| 304 | input_dev->id.version = hdev->version; | ||
| 305 | input_set_drvdata(input_dev, hid_get_drvdata(hdev)); | ||
| 306 | |||
| 307 | return input_dev; | ||
| 308 | } | ||
| 309 | |||
| 310 | static bool udraw_setup_touch(struct udraw *udraw, | ||
| 311 | struct hid_device *hdev) | ||
| 312 | { | ||
| 313 | struct input_dev *input_dev; | ||
| 314 | |||
| 315 | input_dev = allocate_and_setup(hdev, DEVICE_NAME " Touchpad"); | ||
| 316 | if (!input_dev) | ||
| 317 | return false; | ||
| 318 | |||
| 319 | input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); | ||
| 320 | |||
| 321 | input_set_abs_params(input_dev, ABS_X, 0, RES_X, 1, 0); | ||
| 322 | input_abs_set_res(input_dev, ABS_X, RES_X / WIDTH); | ||
| 323 | input_set_abs_params(input_dev, ABS_Y, 0, RES_Y, 1, 0); | ||
| 324 | input_abs_set_res(input_dev, ABS_Y, RES_Y / HEIGHT); | ||
| 325 | |||
| 326 | set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 327 | set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
| 328 | set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
| 329 | |||
| 330 | set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
| 331 | |||
| 332 | udraw->touch_input_dev = input_dev; | ||
| 333 | |||
| 334 | return true; | ||
| 335 | } | ||
| 336 | |||
| 337 | static bool udraw_setup_pen(struct udraw *udraw, | ||
| 338 | struct hid_device *hdev) | ||
| 339 | { | ||
| 340 | struct input_dev *input_dev; | ||
| 341 | |||
| 342 | input_dev = allocate_and_setup(hdev, DEVICE_NAME " Pen"); | ||
| 343 | if (!input_dev) | ||
| 344 | return false; | ||
| 345 | |||
| 346 | input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); | ||
| 347 | |||
| 348 | input_set_abs_params(input_dev, ABS_X, 0, RES_X, 1, 0); | ||
| 349 | input_abs_set_res(input_dev, ABS_X, RES_X / WIDTH); | ||
| 350 | input_set_abs_params(input_dev, ABS_Y, 0, RES_Y, 1, 0); | ||
| 351 | input_abs_set_res(input_dev, ABS_Y, RES_Y / HEIGHT); | ||
| 352 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
| 353 | 0, MAX_PRESSURE, 0, 0); | ||
| 354 | |||
| 355 | set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 356 | set_bit(BTN_TOOL_PEN, input_dev->keybit); | ||
| 357 | |||
| 358 | set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
| 359 | |||
| 360 | udraw->pen_input_dev = input_dev; | ||
| 361 | |||
| 362 | return true; | ||
| 363 | } | ||
| 364 | |||
| 365 | static bool udraw_setup_accel(struct udraw *udraw, | ||
| 366 | struct hid_device *hdev) | ||
| 367 | { | ||
| 368 | struct input_dev *input_dev; | ||
| 369 | |||
| 370 | input_dev = allocate_and_setup(hdev, DEVICE_NAME " Accelerometer"); | ||
| 371 | if (!input_dev) | ||
| 372 | return false; | ||
| 373 | |||
| 374 | input_dev->evbit[0] = BIT(EV_ABS); | ||
| 375 | |||
| 376 | /* 1G accel is reported as ~256, so clamp to 2G */ | ||
| 377 | input_set_abs_params(input_dev, ABS_X, -512, 512, 0, 0); | ||
| 378 | input_set_abs_params(input_dev, ABS_Y, -512, 512, 0, 0); | ||
| 379 | input_set_abs_params(input_dev, ABS_Z, -512, 512, 0, 0); | ||
| 380 | |||
| 381 | set_bit(INPUT_PROP_ACCELEROMETER, input_dev->propbit); | ||
| 382 | |||
| 383 | udraw->accel_input_dev = input_dev; | ||
| 384 | |||
| 385 | return true; | ||
| 386 | } | ||
| 387 | |||
| 388 | static bool udraw_setup_joypad(struct udraw *udraw, | ||
| 389 | struct hid_device *hdev) | ||
| 390 | { | ||
| 391 | struct input_dev *input_dev; | ||
| 392 | |||
| 393 | input_dev = allocate_and_setup(hdev, DEVICE_NAME " Joypad"); | ||
| 394 | if (!input_dev) | ||
| 395 | return false; | ||
| 396 | |||
| 397 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
| 398 | |||
| 399 | set_bit(BTN_SOUTH, input_dev->keybit); | ||
| 400 | set_bit(BTN_NORTH, input_dev->keybit); | ||
| 401 | set_bit(BTN_EAST, input_dev->keybit); | ||
| 402 | set_bit(BTN_WEST, input_dev->keybit); | ||
| 403 | set_bit(BTN_SELECT, input_dev->keybit); | ||
| 404 | set_bit(BTN_START, input_dev->keybit); | ||
| 405 | set_bit(BTN_MODE, input_dev->keybit); | ||
| 406 | |||
| 407 | input_set_abs_params(input_dev, ABS_X, -127, 127, 0, 0); | ||
| 408 | input_set_abs_params(input_dev, ABS_Y, -127, 127, 0, 0); | ||
| 409 | |||
| 410 | udraw->joy_input_dev = input_dev; | ||
| 411 | |||
| 412 | return true; | ||
| 413 | } | ||
| 414 | |||
| 415 | static int udraw_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
| 416 | { | ||
| 417 | struct udraw *udraw; | ||
| 418 | int ret; | ||
| 419 | |||
| 420 | udraw = devm_kzalloc(&hdev->dev, sizeof(struct udraw), GFP_KERNEL); | ||
| 421 | if (!udraw) | ||
| 422 | return -ENOMEM; | ||
| 423 | |||
| 424 | udraw->hdev = hdev; | ||
| 425 | udraw->last_two_finger_x = -1; | ||
| 426 | udraw->last_two_finger_y = -1; | ||
| 427 | |||
| 428 | hid_set_drvdata(hdev, udraw); | ||
| 429 | |||
| 430 | ret = hid_parse(hdev); | ||
| 431 | if (ret) { | ||
| 432 | hid_err(hdev, "parse failed\n"); | ||
| 433 | return ret; | ||
| 434 | } | ||
| 435 | |||
| 436 | if (!udraw_setup_joypad(udraw, hdev) || | ||
| 437 | !udraw_setup_touch(udraw, hdev) || | ||
| 438 | !udraw_setup_pen(udraw, hdev) || | ||
| 439 | !udraw_setup_accel(udraw, hdev)) { | ||
| 440 | hid_err(hdev, "could not allocate interfaces\n"); | ||
| 441 | return -ENOMEM; | ||
| 442 | } | ||
| 443 | |||
| 444 | ret = input_register_device(udraw->joy_input_dev) || | ||
| 445 | input_register_device(udraw->touch_input_dev) || | ||
| 446 | input_register_device(udraw->pen_input_dev) || | ||
| 447 | input_register_device(udraw->accel_input_dev); | ||
| 448 | if (ret) { | ||
| 449 | hid_err(hdev, "failed to register interfaces\n"); | ||
| 450 | return ret; | ||
| 451 | } | ||
| 452 | |||
| 453 | ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW | HID_CONNECT_DRIVER); | ||
| 454 | if (ret) { | ||
| 455 | hid_err(hdev, "hw start failed\n"); | ||
| 456 | return ret; | ||
| 457 | } | ||
| 458 | |||
| 459 | return 0; | ||
| 460 | } | ||
| 461 | |||
| 462 | static const struct hid_device_id udraw_devices[] = { | ||
| 463 | { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) }, | ||
| 464 | { } | ||
| 465 | }; | ||
| 466 | MODULE_DEVICE_TABLE(hid, udraw_devices); | ||
| 467 | |||
| 468 | static struct hid_driver udraw_driver = { | ||
| 469 | .name = "hid-udraw", | ||
| 470 | .id_table = udraw_devices, | ||
| 471 | .raw_event = udraw_raw_event, | ||
| 472 | .probe = udraw_probe, | ||
| 473 | }; | ||
| 474 | module_hid_driver(udraw_driver); | ||
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index b3ec4f2de875..78fb32a7b103 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
| 23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| 24 | #include <linux/input.h> | 24 | #include <linux/input.h> |
| 25 | #include <linux/irq.h> | ||
| 25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 27 | #include <linux/pm.h> | 28 | #include <linux/pm.h> |
| @@ -37,10 +38,15 @@ | |||
| 37 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
| 38 | #include <linux/acpi.h> | 39 | #include <linux/acpi.h> |
| 39 | #include <linux/of.h> | 40 | #include <linux/of.h> |
| 40 | #include <linux/gpio/consumer.h> | 41 | #include <linux/regulator/consumer.h> |
| 41 | 42 | ||
| 42 | #include <linux/i2c/i2c-hid.h> | 43 | #include <linux/i2c/i2c-hid.h> |
| 43 | 44 | ||
| 45 | #include "../hid-ids.h" | ||
| 46 | |||
| 47 | /* quirks to control the device */ | ||
| 48 | #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0) | ||
| 49 | |||
| 44 | /* flags */ | 50 | /* flags */ |
| 45 | #define I2C_HID_STARTED 0 | 51 | #define I2C_HID_STARTED 0 |
| 46 | #define I2C_HID_RESET_PENDING 1 | 52 | #define I2C_HID_RESET_PENDING 1 |
| @@ -143,10 +149,9 @@ struct i2c_hid { | |||
| 143 | char *argsbuf; /* Command arguments buffer */ | 149 | char *argsbuf; /* Command arguments buffer */ |
| 144 | 150 | ||
| 145 | unsigned long flags; /* device flags */ | 151 | unsigned long flags; /* device flags */ |
| 152 | unsigned long quirks; /* Various quirks */ | ||
| 146 | 153 | ||
| 147 | wait_queue_head_t wait; /* For waiting the interrupt */ | 154 | wait_queue_head_t wait; /* For waiting the interrupt */ |
| 148 | struct gpio_desc *desc; | ||
| 149 | int irq; | ||
| 150 | 155 | ||
| 151 | struct i2c_hid_platform_data pdata; | 156 | struct i2c_hid_platform_data pdata; |
| 152 | 157 | ||
| @@ -154,6 +159,39 @@ struct i2c_hid { | |||
| 154 | struct mutex reset_lock; | 159 | struct mutex reset_lock; |
| 155 | }; | 160 | }; |
| 156 | 161 | ||
| 162 | static const struct i2c_hid_quirks { | ||
| 163 | __u16 idVendor; | ||
| 164 | __u16 idProduct; | ||
| 165 | __u32 quirks; | ||
| 166 | } i2c_hid_quirks[] = { | ||
| 167 | { USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8752, | ||
| 168 | I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV }, | ||
| 169 | { USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8755, | ||
| 170 | I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV }, | ||
| 171 | { 0, 0 } | ||
| 172 | }; | ||
| 173 | |||
| 174 | /* | ||
| 175 | * i2c_hid_lookup_quirk: return any quirks associated with a I2C HID device | ||
| 176 | * @idVendor: the 16-bit vendor ID | ||
| 177 | * @idProduct: the 16-bit product ID | ||
| 178 | * | ||
| 179 | * Returns: a u32 quirks value. | ||
| 180 | */ | ||
| 181 | static u32 i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct) | ||
| 182 | { | ||
| 183 | u32 quirks = 0; | ||
| 184 | int n; | ||
| 185 | |||
| 186 | for (n = 0; i2c_hid_quirks[n].idVendor; n++) | ||
| 187 | if (i2c_hid_quirks[n].idVendor == idVendor && | ||
| 188 | (i2c_hid_quirks[n].idProduct == (__u16)HID_ANY_ID || | ||
| 189 | i2c_hid_quirks[n].idProduct == idProduct)) | ||
| 190 | quirks = i2c_hid_quirks[n].quirks; | ||
| 191 | |||
| 192 | return quirks; | ||
| 193 | } | ||
| 194 | |||
| 157 | static int __i2c_hid_command(struct i2c_client *client, | 195 | static int __i2c_hid_command(struct i2c_client *client, |
| 158 | const struct i2c_hid_cmd *command, u8 reportID, | 196 | const struct i2c_hid_cmd *command, u8 reportID, |
| 159 | u8 reportType, u8 *args, int args_len, | 197 | u8 reportType, u8 *args, int args_len, |
| @@ -346,11 +384,27 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state) | |||
| 346 | 384 | ||
| 347 | i2c_hid_dbg(ihid, "%s\n", __func__); | 385 | i2c_hid_dbg(ihid, "%s\n", __func__); |
| 348 | 386 | ||
| 387 | /* | ||
| 388 | * Some devices require to send a command to wakeup before power on. | ||
| 389 | * The call will get a return value (EREMOTEIO) but device will be | ||
| 390 | * triggered and activated. After that, it goes like a normal device. | ||
| 391 | */ | ||
| 392 | if (power_state == I2C_HID_PWR_ON && | ||
| 393 | ihid->quirks & I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV) { | ||
| 394 | ret = i2c_hid_command(client, &hid_set_power_cmd, NULL, 0); | ||
| 395 | |||
| 396 | /* Device was already activated */ | ||
| 397 | if (!ret) | ||
| 398 | goto set_pwr_exit; | ||
| 399 | } | ||
| 400 | |||
| 349 | ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state, | 401 | ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state, |
| 350 | 0, NULL, 0, NULL, 0); | 402 | 0, NULL, 0, NULL, 0); |
| 403 | |||
| 351 | if (ret) | 404 | if (ret) |
| 352 | dev_err(&client->dev, "failed to change power setting.\n"); | 405 | dev_err(&client->dev, "failed to change power setting.\n"); |
| 353 | 406 | ||
| 407 | set_pwr_exit: | ||
| 354 | return ret; | 408 | return ret; |
| 355 | } | 409 | } |
| 356 | 410 | ||
| @@ -716,9 +770,11 @@ static int i2c_hid_start(struct hid_device *hid) | |||
| 716 | i2c_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize); | 770 | i2c_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize); |
| 717 | 771 | ||
| 718 | if (bufsize > ihid->bufsize) { | 772 | if (bufsize > ihid->bufsize) { |
| 773 | disable_irq(client->irq); | ||
| 719 | i2c_hid_free_buffers(ihid); | 774 | i2c_hid_free_buffers(ihid); |
| 720 | 775 | ||
| 721 | ret = i2c_hid_alloc_buffers(ihid, bufsize); | 776 | ret = i2c_hid_alloc_buffers(ihid, bufsize); |
| 777 | enable_irq(client->irq); | ||
| 722 | 778 | ||
| 723 | if (ret) | 779 | if (ret) |
| 724 | return ret; | 780 | return ret; |
| @@ -806,18 +862,21 @@ static struct hid_ll_driver i2c_hid_ll_driver = { | |||
| 806 | static int i2c_hid_init_irq(struct i2c_client *client) | 862 | static int i2c_hid_init_irq(struct i2c_client *client) |
| 807 | { | 863 | { |
| 808 | struct i2c_hid *ihid = i2c_get_clientdata(client); | 864 | struct i2c_hid *ihid = i2c_get_clientdata(client); |
| 865 | unsigned long irqflags = 0; | ||
| 809 | int ret; | 866 | int ret; |
| 810 | 867 | ||
| 811 | dev_dbg(&client->dev, "Requesting IRQ: %d\n", ihid->irq); | 868 | dev_dbg(&client->dev, "Requesting IRQ: %d\n", client->irq); |
| 812 | 869 | ||
| 813 | ret = request_threaded_irq(ihid->irq, NULL, i2c_hid_irq, | 870 | if (!irq_get_trigger_type(client->irq)) |
| 814 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 871 | irqflags = IRQF_TRIGGER_LOW; |
| 815 | client->name, ihid); | 872 | |
| 873 | ret = request_threaded_irq(client->irq, NULL, i2c_hid_irq, | ||
| 874 | irqflags | IRQF_ONESHOT, client->name, ihid); | ||
| 816 | if (ret < 0) { | 875 | if (ret < 0) { |
| 817 | dev_warn(&client->dev, | 876 | dev_warn(&client->dev, |
| 818 | "Could not register for %s interrupt, irq = %d," | 877 | "Could not register for %s interrupt, irq = %d," |
| 819 | " ret = %d\n", | 878 | " ret = %d\n", |
| 820 | client->name, ihid->irq, ret); | 879 | client->name, client->irq, ret); |
| 821 | 880 | ||
| 822 | return ret; | 881 | return ret; |
| 823 | } | 882 | } |
| @@ -864,14 +923,6 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid) | |||
| 864 | } | 923 | } |
| 865 | 924 | ||
| 866 | #ifdef CONFIG_ACPI | 925 | #ifdef CONFIG_ACPI |
| 867 | |||
| 868 | /* Default GPIO mapping */ | ||
| 869 | static const struct acpi_gpio_params i2c_hid_irq_gpio = { 0, 0, true }; | ||
| 870 | static const struct acpi_gpio_mapping i2c_hid_acpi_gpios[] = { | ||
| 871 | { "gpios", &i2c_hid_irq_gpio, 1 }, | ||
| 872 | { }, | ||
| 873 | }; | ||
| 874 | |||
| 875 | static int i2c_hid_acpi_pdata(struct i2c_client *client, | 926 | static int i2c_hid_acpi_pdata(struct i2c_client *client, |
| 876 | struct i2c_hid_platform_data *pdata) | 927 | struct i2c_hid_platform_data *pdata) |
| 877 | { | 928 | { |
| @@ -882,7 +933,6 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, | |||
| 882 | union acpi_object *obj; | 933 | union acpi_object *obj; |
| 883 | struct acpi_device *adev; | 934 | struct acpi_device *adev; |
| 884 | acpi_handle handle; | 935 | acpi_handle handle; |
| 885 | int ret; | ||
| 886 | 936 | ||
| 887 | handle = ACPI_HANDLE(&client->dev); | 937 | handle = ACPI_HANDLE(&client->dev); |
| 888 | if (!handle || acpi_bus_get_device(handle, &adev)) | 938 | if (!handle || acpi_bus_get_device(handle, &adev)) |
| @@ -898,9 +948,7 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, | |||
| 898 | pdata->hid_descriptor_address = obj->integer.value; | 948 | pdata->hid_descriptor_address = obj->integer.value; |
| 899 | ACPI_FREE(obj); | 949 | ACPI_FREE(obj); |
| 900 | 950 | ||
| 901 | /* GPIOs are optional */ | 951 | return 0; |
| 902 | ret = acpi_dev_add_driver_gpios(adev, i2c_hid_acpi_gpios); | ||
| 903 | return ret < 0 && ret != -ENXIO ? ret : 0; | ||
| 904 | } | 952 | } |
| 905 | 953 | ||
| 906 | static const struct acpi_device_id i2c_hid_acpi_match[] = { | 954 | static const struct acpi_device_id i2c_hid_acpi_match[] = { |
| @@ -964,6 +1012,19 @@ static int i2c_hid_probe(struct i2c_client *client, | |||
| 964 | 1012 | ||
| 965 | dbg_hid("HID probe called for i2c 0x%02x\n", client->addr); | 1013 | dbg_hid("HID probe called for i2c 0x%02x\n", client->addr); |
| 966 | 1014 | ||
| 1015 | if (!client->irq) { | ||
| 1016 | dev_err(&client->dev, | ||
| 1017 | "HID over i2c has not been provided an Int IRQ\n"); | ||
| 1018 | return -EINVAL; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | if (client->irq < 0) { | ||
| 1022 | if (client->irq != -EPROBE_DEFER) | ||
| 1023 | dev_err(&client->dev, | ||
| 1024 | "HID over i2c doesn't have a valid IRQ\n"); | ||
| 1025 | return client->irq; | ||
| 1026 | } | ||
| 1027 | |||
| 967 | ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL); | 1028 | ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL); |
| 968 | if (!ihid) | 1029 | if (!ihid) |
| 969 | return -ENOMEM; | 1030 | return -ENOMEM; |
| @@ -983,23 +1044,6 @@ static int i2c_hid_probe(struct i2c_client *client, | |||
| 983 | ihid->pdata = *platform_data; | 1044 | ihid->pdata = *platform_data; |
| 984 | } | 1045 | } |
| 985 | 1046 | ||
| 986 | if (client->irq > 0) { | ||
| 987 | ihid->irq = client->irq; | ||
| 988 | } else if (ACPI_COMPANION(&client->dev)) { | ||
| 989 | ihid->desc = gpiod_get(&client->dev, NULL, GPIOD_IN); | ||
| 990 | if (IS_ERR(ihid->desc)) { | ||
| 991 | dev_err(&client->dev, "Failed to get GPIO interrupt\n"); | ||
| 992 | return PTR_ERR(ihid->desc); | ||
| 993 | } | ||
| 994 | |||
| 995 | ihid->irq = gpiod_to_irq(ihid->desc); | ||
| 996 | if (ihid->irq < 0) { | ||
| 997 | gpiod_put(ihid->desc); | ||
| 998 | dev_err(&client->dev, "Failed to convert GPIO to IRQ\n"); | ||
| 999 | return ihid->irq; | ||
| 1000 | } | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | i2c_set_clientdata(client, ihid); | 1047 | i2c_set_clientdata(client, ihid); |
| 1004 | 1048 | ||
| 1005 | ihid->client = client; | 1049 | ihid->client = client; |
| @@ -1050,6 +1094,8 @@ static int i2c_hid_probe(struct i2c_client *client, | |||
| 1050 | client->name, hid->vendor, hid->product); | 1094 | client->name, hid->vendor, hid->product); |
| 1051 | strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); | 1095 | strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); |
| 1052 | 1096 | ||
| 1097 | ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product); | ||
| 1098 | |||
| 1053 | ret = hid_add_device(hid); | 1099 | ret = hid_add_device(hid); |
| 1054 | if (ret) { | 1100 | if (ret) { |
| 1055 | if (ret != -ENODEV) | 1101 | if (ret != -ENODEV) |
| @@ -1064,16 +1110,13 @@ err_mem_free: | |||
| 1064 | hid_destroy_device(hid); | 1110 | hid_destroy_device(hid); |
| 1065 | 1111 | ||
| 1066 | err_irq: | 1112 | err_irq: |
| 1067 | free_irq(ihid->irq, ihid); | 1113 | free_irq(client->irq, ihid); |
| 1068 | 1114 | ||
| 1069 | err_pm: | 1115 | err_pm: |
| 1070 | pm_runtime_put_noidle(&client->dev); | 1116 | pm_runtime_put_noidle(&client->dev); |
| 1071 | pm_runtime_disable(&client->dev); | 1117 | pm_runtime_disable(&client->dev); |
| 1072 | 1118 | ||
| 1073 | err: | 1119 | err: |
| 1074 | if (ihid->desc) | ||
| 1075 | gpiod_put(ihid->desc); | ||
| 1076 | |||
| 1077 | i2c_hid_free_buffers(ihid); | 1120 | i2c_hid_free_buffers(ihid); |
| 1078 | kfree(ihid); | 1121 | kfree(ihid); |
| 1079 | return ret; | 1122 | return ret; |
| @@ -1092,18 +1135,13 @@ static int i2c_hid_remove(struct i2c_client *client) | |||
| 1092 | hid = ihid->hid; | 1135 | hid = ihid->hid; |
| 1093 | hid_destroy_device(hid); | 1136 | hid_destroy_device(hid); |
| 1094 | 1137 | ||
| 1095 | free_irq(ihid->irq, ihid); | 1138 | free_irq(client->irq, ihid); |
| 1096 | 1139 | ||
| 1097 | if (ihid->bufsize) | 1140 | if (ihid->bufsize) |
| 1098 | i2c_hid_free_buffers(ihid); | 1141 | i2c_hid_free_buffers(ihid); |
| 1099 | 1142 | ||
| 1100 | if (ihid->desc) | ||
| 1101 | gpiod_put(ihid->desc); | ||
| 1102 | |||
| 1103 | kfree(ihid); | 1143 | kfree(ihid); |
| 1104 | 1144 | ||
| 1105 | acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev)); | ||
| 1106 | |||
| 1107 | return 0; | 1145 | return 0; |
| 1108 | } | 1146 | } |
| 1109 | 1147 | ||
| @@ -1142,11 +1180,11 @@ static int i2c_hid_suspend(struct device *dev) | |||
| 1142 | /* Save some power */ | 1180 | /* Save some power */ |
| 1143 | i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); | 1181 | i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); |
| 1144 | 1182 | ||
| 1145 | disable_irq(ihid->irq); | 1183 | disable_irq(client->irq); |
| 1146 | } | 1184 | } |
| 1147 | 1185 | ||
| 1148 | if (device_may_wakeup(&client->dev)) { | 1186 | if (device_may_wakeup(&client->dev)) { |
| 1149 | wake_status = enable_irq_wake(ihid->irq); | 1187 | wake_status = enable_irq_wake(client->irq); |
| 1150 | if (!wake_status) | 1188 | if (!wake_status) |
| 1151 | ihid->irq_wake_enabled = true; | 1189 | ihid->irq_wake_enabled = true; |
| 1152 | else | 1190 | else |
| @@ -1166,7 +1204,7 @@ static int i2c_hid_resume(struct device *dev) | |||
| 1166 | int wake_status; | 1204 | int wake_status; |
| 1167 | 1205 | ||
| 1168 | if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) { | 1206 | if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) { |
| 1169 | wake_status = disable_irq_wake(ihid->irq); | 1207 | wake_status = disable_irq_wake(client->irq); |
| 1170 | if (!wake_status) | 1208 | if (!wake_status) |
| 1171 | ihid->irq_wake_enabled = false; | 1209 | ihid->irq_wake_enabled = false; |
| 1172 | else | 1210 | else |
| @@ -1179,7 +1217,7 @@ static int i2c_hid_resume(struct device *dev) | |||
| 1179 | pm_runtime_set_active(dev); | 1217 | pm_runtime_set_active(dev); |
| 1180 | pm_runtime_enable(dev); | 1218 | pm_runtime_enable(dev); |
| 1181 | 1219 | ||
| 1182 | enable_irq(ihid->irq); | 1220 | enable_irq(client->irq); |
| 1183 | ret = i2c_hid_hwreset(client); | 1221 | ret = i2c_hid_hwreset(client); |
| 1184 | if (ret) | 1222 | if (ret) |
| 1185 | return ret; | 1223 | return ret; |
| @@ -1197,19 +1235,17 @@ static int i2c_hid_resume(struct device *dev) | |||
| 1197 | static int i2c_hid_runtime_suspend(struct device *dev) | 1235 | static int i2c_hid_runtime_suspend(struct device *dev) |
| 1198 | { | 1236 | { |
| 1199 | struct i2c_client *client = to_i2c_client(dev); | 1237 | struct i2c_client *client = to_i2c_client(dev); |
| 1200 | struct i2c_hid *ihid = i2c_get_clientdata(client); | ||
| 1201 | 1238 | ||
| 1202 | i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); | 1239 | i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); |
| 1203 | disable_irq(ihid->irq); | 1240 | disable_irq(client->irq); |
| 1204 | return 0; | 1241 | return 0; |
| 1205 | } | 1242 | } |
| 1206 | 1243 | ||
| 1207 | static int i2c_hid_runtime_resume(struct device *dev) | 1244 | static int i2c_hid_runtime_resume(struct device *dev) |
| 1208 | { | 1245 | { |
| 1209 | struct i2c_client *client = to_i2c_client(dev); | 1246 | struct i2c_client *client = to_i2c_client(dev); |
| 1210 | struct i2c_hid *ihid = i2c_get_clientdata(client); | ||
| 1211 | 1247 | ||
| 1212 | enable_irq(ihid->irq); | 1248 | enable_irq(client->irq); |
| 1213 | i2c_hid_set_power(client, I2C_HID_PWR_ON); | 1249 | i2c_hid_set_power(client, I2C_HID_PWR_ON); |
| 1214 | return 0; | 1250 | return 0; |
| 1215 | } | 1251 | } |
diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index 0c9ac4d5d850..842d8416a7a6 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
| 20 | #include "client.h" | 20 | #include "client.h" |
| 21 | #include "hw-ish.h" | 21 | #include "hw-ish.h" |
| 22 | #include "utils.h" | ||
| 23 | #include "hbm.h" | 22 | #include "hbm.h" |
| 24 | 23 | ||
| 25 | /* For FW reset flow */ | 24 | /* For FW reset flow */ |
| @@ -310,6 +309,7 @@ static int write_ipc_from_queue(struct ishtp_device *dev) | |||
| 310 | ((uint32_t)tv_utc.tv_usec); | 309 | ((uint32_t)tv_utc.tv_usec); |
| 311 | ts_format.ts1_source = HOST_SYSTEM_TIME_USEC; | 310 | ts_format.ts1_source = HOST_SYSTEM_TIME_USEC; |
| 312 | ts_format.ts2_source = HOST_UTC_TIME_USEC; | 311 | ts_format.ts2_source = HOST_UTC_TIME_USEC; |
| 312 | ts_format.reserved = 0; | ||
| 313 | 313 | ||
| 314 | time_update.primary_host_time = usec_system; | 314 | time_update.primary_host_time = usec_system; |
| 315 | time_update.secondary_host_time = usec_utc; | 315 | time_update.secondary_host_time = usec_utc; |
| @@ -427,6 +427,59 @@ static int ipc_send_mng_msg(struct ishtp_device *dev, uint32_t msg_code, | |||
| 427 | sizeof(uint32_t) + size); | 427 | sizeof(uint32_t) + size); |
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | #define WAIT_FOR_FW_RDY 0x1 | ||
| 431 | #define WAIT_FOR_INPUT_RDY 0x2 | ||
| 432 | |||
| 433 | /** | ||
| 434 | * timed_wait_for_timeout() - wait special event with timeout | ||
| 435 | * @dev: ISHTP device pointer | ||
| 436 | * @condition: indicate the condition for waiting | ||
| 437 | * @timeinc: time slice for every wait cycle, in ms | ||
| 438 | * @timeout: time in ms for timeout | ||
| 439 | * | ||
| 440 | * This function will check special event to be ready in a loop, the loop | ||
| 441 | * period is specificd in timeinc. Wait timeout will causes failure. | ||
| 442 | * | ||
| 443 | * Return: 0 for success else failure code | ||
| 444 | */ | ||
| 445 | static int timed_wait_for_timeout(struct ishtp_device *dev, int condition, | ||
| 446 | unsigned int timeinc, unsigned int timeout) | ||
| 447 | { | ||
| 448 | bool complete = false; | ||
| 449 | int ret; | ||
| 450 | |||
| 451 | do { | ||
| 452 | if (condition == WAIT_FOR_FW_RDY) { | ||
| 453 | complete = ishtp_fw_is_ready(dev); | ||
| 454 | } else if (condition == WAIT_FOR_INPUT_RDY) { | ||
| 455 | complete = ish_is_input_ready(dev); | ||
| 456 | } else { | ||
| 457 | ret = -EINVAL; | ||
| 458 | goto out; | ||
| 459 | } | ||
| 460 | |||
| 461 | if (!complete) { | ||
| 462 | unsigned long left_time; | ||
| 463 | |||
| 464 | left_time = msleep_interruptible(timeinc); | ||
| 465 | timeout -= (timeinc - left_time); | ||
| 466 | } | ||
| 467 | } while (!complete && timeout > 0); | ||
| 468 | |||
| 469 | if (complete) | ||
| 470 | ret = 0; | ||
| 471 | else | ||
| 472 | ret = -EBUSY; | ||
| 473 | |||
| 474 | out: | ||
| 475 | return ret; | ||
| 476 | } | ||
| 477 | |||
| 478 | #define TIME_SLICE_FOR_FW_RDY_MS 100 | ||
| 479 | #define TIME_SLICE_FOR_INPUT_RDY_MS 100 | ||
| 480 | #define TIMEOUT_FOR_FW_RDY_MS 2000 | ||
| 481 | #define TIMEOUT_FOR_INPUT_RDY_MS 2000 | ||
| 482 | |||
| 430 | /** | 483 | /** |
| 431 | * ish_fw_reset_handler() - FW reset handler | 484 | * ish_fw_reset_handler() - FW reset handler |
| 432 | * @dev: ishtp device pointer | 485 | * @dev: ishtp device pointer |
| @@ -456,8 +509,8 @@ static int ish_fw_reset_handler(struct ishtp_device *dev) | |||
| 456 | ishtp_reset_handler(dev); | 509 | ishtp_reset_handler(dev); |
| 457 | 510 | ||
| 458 | if (!ish_is_input_ready(dev)) | 511 | if (!ish_is_input_ready(dev)) |
| 459 | timed_wait_for_timeout(WAIT_FOR_SEND_SLICE, | 512 | timed_wait_for_timeout(dev, WAIT_FOR_INPUT_RDY, |
| 460 | ish_is_input_ready(dev), (2 * HZ)); | 513 | TIME_SLICE_FOR_INPUT_RDY_MS, TIMEOUT_FOR_INPUT_RDY_MS); |
| 461 | 514 | ||
| 462 | /* ISH FW is dead */ | 515 | /* ISH FW is dead */ |
| 463 | if (!ish_is_input_ready(dev)) | 516 | if (!ish_is_input_ready(dev)) |
| @@ -472,8 +525,8 @@ static int ish_fw_reset_handler(struct ishtp_device *dev) | |||
| 472 | sizeof(uint32_t)); | 525 | sizeof(uint32_t)); |
| 473 | 526 | ||
| 474 | /* Wait for ISH FW'es ILUP and ISHTP_READY */ | 527 | /* Wait for ISH FW'es ILUP and ISHTP_READY */ |
| 475 | timed_wait_for_timeout(WAIT_FOR_SEND_SLICE, ishtp_fw_is_ready(dev), | 528 | timed_wait_for_timeout(dev, WAIT_FOR_FW_RDY, |
| 476 | (2 * HZ)); | 529 | TIME_SLICE_FOR_FW_RDY_MS, TIMEOUT_FOR_FW_RDY_MS); |
| 477 | if (!ishtp_fw_is_ready(dev)) { | 530 | if (!ishtp_fw_is_ready(dev)) { |
| 478 | /* ISH FW is dead */ | 531 | /* ISH FW is dead */ |
| 479 | uint32_t ish_status; | 532 | uint32_t ish_status; |
| @@ -487,6 +540,8 @@ static int ish_fw_reset_handler(struct ishtp_device *dev) | |||
| 487 | return 0; | 540 | return 0; |
| 488 | } | 541 | } |
| 489 | 542 | ||
| 543 | #define TIMEOUT_FOR_HW_RDY_MS 300 | ||
| 544 | |||
| 490 | /** | 545 | /** |
| 491 | * ish_fw_reset_work_fn() - FW reset worker function | 546 | * ish_fw_reset_work_fn() - FW reset worker function |
| 492 | * @unused: not used | 547 | * @unused: not used |
| @@ -500,7 +555,7 @@ static void fw_reset_work_fn(struct work_struct *unused) | |||
| 500 | rv = ish_fw_reset_handler(ishtp_dev); | 555 | rv = ish_fw_reset_handler(ishtp_dev); |
| 501 | if (!rv) { | 556 | if (!rv) { |
| 502 | /* ISH is ILUP & ISHTP-ready. Restart ISHTP */ | 557 | /* ISH is ILUP & ISHTP-ready. Restart ISHTP */ |
| 503 | schedule_timeout(HZ / 3); | 558 | msleep_interruptible(TIMEOUT_FOR_HW_RDY_MS); |
| 504 | ishtp_dev->recvd_hw_ready = 1; | 559 | ishtp_dev->recvd_hw_ready = 1; |
| 505 | wake_up_interruptible(&ishtp_dev->wait_hw_ready); | 560 | wake_up_interruptible(&ishtp_dev->wait_hw_ready); |
| 506 | 561 | ||
diff --git a/drivers/hid/intel-ish-hid/ipc/utils.h b/drivers/hid/intel-ish-hid/ipc/utils.h deleted file mode 100644 index 5a82123dc7b4..000000000000 --- a/drivers/hid/intel-ish-hid/ipc/utils.h +++ /dev/null | |||
| @@ -1,64 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Utility macros of ISH | ||
| 3 | * | ||
| 4 | * Copyright (c) 2014-2016, Intel Corporation. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 13 | * more details. | ||
| 14 | */ | ||
| 15 | #ifndef UTILS__H | ||
| 16 | #define UTILS__H | ||
| 17 | |||
| 18 | #define WAIT_FOR_SEND_SLICE (HZ / 10) | ||
| 19 | #define WAIT_FOR_CONNECT_SLICE (HZ / 10) | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Waits for specified event when a thread that triggers event can't signal | ||
| 23 | * Also, waits *at_least* `timeinc` after condition is satisfied | ||
| 24 | */ | ||
| 25 | #define timed_wait_for(timeinc, condition) \ | ||
| 26 | do { \ | ||
| 27 | int completed = 0; \ | ||
| 28 | do { \ | ||
| 29 | unsigned long j; \ | ||
| 30 | int done = 0; \ | ||
| 31 | \ | ||
| 32 | completed = (condition); \ | ||
| 33 | for (j = jiffies, done = 0; !done; ) { \ | ||
| 34 | schedule_timeout(timeinc); \ | ||
| 35 | if (time_is_before_eq_jiffies(j + timeinc)) \ | ||
| 36 | done = 1; \ | ||
| 37 | } \ | ||
| 38 | } while (!(completed)); \ | ||
| 39 | } while (0) | ||
| 40 | |||
| 41 | |||
| 42 | /* | ||
| 43 | * Waits for specified event when a thread that triggers event | ||
| 44 | * can't signal with timeout (use whenever we may hang) | ||
| 45 | */ | ||
| 46 | #define timed_wait_for_timeout(timeinc, condition, timeout) \ | ||
| 47 | do { \ | ||
| 48 | int t = timeout; \ | ||
| 49 | do { \ | ||
| 50 | unsigned long j; \ | ||
| 51 | int done = 0; \ | ||
| 52 | \ | ||
| 53 | for (j = jiffies, done = 0; !done; ) { \ | ||
| 54 | schedule_timeout(timeinc); \ | ||
| 55 | if (time_is_before_eq_jiffies(j + timeinc)) \ | ||
| 56 | done = 1; \ | ||
| 57 | } \ | ||
| 58 | t -= timeinc; \ | ||
| 59 | if (t <= 0) \ | ||
| 60 | break; \ | ||
| 61 | } while (!(condition)); \ | ||
| 62 | } while (0) | ||
| 63 | |||
| 64 | #endif /* UTILS__H */ | ||
diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c index 256521509d20..f4cbc744e657 100644 --- a/drivers/hid/intel-ish-hid/ishtp/bus.c +++ b/drivers/hid/intel-ish-hid/ishtp/bus.c | |||
| @@ -585,14 +585,7 @@ int ishtp_bus_new_client(struct ishtp_device *dev) | |||
| 585 | */ | 585 | */ |
| 586 | i = dev->fw_client_presentation_num - 1; | 586 | i = dev->fw_client_presentation_num - 1; |
| 587 | device_uuid = dev->fw_clients[i].props.protocol_name; | 587 | device_uuid = dev->fw_clients[i].props.protocol_name; |
| 588 | dev_name = kasprintf(GFP_KERNEL, | 588 | dev_name = kasprintf(GFP_KERNEL, "{%pUL}", device_uuid.b); |
| 589 | "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", | ||
| 590 | device_uuid.b[3], device_uuid.b[2], device_uuid.b[1], | ||
| 591 | device_uuid.b[0], device_uuid.b[5], device_uuid.b[4], | ||
| 592 | device_uuid.b[7], device_uuid.b[6], device_uuid.b[8], | ||
| 593 | device_uuid.b[9], device_uuid.b[10], device_uuid.b[11], | ||
| 594 | device_uuid.b[12], device_uuid.b[13], device_uuid.b[14], | ||
| 595 | device_uuid.b[15]); | ||
| 596 | if (!dev_name) | 589 | if (!dev_name) |
| 597 | return -ENOMEM; | 590 | return -ENOMEM; |
| 598 | 591 | ||
diff --git a/drivers/hid/intel-ish-hid/ishtp/hbm.c b/drivers/hid/intel-ish-hid/ishtp/hbm.c index 74bffee60774..59460b66e689 100644 --- a/drivers/hid/intel-ish-hid/ishtp/hbm.c +++ b/drivers/hid/intel-ish-hid/ishtp/hbm.c | |||
| @@ -378,11 +378,10 @@ static void ishtp_hbm_cl_disconnect_res(struct ishtp_device *dev, | |||
| 378 | list_for_each_entry(cl, &dev->cl_list, link) { | 378 | list_for_each_entry(cl, &dev->cl_list, link) { |
| 379 | if (!rs->status && ishtp_hbm_cl_addr_equal(cl, rs)) { | 379 | if (!rs->status && ishtp_hbm_cl_addr_equal(cl, rs)) { |
| 380 | cl->state = ISHTP_CL_DISCONNECTED; | 380 | cl->state = ISHTP_CL_DISCONNECTED; |
| 381 | wake_up_interruptible(&cl->wait_ctrl_res); | ||
| 381 | break; | 382 | break; |
| 382 | } | 383 | } |
| 383 | } | 384 | } |
| 384 | if (cl) | ||
| 385 | wake_up_interruptible(&cl->wait_ctrl_res); | ||
| 386 | spin_unlock_irqrestore(&dev->cl_list_lock, flags); | 385 | spin_unlock_irqrestore(&dev->cl_list_lock, flags); |
| 387 | } | 386 | } |
| 388 | 387 | ||
| @@ -431,11 +430,10 @@ static void ishtp_hbm_cl_connect_res(struct ishtp_device *dev, | |||
| 431 | cl->state = ISHTP_CL_DISCONNECTED; | 430 | cl->state = ISHTP_CL_DISCONNECTED; |
| 432 | cl->status = -ENODEV; | 431 | cl->status = -ENODEV; |
| 433 | } | 432 | } |
| 433 | wake_up_interruptible(&cl->wait_ctrl_res); | ||
| 434 | break; | 434 | break; |
| 435 | } | 435 | } |
| 436 | } | 436 | } |
| 437 | if (cl) | ||
| 438 | wake_up_interruptible(&cl->wait_ctrl_res); | ||
| 439 | spin_unlock_irqrestore(&dev->cl_list_lock, flags); | 437 | spin_unlock_irqrestore(&dev->cl_list_lock, flags); |
| 440 | } | 438 | } |
| 441 | 439 | ||
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index ae83af649a60..333108ef18cf 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -1459,7 +1459,7 @@ static int hid_post_reset(struct usb_interface *intf) | |||
| 1459 | rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL); | 1459 | rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL); |
| 1460 | if (!rdesc) { | 1460 | if (!rdesc) { |
| 1461 | dbg_hid("couldn't allocate rdesc memory (post_reset)\n"); | 1461 | dbg_hid("couldn't allocate rdesc memory (post_reset)\n"); |
| 1462 | return 1; | 1462 | return -ENOMEM; |
| 1463 | } | 1463 | } |
| 1464 | status = hid_get_class_descriptor(dev, | 1464 | status = hid_get_class_descriptor(dev, |
| 1465 | interface->desc.bInterfaceNumber, | 1465 | interface->desc.bInterfaceNumber, |
| @@ -1467,13 +1467,13 @@ static int hid_post_reset(struct usb_interface *intf) | |||
| 1467 | if (status < 0) { | 1467 | if (status < 0) { |
| 1468 | dbg_hid("reading report descriptor failed (post_reset)\n"); | 1468 | dbg_hid("reading report descriptor failed (post_reset)\n"); |
| 1469 | kfree(rdesc); | 1469 | kfree(rdesc); |
| 1470 | return 1; | 1470 | return status; |
| 1471 | } | 1471 | } |
| 1472 | status = memcmp(rdesc, hid->dev_rdesc, hid->dev_rsize); | 1472 | status = memcmp(rdesc, hid->dev_rdesc, hid->dev_rsize); |
| 1473 | kfree(rdesc); | 1473 | kfree(rdesc); |
| 1474 | if (status != 0) { | 1474 | if (status != 0) { |
| 1475 | dbg_hid("report descriptor changed\n"); | 1475 | dbg_hid("report descriptor changed\n"); |
| 1476 | return 1; | 1476 | return -EPERM; |
| 1477 | } | 1477 | } |
| 1478 | 1478 | ||
| 1479 | /* No need to do another reset or clear a halted endpoint */ | 1479 | /* No need to do another reset or clear a halted endpoint */ |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index e6cfd323babc..b3e01c82af05 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -82,6 +82,8 @@ static const struct hid_blacklist { | |||
| 82 | { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET }, | 82 | { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET }, |
| 83 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, | 83 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, |
| 84 | { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT }, | 84 | { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT }, |
| 85 | { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3, HID_QUIRK_MULTI_INPUT }, | ||
| 86 | { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE, HID_QUIRK_MULTI_INPUT }, | ||
| 85 | { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL }, | 87 | { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL }, |
| 86 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 88 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
| 87 | { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, | 89 | { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, |
| @@ -101,8 +103,9 @@ static const struct hid_blacklist { | |||
| 101 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS }, | 103 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS }, |
| 102 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS }, | 104 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS }, |
| 103 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS }, | 105 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS }, |
| 106 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4, HID_QUIRK_NO_INIT_REPORTS }, | ||
| 107 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2, HID_QUIRK_NO_INIT_REPORTS }, | ||
| 104 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP, HID_QUIRK_NO_INIT_REPORTS }, | 108 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP, HID_QUIRK_NO_INIT_REPORTS }, |
| 105 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, | ||
| 106 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, | 109 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, |
| 107 | { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, | 110 | { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, |
| 108 | { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, | 111 | { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, |
diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index b4800ea891cb..d303e413306d 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h | |||
| @@ -210,7 +210,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
| 210 | struct wacom_wac *wacom_wac); | 210 | struct wacom_wac *wacom_wac); |
| 211 | void wacom_wac_usage_mapping(struct hid_device *hdev, | 211 | void wacom_wac_usage_mapping(struct hid_device *hdev, |
| 212 | struct hid_field *field, struct hid_usage *usage); | 212 | struct hid_field *field, struct hid_usage *usage); |
| 213 | int wacom_wac_event(struct hid_device *hdev, struct hid_field *field, | 213 | void wacom_wac_event(struct hid_device *hdev, struct hid_field *field, |
| 214 | struct hid_usage *usage, __s32 value); | 214 | struct hid_usage *usage, __s32 value); |
| 215 | void wacom_wac_report(struct hid_device *hdev, struct hid_report *report); | 215 | void wacom_wac_report(struct hid_device *hdev, struct hid_report *report); |
| 216 | void wacom_battery_work(struct work_struct *work); | 216 | void wacom_battery_work(struct work_struct *work); |
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 5e7a5648e708..b9779bcbd140 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c | |||
| @@ -122,6 +122,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, | |||
| 122 | struct hid_data *hid_data = &wacom->wacom_wac.hid_data; | 122 | struct hid_data *hid_data = &wacom->wacom_wac.hid_data; |
| 123 | u8 *data; | 123 | u8 *data; |
| 124 | int ret; | 124 | int ret; |
| 125 | int n; | ||
| 125 | 126 | ||
| 126 | switch (usage->hid) { | 127 | switch (usage->hid) { |
| 127 | case HID_DG_CONTACTMAX: | 128 | case HID_DG_CONTACTMAX: |
| @@ -159,22 +160,48 @@ static void wacom_feature_mapping(struct hid_device *hdev, | |||
| 159 | 160 | ||
| 160 | case HID_UP_DIGITIZER: | 161 | case HID_UP_DIGITIZER: |
| 161 | if (field->report->id == 0x0B && | 162 | if (field->report->id == 0x0B && |
| 162 | (field->application == WACOM_G9_DIGITIZER || | 163 | (field->application == WACOM_HID_G9_PEN || |
| 163 | field->application == WACOM_G11_DIGITIZER)) { | 164 | field->application == WACOM_HID_G11_PEN)) { |
| 164 | wacom->wacom_wac.mode_report = field->report->id; | 165 | wacom->wacom_wac.mode_report = field->report->id; |
| 165 | wacom->wacom_wac.mode_value = 0; | 166 | wacom->wacom_wac.mode_value = 0; |
| 166 | } | 167 | } |
| 167 | break; | 168 | break; |
| 168 | 169 | ||
| 169 | case WACOM_G9_PAGE: | 170 | case WACOM_HID_WD_DATAMODE: |
| 170 | case WACOM_G11_PAGE: | 171 | wacom->wacom_wac.mode_report = field->report->id; |
| 172 | wacom->wacom_wac.mode_value = 2; | ||
| 173 | break; | ||
| 174 | |||
| 175 | case WACOM_HID_UP_G9: | ||
| 176 | case WACOM_HID_UP_G11: | ||
| 171 | if (field->report->id == 0x03 && | 177 | if (field->report->id == 0x03 && |
| 172 | (field->application == WACOM_G9_TOUCHSCREEN || | 178 | (field->application == WACOM_HID_G9_TOUCHSCREEN || |
| 173 | field->application == WACOM_G11_TOUCHSCREEN)) { | 179 | field->application == WACOM_HID_G11_TOUCHSCREEN)) { |
| 174 | wacom->wacom_wac.mode_report = field->report->id; | 180 | wacom->wacom_wac.mode_report = field->report->id; |
| 175 | wacom->wacom_wac.mode_value = 0; | 181 | wacom->wacom_wac.mode_value = 0; |
| 176 | } | 182 | } |
| 177 | break; | 183 | break; |
| 184 | case WACOM_HID_WD_OFFSETLEFT: | ||
| 185 | case WACOM_HID_WD_OFFSETTOP: | ||
| 186 | case WACOM_HID_WD_OFFSETRIGHT: | ||
| 187 | case WACOM_HID_WD_OFFSETBOTTOM: | ||
| 188 | /* read manually */ | ||
| 189 | n = hid_report_len(field->report); | ||
| 190 | data = hid_alloc_report_buf(field->report, GFP_KERNEL); | ||
| 191 | if (!data) | ||
| 192 | break; | ||
| 193 | data[0] = field->report->id; | ||
| 194 | ret = wacom_get_report(hdev, HID_FEATURE_REPORT, | ||
| 195 | data, n, WAC_CMD_RETRIES); | ||
| 196 | if (ret == n) { | ||
| 197 | ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, | ||
| 198 | data, n, 0); | ||
| 199 | } else { | ||
| 200 | hid_warn(hdev, "%s: could not retrieve sensor offsets\n", | ||
| 201 | __func__); | ||
| 202 | } | ||
| 203 | kfree(data); | ||
| 204 | break; | ||
| 178 | } | 205 | } |
| 179 | } | 206 | } |
| 180 | 207 | ||
| @@ -240,6 +267,30 @@ static void wacom_usage_mapping(struct hid_device *hdev, | |||
| 240 | features->touch_max = 1; | 267 | features->touch_max = 1; |
| 241 | } | 268 | } |
| 242 | 269 | ||
| 270 | /* | ||
| 271 | * ISDv4 devices which predate HID's adoption of the | ||
| 272 | * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its | ||
| 273 | * position instead. We can accurately detect if a | ||
| 274 | * usage with that value should be HID_DG_BARRELSWITCH2 | ||
| 275 | * based on the surrounding usages, which have remained | ||
| 276 | * constant across generations. | ||
| 277 | */ | ||
| 278 | if (features->type == HID_GENERIC && | ||
| 279 | usage->hid == 0x000D0000 && | ||
| 280 | field->application == HID_DG_PEN && | ||
| 281 | field->physical == HID_DG_STYLUS) { | ||
| 282 | int i = usage->usage_index; | ||
| 283 | |||
| 284 | if (i-4 >= 0 && i+1 < field->maxusage && | ||
| 285 | field->usage[i-4].hid == HID_DG_TIPSWITCH && | ||
| 286 | field->usage[i-3].hid == HID_DG_BARRELSWITCH && | ||
| 287 | field->usage[i-2].hid == HID_DG_ERASER && | ||
| 288 | field->usage[i-1].hid == HID_DG_INVERT && | ||
| 289 | field->usage[i+1].hid == HID_DG_INRANGE) { | ||
| 290 | usage->hid = HID_DG_BARRELSWITCH2; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 243 | switch (usage->hid) { | 294 | switch (usage->hid) { |
| 244 | case HID_GD_X: | 295 | case HID_GD_X: |
| 245 | features->x_max = field->logical_maximum; | 296 | features->x_max = field->logical_maximum; |
| @@ -689,11 +740,6 @@ static int wacom_add_shared_data(struct hid_device *hdev) | |||
| 689 | return retval; | 740 | return retval; |
| 690 | } | 741 | } |
| 691 | 742 | ||
| 692 | if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) | ||
| 693 | wacom_wac->shared->touch = hdev; | ||
| 694 | else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) | ||
| 695 | wacom_wac->shared->pen = hdev; | ||
| 696 | |||
| 697 | out: | 743 | out: |
| 698 | mutex_unlock(&wacom_udev_list_lock); | 744 | mutex_unlock(&wacom_udev_list_lock); |
| 699 | return retval; | 745 | return retval; |
| @@ -1916,6 +1962,19 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) | |||
| 1916 | /* shift everything including the terminator */ | 1962 | /* shift everything including the terminator */ |
| 1917 | memmove(gap, gap+1, strlen(gap)); | 1963 | memmove(gap, gap+1, strlen(gap)); |
| 1918 | } | 1964 | } |
| 1965 | |||
| 1966 | /* strip off excessive prefixing */ | ||
| 1967 | if (strstr(name, "Wacom Co.,Ltd. Wacom ") == name) { | ||
| 1968 | int n = strlen(name); | ||
| 1969 | int x = strlen("Wacom Co.,Ltd. "); | ||
| 1970 | memmove(name, name+x, n-x+1); | ||
| 1971 | } | ||
| 1972 | if (strstr(name, "Wacom Co., Ltd. Wacom ") == name) { | ||
| 1973 | int n = strlen(name); | ||
| 1974 | int x = strlen("Wacom Co., Ltd. "); | ||
| 1975 | memmove(name, name+x, n-x+1); | ||
| 1976 | } | ||
| 1977 | |||
| 1919 | /* get rid of trailing whitespace */ | 1978 | /* get rid of trailing whitespace */ |
| 1920 | if (name[strlen(name)-1] == ' ') | 1979 | if (name[strlen(name)-1] == ' ') |
| 1921 | name[strlen(name)-1] = '\0'; | 1980 | name[strlen(name)-1] = '\0'; |
| @@ -1977,6 +2036,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) | |||
| 1977 | if (error) | 2036 | if (error) |
| 1978 | goto fail; | 2037 | goto fail; |
| 1979 | 2038 | ||
| 2039 | error = wacom_add_shared_data(hdev); | ||
| 2040 | if (error) | ||
| 2041 | goto fail; | ||
| 2042 | |||
| 1980 | /* | 2043 | /* |
| 1981 | * Bamboo Pad has a generic hid handling for the Pen, and we switch it | 2044 | * Bamboo Pad has a generic hid handling for the Pen, and we switch it |
| 1982 | * into debug mode for the touch part. | 2045 | * into debug mode for the touch part. |
| @@ -2017,9 +2080,10 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) | |||
| 2017 | 2080 | ||
| 2018 | wacom_update_name(wacom, wireless ? " (WL)" : ""); | 2081 | wacom_update_name(wacom, wireless ? " (WL)" : ""); |
| 2019 | 2082 | ||
| 2020 | error = wacom_add_shared_data(hdev); | 2083 | if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) |
| 2021 | if (error) | 2084 | wacom_wac->shared->touch = hdev; |
| 2022 | goto fail; | 2085 | else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) |
| 2086 | wacom_wac->shared->pen = hdev; | ||
| 2023 | 2087 | ||
| 2024 | if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) && | 2088 | if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) && |
| 2025 | (features->quirks & WACOM_QUIRK_BATTERY)) { | 2089 | (features->quirks & WACOM_QUIRK_BATTERY)) { |
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 1cb79925730d..b1a9a3ca6d56 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c | |||
| @@ -41,6 +41,8 @@ MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)"); | |||
| 41 | static void wacom_report_numbered_buttons(struct input_dev *input_dev, | 41 | static void wacom_report_numbered_buttons(struct input_dev *input_dev, |
| 42 | int button_count, int mask); | 42 | int button_count, int mask); |
| 43 | 43 | ||
| 44 | static int wacom_numbered_button_to_key(int n); | ||
| 45 | |||
| 44 | /* | 46 | /* |
| 45 | * Percent of battery capacity for Graphire. | 47 | * Percent of battery capacity for Graphire. |
| 46 | * 8th value means AC online and show 100% capacity. | 48 | * 8th value means AC online and show 100% capacity. |
| @@ -588,6 +590,11 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) | |||
| 588 | return 1; | 590 | return 1; |
| 589 | } | 591 | } |
| 590 | 592 | ||
| 593 | static int wacom_intuos_id_mangle(int tool_id) | ||
| 594 | { | ||
| 595 | return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF); | ||
| 596 | } | ||
| 597 | |||
| 591 | static int wacom_intuos_get_tool_type(int tool_id) | 598 | static int wacom_intuos_get_tool_type(int tool_id) |
| 592 | { | 599 | { |
| 593 | int tool_type; | 600 | int tool_type; |
| @@ -595,7 +602,7 @@ static int wacom_intuos_get_tool_type(int tool_id) | |||
| 595 | switch (tool_id) { | 602 | switch (tool_id) { |
| 596 | case 0x812: /* Inking pen */ | 603 | case 0x812: /* Inking pen */ |
| 597 | case 0x801: /* Intuos3 Inking pen */ | 604 | case 0x801: /* Intuos3 Inking pen */ |
| 598 | case 0x120802: /* Intuos4/5 Inking Pen */ | 605 | case 0x12802: /* Intuos4/5 Inking Pen */ |
| 599 | case 0x012: | 606 | case 0x012: |
| 600 | tool_type = BTN_TOOL_PENCIL; | 607 | tool_type = BTN_TOOL_PENCIL; |
| 601 | break; | 608 | break; |
| @@ -610,11 +617,11 @@ static int wacom_intuos_get_tool_type(int tool_id) | |||
| 610 | case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ | 617 | case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ |
| 611 | case 0x8e2: /* IntuosHT2 pen */ | 618 | case 0x8e2: /* IntuosHT2 pen */ |
| 612 | case 0x022: | 619 | case 0x022: |
| 613 | case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */ | 620 | case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */ |
| 614 | case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */ | 621 | case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */ |
| 615 | case 0x160802: /* Cintiq 13HD Pro Pen */ | 622 | case 0x16802: /* Cintiq 13HD Pro Pen */ |
| 616 | case 0x180802: /* DTH2242 Pen */ | 623 | case 0x18802: /* DTH2242 Pen */ |
| 617 | case 0x100802: /* Intuos4/5 13HD/24HD General Pen */ | 624 | case 0x10802: /* Intuos4/5 13HD/24HD General Pen */ |
| 618 | tool_type = BTN_TOOL_PEN; | 625 | tool_type = BTN_TOOL_PEN; |
| 619 | break; | 626 | break; |
| 620 | 627 | ||
| @@ -638,6 +645,7 @@ static int wacom_intuos_get_tool_type(int tool_id) | |||
| 638 | break; | 645 | break; |
| 639 | 646 | ||
| 640 | case 0x82a: /* Eraser */ | 647 | case 0x82a: /* Eraser */ |
| 648 | case 0x84a: | ||
| 641 | case 0x85a: | 649 | case 0x85a: |
| 642 | case 0x91a: | 650 | case 0x91a: |
| 643 | case 0xd1a: | 651 | case 0xd1a: |
| @@ -648,12 +656,12 @@ static int wacom_intuos_get_tool_type(int tool_id) | |||
| 648 | case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */ | 656 | case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */ |
| 649 | case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */ | 657 | case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */ |
| 650 | case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ | 658 | case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ |
| 651 | case 0x14080a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */ | 659 | case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */ |
| 652 | case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ | 660 | case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ |
| 653 | case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */ | 661 | case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */ |
| 654 | case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */ | 662 | case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */ |
| 655 | case 0x18080a: /* DTH2242 Eraser */ | 663 | case 0x1880a: /* DTH2242 Eraser */ |
| 656 | case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */ | 664 | case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */ |
| 657 | tool_type = BTN_TOOL_RUBBER; | 665 | tool_type = BTN_TOOL_RUBBER; |
| 658 | break; | 666 | break; |
| 659 | 667 | ||
| @@ -662,7 +670,7 @@ static int wacom_intuos_get_tool_type(int tool_id) | |||
| 662 | case 0x112: | 670 | case 0x112: |
| 663 | case 0x913: /* Intuos3 Airbrush */ | 671 | case 0x913: /* Intuos3 Airbrush */ |
| 664 | case 0x902: /* Intuos4/5 13HD/24HD Airbrush */ | 672 | case 0x902: /* Intuos4/5 13HD/24HD Airbrush */ |
| 665 | case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */ | 673 | case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */ |
| 666 | tool_type = BTN_TOOL_AIRBRUSH; | 674 | tool_type = BTN_TOOL_AIRBRUSH; |
| 667 | break; | 675 | break; |
| 668 | 676 | ||
| @@ -693,7 +701,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) | |||
| 693 | (data[6] << 4) + (data[7] >> 4); | 701 | (data[6] << 4) + (data[7] >> 4); |
| 694 | 702 | ||
| 695 | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) | | 703 | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) | |
| 696 | ((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12); | 704 | ((data[7] & 0x0f) << 16) | ((data[8] & 0xf0) << 8); |
| 697 | 705 | ||
| 698 | wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]); | 706 | wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]); |
| 699 | 707 | ||
| @@ -923,7 +931,7 @@ static int wacom_intuos_general(struct wacom_wac *wacom) | |||
| 923 | * don't report events for invalid data | 931 | * don't report events for invalid data |
| 924 | */ | 932 | */ |
| 925 | /* older I4 styli don't work with new Cintiqs */ | 933 | /* older I4 styli don't work with new Cintiqs */ |
| 926 | if ((!((wacom->id[idx] >> 20) & 0x01) && | 934 | if ((!((wacom->id[idx] >> 16) & 0x01) && |
| 927 | (features->type == WACOM_21UX2)) || | 935 | (features->type == WACOM_21UX2)) || |
| 928 | /* Only large Intuos support Lense Cursor */ | 936 | /* Only large Intuos support Lense Cursor */ |
| 929 | (wacom->tool[idx] == BTN_TOOL_LENS && | 937 | (wacom->tool[idx] == BTN_TOOL_LENS && |
| @@ -1059,7 +1067,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom) | |||
| 1059 | break; | 1067 | break; |
| 1060 | } | 1068 | } |
| 1061 | 1069 | ||
| 1062 | input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */ | 1070 | input_report_abs(input, ABS_MISC, |
| 1071 | wacom_intuos_id_mangle(wacom->id[idx])); /* report tool id */ | ||
| 1063 | input_report_key(input, wacom->tool[idx], 1); | 1072 | input_report_key(input, wacom->tool[idx], 1); |
| 1064 | input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 1073 | input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]); |
| 1065 | wacom->reporting_data = true; | 1074 | wacom->reporting_data = true; |
| @@ -1435,11 +1444,59 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
| 1435 | return 0; | 1444 | return 0; |
| 1436 | } | 1445 | } |
| 1437 | 1446 | ||
| 1447 | static int wacom_equivalent_usage(int usage) | ||
| 1448 | { | ||
| 1449 | if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) { | ||
| 1450 | int subpage = (usage & 0xFF00) << 8; | ||
| 1451 | int subusage = (usage & 0xFF); | ||
| 1452 | |||
| 1453 | if (subpage == WACOM_HID_SP_PAD || | ||
| 1454 | subpage == WACOM_HID_SP_BUTTON || | ||
| 1455 | subpage == WACOM_HID_SP_DIGITIZER || | ||
| 1456 | subpage == WACOM_HID_SP_DIGITIZERINFO || | ||
| 1457 | usage == WACOM_HID_WD_SENSE || | ||
| 1458 | usage == WACOM_HID_WD_SERIALHI || | ||
| 1459 | usage == WACOM_HID_WD_TOOLTYPE || | ||
| 1460 | usage == WACOM_HID_WD_DISTANCE || | ||
| 1461 | usage == WACOM_HID_WD_TOUCHSTRIP || | ||
| 1462 | usage == WACOM_HID_WD_TOUCHSTRIP2 || | ||
| 1463 | usage == WACOM_HID_WD_TOUCHRING || | ||
| 1464 | usage == WACOM_HID_WD_TOUCHRINGSTATUS) { | ||
| 1465 | return usage; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | if (subpage == HID_UP_UNDEFINED) | ||
| 1469 | subpage = HID_UP_DIGITIZER; | ||
| 1470 | |||
| 1471 | return subpage | subusage; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | return usage; | ||
| 1475 | } | ||
| 1476 | |||
| 1438 | static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, | 1477 | static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, |
| 1439 | struct hid_field *field, __u8 type, __u16 code, int fuzz) | 1478 | struct hid_field *field, __u8 type, __u16 code, int fuzz) |
| 1440 | { | 1479 | { |
| 1480 | struct wacom *wacom = input_get_drvdata(input); | ||
| 1481 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
| 1482 | struct wacom_features *features = &wacom_wac->features; | ||
| 1441 | int fmin = field->logical_minimum; | 1483 | int fmin = field->logical_minimum; |
| 1442 | int fmax = field->logical_maximum; | 1484 | int fmax = field->logical_maximum; |
| 1485 | unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid); | ||
| 1486 | int resolution_code = code; | ||
| 1487 | |||
| 1488 | if (equivalent_usage == HID_DG_TWIST) { | ||
| 1489 | resolution_code = ABS_RZ; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | if (equivalent_usage == HID_GD_X) { | ||
| 1493 | fmin += features->offset_left; | ||
| 1494 | fmax -= features->offset_right; | ||
| 1495 | } | ||
| 1496 | if (equivalent_usage == HID_GD_Y) { | ||
| 1497 | fmin += features->offset_top; | ||
| 1498 | fmax -= features->offset_bottom; | ||
| 1499 | } | ||
| 1443 | 1500 | ||
| 1444 | usage->type = type; | 1501 | usage->type = type; |
| 1445 | usage->code = code; | 1502 | usage->code = code; |
| @@ -1450,7 +1507,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, | |||
| 1450 | case EV_ABS: | 1507 | case EV_ABS: |
| 1451 | input_set_abs_params(input, code, fmin, fmax, fuzz, 0); | 1508 | input_set_abs_params(input, code, fmin, fmax, fuzz, 0); |
| 1452 | input_abs_set_res(input, code, | 1509 | input_abs_set_res(input, code, |
| 1453 | hidinput_calc_abs_res(field, code)); | 1510 | hidinput_calc_abs_res(field, resolution_code)); |
| 1454 | break; | 1511 | break; |
| 1455 | case EV_KEY: | 1512 | case EV_KEY: |
| 1456 | input_set_capability(input, EV_KEY, code); | 1513 | input_set_capability(input, EV_KEY, code); |
| @@ -1458,6 +1515,172 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, | |||
| 1458 | case EV_MSC: | 1515 | case EV_MSC: |
| 1459 | input_set_capability(input, EV_MSC, code); | 1516 | input_set_capability(input, EV_MSC, code); |
| 1460 | break; | 1517 | break; |
| 1518 | case EV_SW: | ||
| 1519 | input_set_capability(input, EV_SW, code); | ||
| 1520 | break; | ||
| 1521 | } | ||
| 1522 | } | ||
| 1523 | |||
| 1524 | static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, | ||
| 1525 | struct hid_field *field, struct hid_usage *usage) | ||
| 1526 | { | ||
| 1527 | struct wacom *wacom = hid_get_drvdata(hdev); | ||
| 1528 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
| 1529 | struct wacom_features *features = &wacom_wac->features; | ||
| 1530 | struct input_dev *input = wacom_wac->pad_input; | ||
| 1531 | unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); | ||
| 1532 | |||
| 1533 | switch (equivalent_usage) { | ||
| 1534 | case WACOM_HID_WD_BATTERY_LEVEL: | ||
| 1535 | case WACOM_HID_WD_BATTERY_CHARGING: | ||
| 1536 | features->quirks |= WACOM_QUIRK_BATTERY; | ||
| 1537 | break; | ||
| 1538 | case WACOM_HID_WD_ACCELEROMETER_X: | ||
| 1539 | __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); | ||
| 1540 | wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0); | ||
| 1541 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1542 | break; | ||
| 1543 | case WACOM_HID_WD_ACCELEROMETER_Y: | ||
| 1544 | __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); | ||
| 1545 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 0); | ||
| 1546 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1547 | break; | ||
| 1548 | case WACOM_HID_WD_ACCELEROMETER_Z: | ||
| 1549 | __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); | ||
| 1550 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0); | ||
| 1551 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1552 | break; | ||
| 1553 | case WACOM_HID_WD_BUTTONHOME: | ||
| 1554 | case WACOM_HID_WD_BUTTONUP: | ||
| 1555 | case WACOM_HID_WD_BUTTONDOWN: | ||
| 1556 | case WACOM_HID_WD_BUTTONLEFT: | ||
| 1557 | case WACOM_HID_WD_BUTTONRIGHT: | ||
| 1558 | case WACOM_HID_WD_BUTTONCENTER: | ||
| 1559 | wacom_map_usage(input, usage, field, EV_KEY, | ||
| 1560 | wacom_numbered_button_to_key(features->numbered_buttons), | ||
| 1561 | 0); | ||
| 1562 | features->numbered_buttons++; | ||
| 1563 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1564 | break; | ||
| 1565 | case WACOM_HID_WD_TOUCHONOFF: | ||
| 1566 | wacom_map_usage(input, usage, field, EV_SW, SW_MUTE_DEVICE, 0); | ||
| 1567 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1568 | break; | ||
| 1569 | case WACOM_HID_WD_TOUCHSTRIP: | ||
| 1570 | wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, 0); | ||
| 1571 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1572 | break; | ||
| 1573 | case WACOM_HID_WD_TOUCHSTRIP2: | ||
| 1574 | wacom_map_usage(input, usage, field, EV_ABS, ABS_RY, 0); | ||
| 1575 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1576 | break; | ||
| 1577 | case WACOM_HID_WD_TOUCHRING: | ||
| 1578 | wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); | ||
| 1579 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1580 | break; | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | switch (equivalent_usage & 0xfffffff0) { | ||
| 1584 | case WACOM_HID_WD_EXPRESSKEY00: | ||
| 1585 | wacom_map_usage(input, usage, field, EV_KEY, | ||
| 1586 | wacom_numbered_button_to_key(features->numbered_buttons), | ||
| 1587 | 0); | ||
| 1588 | features->numbered_buttons++; | ||
| 1589 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1590 | break; | ||
| 1591 | } | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | static void wacom_wac_pad_battery_event(struct hid_device *hdev, struct hid_field *field, | ||
| 1595 | struct hid_usage *usage, __s32 value) | ||
| 1596 | { | ||
| 1597 | struct wacom *wacom = hid_get_drvdata(hdev); | ||
| 1598 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
| 1599 | unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); | ||
| 1600 | |||
| 1601 | switch (equivalent_usage) { | ||
| 1602 | case WACOM_HID_WD_BATTERY_LEVEL: | ||
| 1603 | wacom_wac->hid_data.battery_capacity = value; | ||
| 1604 | wacom_wac->hid_data.bat_connected = 1; | ||
| 1605 | break; | ||
| 1606 | |||
| 1607 | case WACOM_HID_WD_BATTERY_CHARGING: | ||
| 1608 | wacom_wac->hid_data.bat_charging = value; | ||
| 1609 | wacom_wac->hid_data.ps_connected = value; | ||
| 1610 | wacom_wac->hid_data.bat_connected = 1; | ||
| 1611 | break; | ||
| 1612 | } | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field, | ||
| 1616 | struct hid_usage *usage, __s32 value) | ||
| 1617 | { | ||
| 1618 | struct wacom *wacom = hid_get_drvdata(hdev); | ||
| 1619 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
| 1620 | struct input_dev *input = wacom_wac->pad_input; | ||
| 1621 | struct wacom_features *features = &wacom_wac->features; | ||
| 1622 | unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); | ||
| 1623 | |||
| 1624 | if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) { | ||
| 1625 | wacom_wac->hid_data.inrange_state |= value; | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | switch (equivalent_usage) { | ||
| 1629 | case WACOM_HID_WD_TOUCHRINGSTATUS: | ||
| 1630 | break; | ||
| 1631 | |||
| 1632 | default: | ||
| 1633 | features->input_event_flag = true; | ||
| 1634 | input_event(input, usage->type, usage->code, value); | ||
| 1635 | break; | ||
| 1636 | } | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | static void wacom_wac_pad_pre_report(struct hid_device *hdev, | ||
| 1640 | struct hid_report *report) | ||
| 1641 | { | ||
| 1642 | struct wacom *wacom = hid_get_drvdata(hdev); | ||
| 1643 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
| 1644 | |||
| 1645 | wacom_wac->hid_data.inrange_state = 0; | ||
| 1646 | } | ||
| 1647 | |||
| 1648 | static void wacom_wac_pad_battery_report(struct hid_device *hdev, | ||
| 1649 | struct hid_report *report) | ||
| 1650 | { | ||
| 1651 | struct wacom *wacom = hid_get_drvdata(hdev); | ||
| 1652 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
| 1653 | struct wacom_features *features = &wacom_wac->features; | ||
| 1654 | |||
| 1655 | if (features->quirks & WACOM_QUIRK_BATTERY) { | ||
| 1656 | int capacity = wacom_wac->hid_data.battery_capacity; | ||
| 1657 | bool charging = wacom_wac->hid_data.bat_charging; | ||
| 1658 | bool connected = wacom_wac->hid_data.bat_connected; | ||
| 1659 | bool powered = wacom_wac->hid_data.ps_connected; | ||
| 1660 | |||
| 1661 | wacom_notify_battery(wacom_wac, capacity, charging, | ||
| 1662 | connected, powered); | ||
| 1663 | } | ||
| 1664 | } | ||
| 1665 | |||
| 1666 | static void wacom_wac_pad_report(struct hid_device *hdev, | ||
| 1667 | struct hid_report *report) | ||
| 1668 | { | ||
| 1669 | struct wacom *wacom = hid_get_drvdata(hdev); | ||
| 1670 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
| 1671 | struct wacom_features *features = &wacom_wac->features; | ||
| 1672 | struct input_dev *input = wacom_wac->pad_input; | ||
| 1673 | bool active = wacom_wac->hid_data.inrange_state != 0; | ||
| 1674 | |||
| 1675 | /* report prox for expresskey events */ | ||
| 1676 | if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) { | ||
| 1677 | features->input_event_flag = true; | ||
| 1678 | input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0); | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | if (features->input_event_flag) { | ||
| 1682 | features->input_event_flag = false; | ||
| 1683 | input_sync(input); | ||
| 1461 | } | 1684 | } |
| 1462 | } | 1685 | } |
| 1463 | 1686 | ||
| @@ -1466,25 +1689,43 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, | |||
| 1466 | { | 1689 | { |
| 1467 | struct wacom *wacom = hid_get_drvdata(hdev); | 1690 | struct wacom *wacom = hid_get_drvdata(hdev); |
| 1468 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | 1691 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
| 1692 | struct wacom_features *features = &wacom_wac->features; | ||
| 1469 | struct input_dev *input = wacom_wac->pen_input; | 1693 | struct input_dev *input = wacom_wac->pen_input; |
| 1694 | unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); | ||
| 1470 | 1695 | ||
| 1471 | switch (usage->hid) { | 1696 | switch (equivalent_usage) { |
| 1472 | case HID_GD_X: | 1697 | case HID_GD_X: |
| 1473 | wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); | 1698 | wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); |
| 1474 | break; | 1699 | break; |
| 1475 | case HID_GD_Y: | 1700 | case HID_GD_Y: |
| 1476 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4); | 1701 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4); |
| 1477 | break; | 1702 | break; |
| 1703 | case WACOM_HID_WD_DISTANCE: | ||
| 1704 | case HID_GD_Z: | ||
| 1705 | wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0); | ||
| 1706 | break; | ||
| 1478 | case HID_DG_TIPPRESSURE: | 1707 | case HID_DG_TIPPRESSURE: |
| 1479 | wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0); | 1708 | wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0); |
| 1480 | break; | 1709 | break; |
| 1481 | case HID_DG_INRANGE: | 1710 | case HID_DG_INRANGE: |
| 1482 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0); | 1711 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0); |
| 1483 | break; | 1712 | break; |
| 1713 | case HID_DG_BATTERYSTRENGTH: | ||
| 1714 | features->quirks |= WACOM_QUIRK_BATTERY; | ||
| 1715 | break; | ||
| 1484 | case HID_DG_INVERT: | 1716 | case HID_DG_INVERT: |
| 1485 | wacom_map_usage(input, usage, field, EV_KEY, | 1717 | wacom_map_usage(input, usage, field, EV_KEY, |
| 1486 | BTN_TOOL_RUBBER, 0); | 1718 | BTN_TOOL_RUBBER, 0); |
| 1487 | break; | 1719 | break; |
| 1720 | case HID_DG_TILT_X: | ||
| 1721 | wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, 0); | ||
| 1722 | break; | ||
| 1723 | case HID_DG_TILT_Y: | ||
| 1724 | wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, 0); | ||
| 1725 | break; | ||
| 1726 | case HID_DG_TWIST: | ||
| 1727 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0); | ||
| 1728 | break; | ||
| 1488 | case HID_DG_ERASER: | 1729 | case HID_DG_ERASER: |
| 1489 | case HID_DG_TIPSWITCH: | 1730 | case HID_DG_TIPSWITCH: |
| 1490 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0); | 1731 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0); |
| @@ -1498,39 +1739,131 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, | |||
| 1498 | case HID_DG_TOOLSERIALNUMBER: | 1739 | case HID_DG_TOOLSERIALNUMBER: |
| 1499 | wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0); | 1740 | wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0); |
| 1500 | break; | 1741 | break; |
| 1742 | case WACOM_HID_WD_SENSE: | ||
| 1743 | features->quirks |= WACOM_QUIRK_SENSE; | ||
| 1744 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0); | ||
| 1745 | break; | ||
| 1746 | case WACOM_HID_WD_SERIALHI: | ||
| 1747 | wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0); | ||
| 1748 | set_bit(EV_KEY, input->evbit); | ||
| 1749 | input_set_capability(input, EV_KEY, BTN_TOOL_PEN); | ||
| 1750 | input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER); | ||
| 1751 | input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH); | ||
| 1752 | input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL); | ||
| 1753 | input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH); | ||
| 1754 | input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE); | ||
| 1755 | input_set_capability(input, EV_KEY, BTN_TOOL_LENS); | ||
| 1756 | break; | ||
| 1757 | case WACOM_HID_WD_FINGERWHEEL: | ||
| 1758 | wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); | ||
| 1759 | break; | ||
| 1501 | } | 1760 | } |
| 1502 | } | 1761 | } |
| 1503 | 1762 | ||
| 1504 | static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, | 1763 | static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, |
| 1505 | struct hid_usage *usage, __s32 value) | 1764 | struct hid_usage *usage, __s32 value) |
| 1506 | { | 1765 | { |
| 1507 | struct wacom *wacom = hid_get_drvdata(hdev); | 1766 | struct wacom *wacom = hid_get_drvdata(hdev); |
| 1508 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | 1767 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
| 1768 | struct wacom_features *features = &wacom_wac->features; | ||
| 1509 | struct input_dev *input = wacom_wac->pen_input; | 1769 | struct input_dev *input = wacom_wac->pen_input; |
| 1770 | unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); | ||
| 1510 | 1771 | ||
| 1511 | /* checking which Tool / tip switch to send */ | 1772 | switch (equivalent_usage) { |
| 1512 | switch (usage->hid) { | 1773 | case HID_GD_Z: |
| 1774 | /* | ||
| 1775 | * HID_GD_Z "should increase as the control's position is | ||
| 1776 | * moved from high to low", while ABS_DISTANCE instead | ||
| 1777 | * increases in value as the tool moves from low to high. | ||
| 1778 | */ | ||
| 1779 | value = field->logical_maximum - value; | ||
| 1780 | break; | ||
| 1513 | case HID_DG_INRANGE: | 1781 | case HID_DG_INRANGE: |
| 1514 | wacom_wac->hid_data.inrange_state = value; | 1782 | wacom_wac->hid_data.inrange_state = value; |
| 1515 | return 0; | 1783 | if (!(features->quirks & WACOM_QUIRK_SENSE)) |
| 1784 | wacom_wac->hid_data.sense_state = value; | ||
| 1785 | return; | ||
| 1786 | case HID_DG_BATTERYSTRENGTH: | ||
| 1787 | wacom_wac->hid_data.battery_capacity = value; | ||
| 1788 | wacom_wac->hid_data.bat_connected = 1; | ||
| 1789 | break; | ||
| 1516 | case HID_DG_INVERT: | 1790 | case HID_DG_INVERT: |
| 1517 | wacom_wac->hid_data.invert_state = value; | 1791 | wacom_wac->hid_data.invert_state = value; |
| 1518 | return 0; | 1792 | return; |
| 1519 | case HID_DG_ERASER: | 1793 | case HID_DG_ERASER: |
| 1520 | case HID_DG_TIPSWITCH: | 1794 | case HID_DG_TIPSWITCH: |
| 1521 | wacom_wac->hid_data.tipswitch |= value; | 1795 | wacom_wac->hid_data.tipswitch |= value; |
| 1522 | return 0; | 1796 | return; |
| 1797 | case HID_DG_TOOLSERIALNUMBER: | ||
| 1798 | wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL); | ||
| 1799 | wacom_wac->serial[0] |= value; | ||
| 1800 | return; | ||
| 1801 | case WACOM_HID_WD_SENSE: | ||
| 1802 | wacom_wac->hid_data.sense_state = value; | ||
| 1803 | return; | ||
| 1804 | case WACOM_HID_WD_SERIALHI: | ||
| 1805 | wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF); | ||
| 1806 | wacom_wac->serial[0] |= ((__u64)value) << 32; | ||
| 1807 | /* | ||
| 1808 | * Non-USI EMR devices may contain additional tool type | ||
| 1809 | * information here. See WACOM_HID_WD_TOOLTYPE case for | ||
| 1810 | * more details. | ||
| 1811 | */ | ||
| 1812 | if (value >> 20 == 1) { | ||
| 1813 | wacom_wac->id[0] |= value & 0xFFFFF; | ||
| 1814 | } | ||
| 1815 | return; | ||
| 1816 | case WACOM_HID_WD_TOOLTYPE: | ||
| 1817 | /* | ||
| 1818 | * Some devices (MobileStudio Pro, and possibly later | ||
| 1819 | * devices as well) do not return the complete tool | ||
| 1820 | * type in their WACOM_HID_WD_TOOLTYPE usage. Use a | ||
| 1821 | * bitwise OR so the complete value can be built | ||
| 1822 | * up over time :( | ||
| 1823 | */ | ||
| 1824 | wacom_wac->id[0] |= value; | ||
| 1825 | return; | ||
| 1826 | case WACOM_HID_WD_OFFSETLEFT: | ||
| 1827 | if (features->offset_left && value != features->offset_left) | ||
| 1828 | hid_warn(hdev, "%s: overriding exising left offset " | ||
| 1829 | "%d -> %d\n", __func__, value, | ||
| 1830 | features->offset_left); | ||
| 1831 | features->offset_left = value; | ||
| 1832 | return; | ||
| 1833 | case WACOM_HID_WD_OFFSETRIGHT: | ||
| 1834 | if (features->offset_right && value != features->offset_right) | ||
| 1835 | hid_warn(hdev, "%s: overriding exising right offset " | ||
| 1836 | "%d -> %d\n", __func__, value, | ||
| 1837 | features->offset_right); | ||
| 1838 | features->offset_right = value; | ||
| 1839 | return; | ||
| 1840 | case WACOM_HID_WD_OFFSETTOP: | ||
| 1841 | if (features->offset_top && value != features->offset_top) | ||
| 1842 | hid_warn(hdev, "%s: overriding exising top offset " | ||
| 1843 | "%d -> %d\n", __func__, value, | ||
| 1844 | features->offset_top); | ||
| 1845 | features->offset_top = value; | ||
| 1846 | return; | ||
| 1847 | case WACOM_HID_WD_OFFSETBOTTOM: | ||
| 1848 | if (features->offset_bottom && value != features->offset_bottom) | ||
| 1849 | hid_warn(hdev, "%s: overriding exising bottom offset " | ||
| 1850 | "%d -> %d\n", __func__, value, | ||
| 1851 | features->offset_bottom); | ||
| 1852 | features->offset_bottom = value; | ||
| 1853 | return; | ||
| 1523 | } | 1854 | } |
| 1524 | 1855 | ||
| 1525 | /* send pen events only when touch is up or forced out | 1856 | /* send pen events only when touch is up or forced out |
| 1526 | * or touch arbitration is off | 1857 | * or touch arbitration is off |
| 1527 | */ | 1858 | */ |
| 1528 | if (!usage->type || delay_pen_events(wacom_wac)) | 1859 | if (!usage->type || delay_pen_events(wacom_wac)) |
| 1529 | return 0; | 1860 | return; |
| 1530 | 1861 | ||
| 1531 | input_event(input, usage->type, usage->code, value); | 1862 | /* send pen events only when the pen is in/entering/leaving proximity */ |
| 1863 | if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0]) | ||
| 1864 | return; | ||
| 1532 | 1865 | ||
| 1533 | return 0; | 1866 | input_event(input, usage->type, usage->code, value); |
| 1534 | } | 1867 | } |
| 1535 | 1868 | ||
| 1536 | static void wacom_wac_pen_pre_report(struct hid_device *hdev, | 1869 | static void wacom_wac_pen_pre_report(struct hid_device *hdev, |
| @@ -1546,24 +1879,53 @@ static void wacom_wac_pen_report(struct hid_device *hdev, | |||
| 1546 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | 1879 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
| 1547 | struct input_dev *input = wacom_wac->pen_input; | 1880 | struct input_dev *input = wacom_wac->pen_input; |
| 1548 | bool prox = wacom_wac->hid_data.inrange_state; | 1881 | bool prox = wacom_wac->hid_data.inrange_state; |
| 1882 | bool range = wacom_wac->hid_data.sense_state; | ||
| 1549 | 1883 | ||
| 1550 | if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */ | 1884 | if (!wacom_wac->tool[0] && prox) { /* first in prox */ |
| 1551 | /* Going into proximity select tool */ | 1885 | /* Going into proximity select tool */ |
| 1552 | wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ? | 1886 | if (wacom_wac->hid_data.invert_state) |
| 1553 | BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 1887 | wacom_wac->tool[0] = BTN_TOOL_RUBBER; |
| 1888 | else if (wacom_wac->id[0]) | ||
| 1889 | wacom_wac->tool[0] = wacom_intuos_get_tool_type(wacom_wac->id[0]); | ||
| 1890 | else | ||
| 1891 | wacom_wac->tool[0] = BTN_TOOL_PEN; | ||
| 1892 | } | ||
| 1554 | 1893 | ||
| 1555 | /* keep pen state for touch events */ | 1894 | /* keep pen state for touch events */ |
| 1556 | wacom_wac->shared->stylus_in_proximity = prox; | 1895 | wacom_wac->shared->stylus_in_proximity = range; |
| 1557 | 1896 | ||
| 1558 | if (!delay_pen_events(wacom_wac)) { | 1897 | if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) { |
| 1898 | int id = wacom_wac->id[0]; | ||
| 1899 | |||
| 1900 | /* | ||
| 1901 | * Non-USI EMR tools should have their IDs mangled to | ||
| 1902 | * match the legacy behavior of wacom_intuos_general | ||
| 1903 | */ | ||
| 1904 | if (wacom_wac->serial[0] >> 52 == 1) | ||
| 1905 | id = wacom_intuos_id_mangle(id); | ||
| 1906 | |||
| 1907 | /* | ||
| 1908 | * To ensure compatibility with xf86-input-wacom, we should | ||
| 1909 | * report the BTN_TOOL_* event prior to the ABS_MISC or | ||
| 1910 | * MSC_SERIAL events. | ||
| 1911 | */ | ||
| 1559 | input_report_key(input, BTN_TOUCH, | 1912 | input_report_key(input, BTN_TOUCH, |
| 1560 | wacom_wac->hid_data.tipswitch); | 1913 | wacom_wac->hid_data.tipswitch); |
| 1561 | input_report_key(input, wacom_wac->tool[0], prox); | 1914 | input_report_key(input, wacom_wac->tool[0], prox); |
| 1915 | if (wacom_wac->serial[0]) { | ||
| 1916 | input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]); | ||
| 1917 | input_report_abs(input, ABS_MISC, id); | ||
| 1918 | } | ||
| 1562 | 1919 | ||
| 1563 | wacom_wac->hid_data.tipswitch = false; | 1920 | wacom_wac->hid_data.tipswitch = false; |
| 1564 | 1921 | ||
| 1565 | input_sync(input); | 1922 | input_sync(input); |
| 1566 | } | 1923 | } |
| 1924 | |||
| 1925 | if (!prox) { | ||
| 1926 | wacom_wac->tool[0] = 0; | ||
| 1927 | wacom_wac->id[0] = 0; | ||
| 1928 | } | ||
| 1567 | } | 1929 | } |
| 1568 | 1930 | ||
| 1569 | static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, | 1931 | static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, |
| @@ -1573,8 +1935,9 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, | |||
| 1573 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | 1935 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
| 1574 | struct input_dev *input = wacom_wac->touch_input; | 1936 | struct input_dev *input = wacom_wac->touch_input; |
| 1575 | unsigned touch_max = wacom_wac->features.touch_max; | 1937 | unsigned touch_max = wacom_wac->features.touch_max; |
| 1938 | unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); | ||
| 1576 | 1939 | ||
| 1577 | switch (usage->hid) { | 1940 | switch (equivalent_usage) { |
| 1578 | case HID_GD_X: | 1941 | case HID_GD_X: |
| 1579 | if (touch_max == 1) | 1942 | if (touch_max == 1) |
| 1580 | wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); | 1943 | wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); |
| @@ -1644,13 +2007,14 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac, | |||
| 1644 | } | 2007 | } |
| 1645 | } | 2008 | } |
| 1646 | 2009 | ||
| 1647 | static int wacom_wac_finger_event(struct hid_device *hdev, | 2010 | static void wacom_wac_finger_event(struct hid_device *hdev, |
| 1648 | struct hid_field *field, struct hid_usage *usage, __s32 value) | 2011 | struct hid_field *field, struct hid_usage *usage, __s32 value) |
| 1649 | { | 2012 | { |
| 1650 | struct wacom *wacom = hid_get_drvdata(hdev); | 2013 | struct wacom *wacom = hid_get_drvdata(hdev); |
| 1651 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | 2014 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
| 2015 | unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); | ||
| 1652 | 2016 | ||
| 1653 | switch (usage->hid) { | 2017 | switch (equivalent_usage) { |
| 1654 | case HID_GD_X: | 2018 | case HID_GD_X: |
| 1655 | wacom_wac->hid_data.x = value; | 2019 | wacom_wac->hid_data.x = value; |
| 1656 | break; | 2020 | break; |
| @@ -1673,11 +2037,9 @@ static int wacom_wac_finger_event(struct hid_device *hdev, | |||
| 1673 | 2037 | ||
| 1674 | 2038 | ||
| 1675 | if (usage->usage_index + 1 == field->report_count) { | 2039 | if (usage->usage_index + 1 == field->report_count) { |
| 1676 | if (usage->hid == wacom_wac->hid_data.last_slot_field) | 2040 | if (equivalent_usage == wacom_wac->hid_data.last_slot_field) |
| 1677 | wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); | 2041 | wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); |
| 1678 | } | 2042 | } |
| 1679 | |||
| 1680 | return 0; | ||
| 1681 | } | 2043 | } |
| 1682 | 2044 | ||
| 1683 | static void wacom_wac_finger_pre_report(struct hid_device *hdev, | 2045 | static void wacom_wac_finger_pre_report(struct hid_device *hdev, |
| @@ -1762,28 +2124,30 @@ void wacom_wac_usage_mapping(struct hid_device *hdev, | |||
| 1762 | /* currently, only direct devices have proper hid report descriptors */ | 2124 | /* currently, only direct devices have proper hid report descriptors */ |
| 1763 | features->device_type |= WACOM_DEVICETYPE_DIRECT; | 2125 | features->device_type |= WACOM_DEVICETYPE_DIRECT; |
| 1764 | 2126 | ||
| 1765 | if (WACOM_PEN_FIELD(field)) | 2127 | if (WACOM_PAD_FIELD(field)) |
| 1766 | return wacom_wac_pen_usage_mapping(hdev, field, usage); | 2128 | wacom_wac_pad_usage_mapping(hdev, field, usage); |
| 1767 | 2129 | else if (WACOM_PEN_FIELD(field)) | |
| 1768 | if (WACOM_FINGER_FIELD(field)) | 2130 | wacom_wac_pen_usage_mapping(hdev, field, usage); |
| 1769 | return wacom_wac_finger_usage_mapping(hdev, field, usage); | 2131 | else if (WACOM_FINGER_FIELD(field)) |
| 2132 | wacom_wac_finger_usage_mapping(hdev, field, usage); | ||
| 1770 | } | 2133 | } |
| 1771 | 2134 | ||
| 1772 | int wacom_wac_event(struct hid_device *hdev, struct hid_field *field, | 2135 | void wacom_wac_event(struct hid_device *hdev, struct hid_field *field, |
| 1773 | struct hid_usage *usage, __s32 value) | 2136 | struct hid_usage *usage, __s32 value) |
| 1774 | { | 2137 | { |
| 1775 | struct wacom *wacom = hid_get_drvdata(hdev); | 2138 | struct wacom *wacom = hid_get_drvdata(hdev); |
| 1776 | 2139 | ||
| 1777 | if (wacom->wacom_wac.features.type != HID_GENERIC) | 2140 | if (wacom->wacom_wac.features.type != HID_GENERIC) |
| 1778 | return 0; | 2141 | return; |
| 1779 | |||
| 1780 | if (WACOM_PEN_FIELD(field)) | ||
| 1781 | return wacom_wac_pen_event(hdev, field, usage, value); | ||
| 1782 | |||
| 1783 | if (WACOM_FINGER_FIELD(field)) | ||
| 1784 | return wacom_wac_finger_event(hdev, field, usage, value); | ||
| 1785 | 2142 | ||
| 1786 | return 0; | 2143 | if (WACOM_PAD_FIELD(field)) { |
| 2144 | wacom_wac_pad_battery_event(hdev, field, usage, value); | ||
| 2145 | if (wacom->wacom_wac.pad_input) | ||
| 2146 | wacom_wac_pad_event(hdev, field, usage, value); | ||
| 2147 | } else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) | ||
| 2148 | wacom_wac_pen_event(hdev, field, usage, value); | ||
| 2149 | else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input) | ||
| 2150 | wacom_wac_finger_event(hdev, field, usage, value); | ||
| 1787 | } | 2151 | } |
| 1788 | 2152 | ||
| 1789 | static void wacom_report_events(struct hid_device *hdev, struct hid_report *report) | 2153 | static void wacom_report_events(struct hid_device *hdev, struct hid_report *report) |
| @@ -1814,19 +2178,23 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) | |||
| 1814 | if (wacom_wac->features.type != HID_GENERIC) | 2178 | if (wacom_wac->features.type != HID_GENERIC) |
| 1815 | return; | 2179 | return; |
| 1816 | 2180 | ||
| 1817 | if (WACOM_PEN_FIELD(field)) | 2181 | if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input) |
| 2182 | wacom_wac_pad_pre_report(hdev, report); | ||
| 2183 | else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) | ||
| 1818 | wacom_wac_pen_pre_report(hdev, report); | 2184 | wacom_wac_pen_pre_report(hdev, report); |
| 1819 | 2185 | else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input) | |
| 1820 | if (WACOM_FINGER_FIELD(field)) | ||
| 1821 | wacom_wac_finger_pre_report(hdev, report); | 2186 | wacom_wac_finger_pre_report(hdev, report); |
| 1822 | 2187 | ||
| 1823 | wacom_report_events(hdev, report); | 2188 | wacom_report_events(hdev, report); |
| 1824 | 2189 | ||
| 1825 | if (WACOM_PEN_FIELD(field)) | 2190 | if (WACOM_PAD_FIELD(field)) { |
| 1826 | return wacom_wac_pen_report(hdev, report); | 2191 | wacom_wac_pad_battery_report(hdev, report); |
| 1827 | 2192 | if (wacom->wacom_wac.pad_input) | |
| 1828 | if (WACOM_FINGER_FIELD(field)) | 2193 | wacom_wac_pad_report(hdev, report); |
| 1829 | return wacom_wac_finger_report(hdev, report); | 2194 | } else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) |
| 2195 | wacom_wac_pen_report(hdev, report); | ||
| 2196 | else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input) | ||
| 2197 | wacom_wac_finger_report(hdev, report); | ||
| 1830 | } | 2198 | } |
| 1831 | 2199 | ||
| 1832 | static int wacom_bpt_touch(struct wacom_wac *wacom) | 2200 | static int wacom_bpt_touch(struct wacom_wac *wacom) |
| @@ -2399,6 +2767,8 @@ void wacom_setup_device_quirks(struct wacom *wacom) | |||
| 2399 | struct wacom_features *features = &wacom->wacom_wac.features; | 2767 | struct wacom_features *features = &wacom->wacom_wac.features; |
| 2400 | 2768 | ||
| 2401 | /* The pen and pad share the same interface on most devices */ | 2769 | /* The pen and pad share the same interface on most devices */ |
| 2770 | if (features->numbered_buttons > 0) | ||
| 2771 | features->device_type |= WACOM_DEVICETYPE_PAD; | ||
| 2402 | if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 || | 2772 | if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 || |
| 2403 | features->type == DTUS || | 2773 | features->type == DTUS || |
| 2404 | (features->type >= INTUOS3S && features->type <= WACOM_MO)) { | 2774 | (features->type >= INTUOS3S && features->type <= WACOM_MO)) { |
| @@ -2448,7 +2818,7 @@ void wacom_setup_device_quirks(struct wacom *wacom) | |||
| 2448 | /* | 2818 | /* |
| 2449 | * Raw Wacom-mode pen and touch events both come from interface | 2819 | * Raw Wacom-mode pen and touch events both come from interface |
| 2450 | * 0, whose HID descriptor has an application usage of 0xFF0D | 2820 | * 0, whose HID descriptor has an application usage of 0xFF0D |
| 2451 | * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back | 2821 | * (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back |
| 2452 | * out through the HID_GENERIC device created for interface 1, | 2822 | * out through the HID_GENERIC device created for interface 1, |
| 2453 | * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH. | 2823 | * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH. |
| 2454 | */ | 2824 | */ |
| @@ -2530,10 +2900,12 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, | |||
| 2530 | __set_bit(BTN_TOUCH, input_dev->keybit); | 2900 | __set_bit(BTN_TOUCH, input_dev->keybit); |
| 2531 | __set_bit(ABS_MISC, input_dev->absbit); | 2901 | __set_bit(ABS_MISC, input_dev->absbit); |
| 2532 | 2902 | ||
| 2533 | input_set_abs_params(input_dev, ABS_X, features->x_min, | 2903 | input_set_abs_params(input_dev, ABS_X, 0 + features->offset_left, |
| 2534 | features->x_max, features->x_fuzz, 0); | 2904 | features->x_max - features->offset_right, |
| 2535 | input_set_abs_params(input_dev, ABS_Y, features->y_min, | 2905 | features->x_fuzz, 0); |
| 2536 | features->y_max, features->y_fuzz, 0); | 2906 | input_set_abs_params(input_dev, ABS_Y, 0 + features->offset_top, |
| 2907 | features->y_max - features->offset_bottom, | ||
| 2908 | features->y_fuzz, 0); | ||
| 2537 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, | 2909 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, |
| 2538 | features->pressure_max, features->pressure_fuzz, 0); | 2910 | features->pressure_max, features->pressure_fuzz, 0); |
| 2539 | 2911 | ||
| @@ -2769,17 +3141,29 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, | |||
| 2769 | return 0; | 3141 | return 0; |
| 2770 | } | 3142 | } |
| 2771 | 3143 | ||
| 3144 | static int wacom_numbered_button_to_key(int n) | ||
| 3145 | { | ||
| 3146 | if (n < 10) | ||
| 3147 | return BTN_0 + n; | ||
| 3148 | else if (n < 16) | ||
| 3149 | return BTN_A + (n-10); | ||
| 3150 | else if (n < 18) | ||
| 3151 | return BTN_BASE + (n-16); | ||
| 3152 | else | ||
| 3153 | return 0; | ||
| 3154 | } | ||
| 3155 | |||
| 2772 | static void wacom_setup_numbered_buttons(struct input_dev *input_dev, | 3156 | static void wacom_setup_numbered_buttons(struct input_dev *input_dev, |
| 2773 | int button_count) | 3157 | int button_count) |
| 2774 | { | 3158 | { |
| 2775 | int i; | 3159 | int i; |
| 2776 | 3160 | ||
| 2777 | for (i = 0; i < button_count && i < 10; i++) | 3161 | for (i = 0; i < button_count; i++) { |
| 2778 | __set_bit(BTN_0 + i, input_dev->keybit); | 3162 | int key = wacom_numbered_button_to_key(i); |
| 2779 | for (i = 10; i < button_count && i < 16; i++) | 3163 | |
| 2780 | __set_bit(BTN_A + (i-10), input_dev->keybit); | 3164 | if (key) |
| 2781 | for (i = 16; i < button_count && i < 18; i++) | 3165 | __set_bit(key, input_dev->keybit); |
| 2782 | __set_bit(BTN_BASE + (i-16), input_dev->keybit); | 3166 | } |
| 2783 | } | 3167 | } |
| 2784 | 3168 | ||
| 2785 | static void wacom_24hd_update_leds(struct wacom *wacom, int mask, int group) | 3169 | static void wacom_24hd_update_leds(struct wacom *wacom, int mask, int group) |
| @@ -2881,12 +3265,12 @@ static void wacom_report_numbered_buttons(struct input_dev *input_dev, | |||
| 2881 | for (i = 0; i < wacom->led.count; i++) | 3265 | for (i = 0; i < wacom->led.count; i++) |
| 2882 | wacom_update_led(wacom, button_count, mask, i); | 3266 | wacom_update_led(wacom, button_count, mask, i); |
| 2883 | 3267 | ||
| 2884 | for (i = 0; i < button_count && i < 10; i++) | 3268 | for (i = 0; i < button_count; i++) { |
| 2885 | input_report_key(input_dev, BTN_0 + i, mask & (1 << i)); | 3269 | int key = wacom_numbered_button_to_key(i); |
| 2886 | for (i = 10; i < button_count && i < 16; i++) | 3270 | |
| 2887 | input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i)); | 3271 | if (key) |
| 2888 | for (i = 16; i < button_count && i < 18; i++) | 3272 | input_report_key(input_dev, key, mask & (1 << i)); |
| 2889 | input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i)); | 3273 | } |
| 2890 | } | 3274 | } |
| 2891 | 3275 | ||
| 2892 | int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | 3276 | int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, |
| @@ -2906,8 +3290,12 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
| 2906 | __set_bit(ABS_MISC, input_dev->absbit); | 3290 | __set_bit(ABS_MISC, input_dev->absbit); |
| 2907 | 3291 | ||
| 2908 | /* kept for making legacy xf86-input-wacom accepting the pad */ | 3292 | /* kept for making legacy xf86-input-wacom accepting the pad */ |
| 2909 | input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0); | 3293 | if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X].minimum || |
| 2910 | input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0); | 3294 | input_dev->absinfo[ABS_X].maximum))) |
| 3295 | input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0); | ||
| 3296 | if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y].minimum || | ||
| 3297 | input_dev->absinfo[ABS_Y].maximum))) | ||
| 3298 | input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0); | ||
| 2911 | 3299 | ||
| 2912 | /* kept for making udev and libwacom accepting the pad */ | 3300 | /* kept for making udev and libwacom accepting the pad */ |
| 2913 | __set_bit(BTN_STYLUS, input_dev->keybit); | 3301 | __set_bit(BTN_STYLUS, input_dev->keybit); |
| @@ -3027,6 +3415,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
| 3027 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); | 3415 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); |
| 3028 | break; | 3416 | break; |
| 3029 | 3417 | ||
| 3418 | case HID_GENERIC: | ||
| 3419 | break; | ||
| 3420 | |||
| 3030 | default: | 3421 | default: |
| 3031 | /* no pad supported */ | 3422 | /* no pad supported */ |
| 3032 | return -ENODEV; | 3423 | return -ENODEV; |
| @@ -3233,26 +3624,30 @@ static const struct wacom_features wacom_features_0x317 = | |||
| 3233 | INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16, | 3624 | INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16, |
| 3234 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 3625 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 3235 | static const struct wacom_features wacom_features_0xF4 = | 3626 | static const struct wacom_features wacom_features_0xF4 = |
| 3236 | { "Wacom Cintiq 24HD", 104080, 65200, 2047, 63, | 3627 | { "Wacom Cintiq 24HD", 104480, 65600, 2047, 63, |
| 3237 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16, | 3628 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16, |
| 3629 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3238 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | 3630 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
| 3239 | static const struct wacom_features wacom_features_0xF8 = | 3631 | static const struct wacom_features wacom_features_0xF8 = |
| 3240 | { "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */ | 3632 | { "Wacom Cintiq 24HD touch", 104480, 65600, 2047, 63, /* Pen */ |
| 3241 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16, | 3633 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16, |
| 3242 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | 3634 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
| 3635 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3243 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; | 3636 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; |
| 3244 | static const struct wacom_features wacom_features_0xF6 = | 3637 | static const struct wacom_features wacom_features_0xF6 = |
| 3245 | { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ | 3638 | { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ |
| 3246 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10, | 3639 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10, |
| 3247 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 3640 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 3248 | static const struct wacom_features wacom_features_0x32A = | 3641 | static const struct wacom_features wacom_features_0x32A = |
| 3249 | { "Wacom Cintiq 27QHD", 119740, 67520, 2047, 63, | 3642 | { "Wacom Cintiq 27QHD", 120140, 67920, 2047, 63, |
| 3250 | WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0, | 3643 | WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0, |
| 3644 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3251 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | 3645 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
| 3252 | static const struct wacom_features wacom_features_0x32B = | 3646 | static const struct wacom_features wacom_features_0x32B = |
| 3253 | { "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63, | 3647 | { "Wacom Cintiq 27QHD touch", 120140, 67920, 2047, 63, |
| 3254 | WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0, | 3648 | WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0, |
| 3255 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | 3649 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
| 3650 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3256 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C }; | 3651 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C }; |
| 3257 | static const struct wacom_features wacom_features_0x32C = | 3652 | static const struct wacom_features wacom_features_0x32C = |
| 3258 | { "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT, | 3653 | { "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT, |
| @@ -3267,13 +3662,15 @@ static const struct wacom_features wacom_features_0xC6 = | |||
| 3267 | { "Wacom Cintiq 12WX", 53020, 33440, 1023, 63, | 3662 | { "Wacom Cintiq 12WX", 53020, 33440, 1023, 63, |
| 3268 | WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 }; | 3663 | WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 }; |
| 3269 | static const struct wacom_features wacom_features_0x304 = | 3664 | static const struct wacom_features wacom_features_0x304 = |
| 3270 | { "Wacom Cintiq 13HD", 59152, 33448, 1023, 63, | 3665 | { "Wacom Cintiq 13HD", 59552, 33848, 1023, 63, |
| 3271 | WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, | 3666 | WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, |
| 3667 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3272 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | 3668 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
| 3273 | static const struct wacom_features wacom_features_0x333 = | 3669 | static const struct wacom_features wacom_features_0x333 = |
| 3274 | { "Wacom Cintiq 13HD touch", 59152, 33448, 2047, 63, | 3670 | { "Wacom Cintiq 13HD touch", 59552, 33848, 2047, 63, |
| 3275 | WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, | 3671 | WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, |
| 3276 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | 3672 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
| 3673 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3277 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 }; | 3674 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 }; |
| 3278 | static const struct wacom_features wacom_features_0x335 = | 3675 | static const struct wacom_features wacom_features_0x335 = |
| 3279 | { "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */ | 3676 | { "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */ |
| @@ -3290,42 +3687,50 @@ static const struct wacom_features wacom_features_0xF0 = | |||
| 3290 | { "Wacom DTU1631", 34623, 19553, 511, 0, | 3687 | { "Wacom DTU1631", 34623, 19553, 511, 0, |
| 3291 | DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 3688 | DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 3292 | static const struct wacom_features wacom_features_0xFB = | 3689 | static const struct wacom_features wacom_features_0xFB = |
| 3293 | { "Wacom DTU1031", 21896, 13760, 511, 0, | 3690 | { "Wacom DTU1031", 22096, 13960, 511, 0, |
| 3294 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, | 3691 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, |
| 3692 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, | ||
| 3295 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; | 3693 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; |
| 3296 | static const struct wacom_features wacom_features_0x32F = | 3694 | static const struct wacom_features wacom_features_0x32F = |
| 3297 | { "Wacom DTU1031X", 22472, 12728, 511, 0, | 3695 | { "Wacom DTU1031X", 22672, 12928, 511, 0, |
| 3298 | DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0, | 3696 | DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0, |
| 3697 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, | ||
| 3299 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; | 3698 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; |
| 3300 | static const struct wacom_features wacom_features_0x336 = | 3699 | static const struct wacom_features wacom_features_0x336 = |
| 3301 | { "Wacom DTU1141", 23472, 13203, 1023, 0, | 3700 | { "Wacom DTU1141", 23672, 13403, 1023, 0, |
| 3302 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, | 3701 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, |
| 3702 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, | ||
| 3303 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; | 3703 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; |
| 3304 | static const struct wacom_features wacom_features_0x57 = | 3704 | static const struct wacom_features wacom_features_0x57 = |
| 3305 | { "Wacom DTK2241", 95640, 54060, 2047, 63, | 3705 | { "Wacom DTK2241", 95840, 54260, 2047, 63, |
| 3306 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6, | 3706 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6, |
| 3707 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3307 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | 3708 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
| 3308 | static const struct wacom_features wacom_features_0x59 = /* Pen */ | 3709 | static const struct wacom_features wacom_features_0x59 = /* Pen */ |
| 3309 | { "Wacom DTH2242", 95640, 54060, 2047, 63, | 3710 | { "Wacom DTH2242", 95840, 54260, 2047, 63, |
| 3310 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6, | 3711 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6, |
| 3311 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | 3712 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
| 3713 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3312 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; | 3714 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; |
| 3313 | static const struct wacom_features wacom_features_0x5D = /* Touch */ | 3715 | static const struct wacom_features wacom_features_0x5D = /* Touch */ |
| 3314 | { "Wacom DTH2242", .type = WACOM_24HDT, | 3716 | { "Wacom DTH2242", .type = WACOM_24HDT, |
| 3315 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10, | 3717 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10, |
| 3316 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 3718 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 3317 | static const struct wacom_features wacom_features_0xCC = | 3719 | static const struct wacom_features wacom_features_0xCC = |
| 3318 | { "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63, | 3720 | { "Wacom Cintiq 21UX2", 87200, 65600, 2047, 63, |
| 3319 | WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, | 3721 | WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, |
| 3722 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3320 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | 3723 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
| 3321 | static const struct wacom_features wacom_features_0xFA = | 3724 | static const struct wacom_features wacom_features_0xFA = |
| 3322 | { "Wacom Cintiq 22HD", 95440, 53860, 2047, 63, | 3725 | { "Wacom Cintiq 22HD", 95840, 54260, 2047, 63, |
| 3323 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, | 3726 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, |
| 3727 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3324 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | 3728 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
| 3325 | static const struct wacom_features wacom_features_0x5B = | 3729 | static const struct wacom_features wacom_features_0x5B = |
| 3326 | { "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63, | 3730 | { "Wacom Cintiq 22HDT", 95840, 54260, 2047, 63, |
| 3327 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, | 3731 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, |
| 3328 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | 3732 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
| 3733 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3329 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e }; | 3734 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e }; |
| 3330 | static const struct wacom_features wacom_features_0x5E = | 3735 | static const struct wacom_features wacom_features_0x5E = |
| 3331 | { "Wacom Cintiq 22HDT", .type = WACOM_24HDT, | 3736 | { "Wacom Cintiq 22HDT", .type = WACOM_24HDT, |
| @@ -3469,18 +3874,20 @@ static const struct wacom_features wacom_features_0x6004 = | |||
| 3469 | { "ISD-V4", 12800, 8000, 255, 0, | 3874 | { "ISD-V4", 12800, 8000, 255, 0, |
| 3470 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 3875 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 3471 | static const struct wacom_features wacom_features_0x307 = | 3876 | static const struct wacom_features wacom_features_0x307 = |
| 3472 | { "Wacom ISDv5 307", 59152, 33448, 2047, 63, | 3877 | { "Wacom ISDv5 307", 59552, 33848, 2047, 63, |
| 3473 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, | 3878 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, |
| 3474 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | 3879 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
| 3880 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3475 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; | 3881 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; |
| 3476 | static const struct wacom_features wacom_features_0x309 = | 3882 | static const struct wacom_features wacom_features_0x309 = |
| 3477 | { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ | 3883 | { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ |
| 3478 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10, | 3884 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10, |
| 3479 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 3885 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 3480 | static const struct wacom_features wacom_features_0x30A = | 3886 | static const struct wacom_features wacom_features_0x30A = |
| 3481 | { "Wacom ISDv5 30A", 59152, 33448, 2047, 63, | 3887 | { "Wacom ISDv5 30A", 59552, 33848, 2047, 63, |
| 3482 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, | 3888 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, |
| 3483 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | 3889 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
| 3890 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3484 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C }; | 3891 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C }; |
| 3485 | static const struct wacom_features wacom_features_0x30C = | 3892 | static const struct wacom_features wacom_features_0x30C = |
| 3486 | { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */ | 3893 | { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */ |
| @@ -3496,6 +3903,7 @@ static const struct wacom_features wacom_features_0x325 = | |||
| 3496 | { "Wacom ISDv5 325", 59552, 33848, 2047, 63, | 3903 | { "Wacom ISDv5 325", 59552, 33848, 2047, 63, |
| 3497 | CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11, | 3904 | CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11, |
| 3498 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | 3905 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
| 3906 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3499 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 }; | 3907 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 }; |
| 3500 | static const struct wacom_features wacom_features_0x326 = /* Touch */ | 3908 | static const struct wacom_features wacom_features_0x326 = /* Touch */ |
| 3501 | { "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM, | 3909 | { "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM, |
| @@ -3525,8 +3933,9 @@ static const struct wacom_features wacom_features_0x33E = | |||
| 3525 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, | 3933 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, |
| 3526 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 3934 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 3527 | static const struct wacom_features wacom_features_0x343 = | 3935 | static const struct wacom_features wacom_features_0x343 = |
| 3528 | { "Wacom DTK1651", 34616, 19559, 1023, 0, | 3936 | { "Wacom DTK1651", 34816, 19759, 1023, 0, |
| 3529 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, | 3937 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, |
| 3938 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, | ||
| 3530 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; | 3939 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; |
| 3531 | 3940 | ||
| 3532 | static const struct wacom_features wacom_features_HID_ANY_ID = | 3941 | static const struct wacom_features wacom_features_HID_ANY_ID = |
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 324c40b0c119..fb0e50acb10d 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h | |||
| @@ -74,6 +74,7 @@ | |||
| 74 | 74 | ||
| 75 | /* device quirks */ | 75 | /* device quirks */ |
| 76 | #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 | 76 | #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 |
| 77 | #define WACOM_QUIRK_SENSE 0x0002 | ||
| 77 | #define WACOM_QUIRK_BATTERY 0x0008 | 78 | #define WACOM_QUIRK_BATTERY 0x0008 |
| 78 | 79 | ||
| 79 | /* device types */ | 80 | /* device types */ |
| @@ -84,23 +85,66 @@ | |||
| 84 | #define WACOM_DEVICETYPE_WL_MONITOR 0x0008 | 85 | #define WACOM_DEVICETYPE_WL_MONITOR 0x0008 |
| 85 | #define WACOM_DEVICETYPE_DIRECT 0x0010 | 86 | #define WACOM_DEVICETYPE_DIRECT 0x0010 |
| 86 | 87 | ||
| 87 | #define WACOM_VENDORDEFINED_PEN 0xff0d0001 | 88 | #define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 |
| 88 | #define WACOM_G9_PAGE 0xff090000 | 89 | #define WACOM_HID_SP_PAD 0x00040000 |
| 89 | #define WACOM_G9_DIGITIZER (WACOM_G9_PAGE | 0x02) | 90 | #define WACOM_HID_SP_BUTTON 0x00090000 |
| 90 | #define WACOM_G9_TOUCHSCREEN (WACOM_G9_PAGE | 0x11) | 91 | #define WACOM_HID_SP_DIGITIZER 0x000d0000 |
| 91 | #define WACOM_G11_PAGE 0xff110000 | 92 | #define WACOM_HID_SP_DIGITIZERINFO 0x00100000 |
| 92 | #define WACOM_G11_DIGITIZER (WACOM_G11_PAGE | 0x02) | 93 | #define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01) |
| 93 | #define WACOM_G11_TOUCHSCREEN (WACOM_G11_PAGE | 0x11) | 94 | #define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) |
| 95 | #define WACOM_HID_WD_DIGITIZERFNKEYS (WACOM_HID_UP_WACOMDIGITIZER | 0x39) | ||
| 96 | #define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c) | ||
| 97 | #define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77) | ||
| 98 | #define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) | ||
| 99 | #define WACOM_HID_WD_TOUCHSTRIP (WACOM_HID_UP_WACOMDIGITIZER | 0x0136) | ||
| 100 | #define WACOM_HID_WD_TOUCHSTRIP2 (WACOM_HID_UP_WACOMDIGITIZER | 0x0137) | ||
| 101 | #define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138) | ||
| 102 | #define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139) | ||
| 103 | #define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401) | ||
| 104 | #define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402) | ||
| 105 | #define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403) | ||
| 106 | #define WACOM_HID_WD_BATTERY_CHARGING (WACOM_HID_UP_WACOMDIGITIZER | 0x0404) | ||
| 107 | #define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b) | ||
| 108 | #define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) | ||
| 109 | #define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950) | ||
| 110 | #define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990) | ||
| 111 | #define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991) | ||
| 112 | #define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992) | ||
| 113 | #define WACOM_HID_WD_BUTTONLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0993) | ||
| 114 | #define WACOM_HID_WD_BUTTONRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0994) | ||
| 115 | #define WACOM_HID_WD_BUTTONCENTER (WACOM_HID_UP_WACOMDIGITIZER | 0x0995) | ||
| 116 | #define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0996) | ||
| 117 | #define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03) | ||
| 118 | #define WACOM_HID_WD_OFFSETLEFT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30) | ||
| 119 | #define WACOM_HID_WD_OFFSETTOP (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31) | ||
| 120 | #define WACOM_HID_WD_OFFSETRIGHT (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32) | ||
| 121 | #define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33) | ||
| 122 | #define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) | ||
| 123 | #define WACOM_HID_WD_DIGITIZERINFO (WACOM_HID_UP_WACOMDIGITIZER | 0x1013) | ||
| 124 | #define WACOM_HID_UP_G9 0xff090000 | ||
| 125 | #define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) | ||
| 126 | #define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) | ||
| 127 | #define WACOM_HID_UP_G11 0xff110000 | ||
| 128 | #define WACOM_HID_G11_PEN (WACOM_HID_UP_G11 | 0x02) | ||
| 129 | #define WACOM_HID_G11_TOUCHSCREEN (WACOM_HID_UP_G11 | 0x11) | ||
| 130 | |||
| 131 | #define WACOM_PAD_FIELD(f) (((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \ | ||
| 132 | ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \ | ||
| 133 | ((f)->physical == WACOM_HID_WD_DIGITIZERINFO)) | ||
| 94 | 134 | ||
| 95 | #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ | 135 | #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ |
| 96 | ((f)->physical == HID_DG_STYLUS) || \ | 136 | ((f)->physical == HID_DG_STYLUS) || \ |
| 97 | ((f)->physical == HID_DG_PEN) || \ | 137 | ((f)->physical == HID_DG_PEN) || \ |
| 98 | ((f)->application == HID_DG_PEN) || \ | 138 | ((f)->application == HID_DG_PEN) || \ |
| 99 | ((f)->application == HID_DG_DIGITIZER) || \ | 139 | ((f)->application == HID_DG_DIGITIZER) || \ |
| 100 | ((f)->application == WACOM_VENDORDEFINED_PEN)) | 140 | ((f)->application == WACOM_HID_WD_DIGITIZER) || \ |
| 141 | ((f)->application == WACOM_HID_G9_PEN) || \ | ||
| 142 | ((f)->application == WACOM_HID_G11_PEN)) | ||
| 101 | #define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \ | 143 | #define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \ |
| 102 | ((f)->physical == HID_DG_FINGER) || \ | 144 | ((f)->physical == HID_DG_FINGER) || \ |
| 103 | ((f)->application == HID_DG_TOUCHSCREEN)) | 145 | ((f)->application == HID_DG_TOUCHSCREEN) || \ |
| 146 | ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \ | ||
| 147 | ((f)->application == WACOM_HID_G11_TOUCHSCREEN)) | ||
| 104 | 148 | ||
| 105 | enum { | 149 | enum { |
| 106 | PENPARTNER = 0, | 150 | PENPARTNER = 0, |
| @@ -167,8 +211,10 @@ struct wacom_features { | |||
| 167 | int x_resolution; | 211 | int x_resolution; |
| 168 | int y_resolution; | 212 | int y_resolution; |
| 169 | int numbered_buttons; | 213 | int numbered_buttons; |
| 170 | int x_min; | 214 | int offset_left; |
| 171 | int y_min; | 215 | int offset_right; |
| 216 | int offset_top; | ||
| 217 | int offset_bottom; | ||
| 172 | int device_type; | 218 | int device_type; |
| 173 | int x_phy; | 219 | int x_phy; |
| 174 | int y_phy; | 220 | int y_phy; |
| @@ -186,6 +232,7 @@ struct wacom_features { | |||
| 186 | int pktlen; | 232 | int pktlen; |
| 187 | bool check_for_hid_type; | 233 | bool check_for_hid_type; |
| 188 | int hid_type; | 234 | int hid_type; |
| 235 | bool input_event_flag; | ||
| 189 | }; | 236 | }; |
| 190 | 237 | ||
| 191 | struct wacom_shared { | 238 | struct wacom_shared { |
| @@ -202,6 +249,7 @@ struct wacom_shared { | |||
| 202 | struct hid_data { | 249 | struct hid_data { |
| 203 | __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ | 250 | __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ |
| 204 | __s16 inputmode_index; /* InputMode HID feature index in the report */ | 251 | __s16 inputmode_index; /* InputMode HID feature index in the report */ |
| 252 | bool sense_state; | ||
| 205 | bool inrange_state; | 253 | bool inrange_state; |
| 206 | bool invert_state; | 254 | bool invert_state; |
| 207 | bool tipswitch; | 255 | bool tipswitch; |
| @@ -217,6 +265,10 @@ struct hid_data { | |||
| 217 | int last_slot_field; | 265 | int last_slot_field; |
| 218 | int num_expected; | 266 | int num_expected; |
| 219 | int num_received; | 267 | int num_received; |
| 268 | int battery_capacity; | ||
| 269 | int bat_charging; | ||
| 270 | int bat_connected; | ||
| 271 | int ps_connected; | ||
| 220 | }; | 272 | }; |
| 221 | 273 | ||
| 222 | struct wacom_remote_data { | 274 | struct wacom_remote_data { |
| @@ -234,7 +286,7 @@ struct wacom_wac { | |||
| 234 | unsigned char data[WACOM_PKGLEN_MAX]; | 286 | unsigned char data[WACOM_PKGLEN_MAX]; |
| 235 | int tool[2]; | 287 | int tool[2]; |
| 236 | int id[2]; | 288 | int id[2]; |
| 237 | __u32 serial[2]; | 289 | __u64 serial[2]; |
| 238 | bool reporting_data; | 290 | bool reporting_data; |
| 239 | struct wacom_features features; | 291 | struct wacom_features features; |
| 240 | struct wacom_shared *shared; | 292 | struct wacom_shared *shared; |
diff --git a/include/linux/hid.h b/include/linux/hid.h index b2ec82712baa..28f38e2b8f30 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -231,7 +231,11 @@ struct hid_item { | |||
| 231 | #define HID_DG_TAP 0x000d0035 | 231 | #define HID_DG_TAP 0x000d0035 |
| 232 | #define HID_DG_TABLETFUNCTIONKEY 0x000d0039 | 232 | #define HID_DG_TABLETFUNCTIONKEY 0x000d0039 |
| 233 | #define HID_DG_PROGRAMCHANGEKEY 0x000d003a | 233 | #define HID_DG_PROGRAMCHANGEKEY 0x000d003a |
| 234 | #define HID_DG_BATTERYSTRENGTH 0x000d003b | ||
| 234 | #define HID_DG_INVERT 0x000d003c | 235 | #define HID_DG_INVERT 0x000d003c |
| 236 | #define HID_DG_TILT_X 0x000d003d | ||
| 237 | #define HID_DG_TILT_Y 0x000d003e | ||
| 238 | #define HID_DG_TWIST 0x000d0041 | ||
| 235 | #define HID_DG_TIPSWITCH 0x000d0042 | 239 | #define HID_DG_TIPSWITCH 0x000d0042 |
| 236 | #define HID_DG_TIPSWITCH2 0x000d0043 | 240 | #define HID_DG_TIPSWITCH2 0x000d0043 |
| 237 | #define HID_DG_BARRELSWITCH 0x000d0044 | 241 | #define HID_DG_BARRELSWITCH 0x000d0044 |
| @@ -479,6 +483,7 @@ struct hid_input { | |||
| 479 | struct list_head list; | 483 | struct list_head list; |
| 480 | struct hid_report *report; | 484 | struct hid_report *report; |
| 481 | struct input_dev *input; | 485 | struct input_dev *input; |
| 486 | bool registered; | ||
| 482 | }; | 487 | }; |
| 483 | 488 | ||
| 484 | enum hid_type { | 489 | enum hid_type { |
