Pull HID subsystem updates from Jiri Kosina: - The need for HID_QUIRK_NO_INIT_REPORTS per-device quirk has been growing dramatically during past years, so the time has come to switch over the default, and perform the pro-active reading only in cases where it's really needed (multitouch, wacom). The only place where this behavior is (in some form) preserved is hiddev so that we don't introduce userspace-visible change of behavior. From Benjamin Tissoires - HID++ support for power_supply / baterry reporting. From Benjamin Tissoires and Bastien Nocera - Vast improvements / rework of DS3 and DS4 in Sony driver. From Roderick Colenbrander - Improvment (in terms of getting closer to the Microsoft's interpretation of slightly ambiguous specification) of logical range interpretation in case null-state is set in the rdesc. From Valtteri Heikkilä and Tomasz Kramkowski - A lot of newly supported device IDs and small assorted fixes * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (71 commits) HID: usbhid: Add HID_QUIRK_NOGET for Aten CS-1758 KVM switch HID: asus: support backlight on USB keyboards HID: wacom: Move wacom_remote_irq and wacom_remote_status_irq HID: wacom: generic: sync pad events only for actual packets HID: sony: remove redundant check for -ve err HID: sony: Make sure to unregister sensors on failure HID: sony: Make DS4 bt poll interval adjustable HID: sony: Set proper bit flags on DS4 output report HID: sony: DS4 use brighter LED colors HID: sony: Improve navigation controller axis/button mapping HID: sony: Use DS3 MAC address as unique identifier on USB HID: logitech-hidpp: add a sysfs file to tell we support power_supply HID: logitech-hidpp: enable HID++ 1.0 battery reporting HID: logitech-hidpp: add support for battery status for the K750 HID: logitech-hidpp: battery: provide CAPACITY_LEVEL HID: logitech-hidpp: rename battery level into capacity HID: logitech-hidpp: battery: provide ONLINE property HID: logitech-hidpp: notify battery on connect HID: logitech-hidpp: return an error if the queried feature is not present HID: logitech-hidpp: create the battery for all types of HID++ devices ...
Unified · Split
| @@ -4127,6 +4127,9 @@ · 4126 unmodified lines | ||
| 4127 | 4127 | usbhid.mousepoll= |
| 4128 | 4128 | [USBHID] The interval which mice are to be polled at. |
| 4129 | 4129 | |
| 4130 | + usbhid.jspoll= | |
| 4131 | + [USBHID] The interval which joysticks are to be polled at. | |
| 4132 | + | |
| 4130 | 4133 | usb-storage.delay_use= |
| 4131 | 4134 | [UMS] The delay in seconds before a new device is |
| 4132 | 4135 | scanned for Logical Units (default 1). |
| @@ -17,6 +17,22 @@ Required properties: · 16 unmodified lines | ||
| 17 | 17 | - interrupt-parent: the phandle for the interrupt controller |
| 18 | 18 | - interrupts: interrupt line |
| 19 | 19 | |
| 20 | +Additional optional properties: | |
| 21 | + | |
| 22 | +Some devices may support additional optional properties to help with, e.g., | |
| 23 | +power sequencing. The following properties can be supported by one or more | |
| 24 | +device-specific compatible properties, which should be used in addition to the | |
| 25 | +"hid-over-i2c" string. | |
| 26 | + | |
| 27 | +- compatible: | |
| 28 | + * "wacom,w9013" (Wacom W9013 digitizer). Supports: | |
| 29 | + - vdd-supply | |
| 30 | + - post-power-on-delay-ms | |
| 31 | + | |
| 32 | +- vdd-supply: phandle of the regulator that provides the supply voltage. | |
| 33 | +- post-power-on-delay-ms: time required by the device after enabling its regulators | |
| 34 | + before it is ready for communication. Must be used with 'vdd-supply'. | |
| 35 | + | |
| 20 | 36 | Example: |
| 21 | 37 | |
| 22 | 38 | i2c-hid-dev@2c { |
| @@ -301,7 +301,10 @@ them as any other INPUT_PROP_BUTTONPAD device. · 300 unmodified lines | ||
| 301 | 301 | INPUT_PROP_ACCELEROMETER |
| 302 | 302 | ------------------------- |
| 303 | 303 | Directional axes on this device (absolute and/or relative x, y, z) represent |
| 304 | −accelerometer data. All other axes retain their meaning. A device must not mix | |
| 304 | +accelerometer data. Some devices also report gyroscope data, which devices | |
| 305 | +can report through the rotational axes (absolute and/or relative rx, ry, rz). | |
| 306 | + | |
| 307 | +All other axes retain their meaning. A device must not mix | |
| 305 | 308 | regular directional axes and accelerometer axes on the same event node. |
| 306 | 309 | |
| 307 | 310 | Guidelines: |
| @@ -98,6 +98,18 @@ config HID_A4TECH · 97 unmodified lines | ||
| 98 | 98 | ---help--- |
| 99 | 99 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. |
| 100 | 100 | |
| 101 | +config HID_ACCUTOUCH | |
| 102 | + tristate "Accutouch touch device" | |
| 103 | + depends on USB_HID | |
| 104 | + ---help--- | |
| 105 | + This selects a driver for the Accutouch 2216 touch controller. | |
| 106 | + | |
| 107 | + The driver works around a problem in the reported device capabilities | |
| 108 | + which causes userspace to detect the device as a mouse rather than | |
| 109 | + a touchscreen. | |
| 110 | + | |
| 111 | + Say Y here if you have a Accutouch 2216 touch controller. | |
| 112 | + | |
| 101 | 113 | config HID_ACRUX |
| 102 | 114 | tristate "ACRUX game controller support" |
| 103 | 115 | depends on HID |
| @@ -136,13 +148,16 @@ config HID_APPLEIR · 32 unmodified lines | ||
| 136 | 148 | |
| 137 | 149 | config HID_ASUS |
| 138 | 150 | tristate "Asus" |
| 139 | − depends on I2C_HID | |
| 151 | + depends on LEDS_CLASS | |
| 140 | 152 | ---help--- |
| 141 | − Support for Asus notebook built-in keyboard and touchpad via i2c. | |
| 153 | + Support for Asus notebook built-in keyboard and touchpad via i2c, and | |
| 154 | + the Asus Republic of Gamers laptop keyboard special keys. | |
| 142 | 155 | |
| 143 | 156 | Supported devices: |
| 144 | 157 | - EeeBook X205TA |
| 145 | 158 | - VivoBook E200HA |
| 159 | + - GL553V series | |
| 160 | + - GL753V series | |
| 146 | 161 | |
| 147 | 162 | config HID_AUREAL |
| 148 | 163 | tristate "Aureal" |
| @@ -215,7 +230,8 @@ config HID_CMEDIA · 66 unmodified lines | ||
| 215 | 230 | |
| 216 | 231 | config HID_CP2112 |
| 217 | 232 | tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support" |
| 218 | − depends on USB_HID && I2C && GPIOLIB && GPIOLIB_IRQCHIP | |
| 233 | + depends on USB_HID && I2C && GPIOLIB | |
| 234 | + select GPIOLIB_IRQCHIP | |
| 219 | 235 | ---help--- |
| 220 | 236 | Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge. |
| 221 | 237 | This is a HID device driver which registers as an i2c adapter |
| @@ -441,6 +457,7 @@ config HID_LOGITECH_DJ · 219 unmodified lines | ||
| 441 | 457 | config HID_LOGITECH_HIDPP |
| 442 | 458 | tristate "Logitech HID++ devices support" |
| 443 | 459 | depends on HID_LOGITECH |
| 460 | + select POWER_SUPPLY | |
| 444 | 461 | ---help--- |
| 445 | 462 | Support for Logitech devices relyingon the HID++ Logitech specification |
| 446 | 463 | |
| @@ -581,6 +598,12 @@ config HID_MULTITOUCH · 134 unmodified lines | ||
| 581 | 598 | To compile this driver as a module, choose M here: the |
| 582 | 599 | module will be called hid-multitouch. |
| 583 | 600 | |
| 601 | +config HID_NTI | |
| 602 | + tristate "NTI keyboard adapters" | |
| 603 | + ---help--- | |
| 604 | + Support for the "extra" Sun keyboard keys on keyboards attached | |
| 605 | + through Network Technologies USB-SUN keyboard adapters. | |
| 606 | + | |
| 584 | 607 | config HID_NTRIG |
| 585 | 608 | tristate "N-Trig touch screen" |
| 586 | 609 | depends on USB_HID |
| @@ -21,6 +21,7 @@ hid-wiimote-y := hid-wiimote-core.o hid-wiimote-modules.o · 20 unmodified lines | ||
| 21 | 21 | hid-wiimote-$(CONFIG_DEBUG_FS) += hid-wiimote-debug.o |
| 22 | 22 | |
| 23 | 23 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o |
| 24 | +obj-$(CONFIG_HID_ACCUTOUCH) += hid-accutouch.o | |
| 24 | 25 | obj-$(CONFIG_HID_ALPS) += hid-alps.o |
| 25 | 26 | obj-$(CONFIG_HID_ACRUX) += hid-axff.o |
| 26 | 27 | obj-$(CONFIG_HID_APPLE) += hid-apple.o |
| @@ -62,6 +63,7 @@ obj-$(CONFIG_HID_MAYFLASH) += hid-mf.o · 35 unmodified lines | ||
| 62 | 63 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
| 63 | 64 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
| 64 | 65 | obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o |
| 66 | +obj-$(CONFIG_HID_NTI) += hid-nti.o | |
| 65 | 67 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o |
| 66 | 68 | obj-$(CONFIG_HID_ORTEK) += hid-ortek.o |
| 67 | 69 | obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o |
| @@ -0,0 +1,52 @@ | ||
| 1 | +/* | |
| 2 | + * HID driver for Elo Accutouch touchscreens | |
| 3 | + * | |
| 4 | + * Copyright (c) 2016, Collabora Ltd. | |
| 5 | + * Copyright (c) 2016, General Electric Company | |
| 6 | + * | |
| 7 | + * based on hid-penmount.c | |
| 8 | + * Copyright (c) 2014 Christian Gmeiner <christian.gmeiner <at> gmail.com> | |
| 9 | + */ | |
| 10 | + | |
| 11 | +/* | |
| 12 | + * This program is free software; you can redistribute it and/or modify it | |
| 13 | + * under the terms of the GNU General Public License as published by the Free | |
| 14 | + * Software Foundation; either version 2 of the License, or (at your option) | |
| 15 | + * any later version. | |
| 16 | + */ | |
| 17 | + | |
| 18 | +#include <linux/hid.h> | |
| 19 | +#include <linux/module.h> | |
| 20 | +#include "hid-ids.h" | |
| 21 | + | |
| 22 | +static int accutouch_input_mapping(struct hid_device *hdev, | |
| 23 | + struct hid_input *hi, | |
| 24 | + struct hid_field *field, | |
| 25 | + struct hid_usage *usage, | |
| 26 | + unsigned long **bit, int *max) | |
| 27 | +{ | |
| 28 | + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { | |
| 29 | + hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | |
| 30 | + return 1; | |
| 31 | + } | |
| 32 | + | |
| 33 | + return 0; | |
| 34 | +} | |
| 35 | + | |
| 36 | +static const struct hid_device_id accutouch_devices[] = { | |
| 37 | + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) }, | |
| 38 | + { } | |
| 39 | +}; | |
| 40 | +MODULE_DEVICE_TABLE(hid, accutouch_devices); | |
| 41 | + | |
| 42 | +static struct hid_driver accutouch_driver = { | |
| 43 | + .name = "hid-accutouch", | |
| 44 | + .id_table = accutouch_devices, | |
| 45 | + .input_mapping = accutouch_input_mapping, | |
| 46 | +}; | |
| 47 | + | |
| 48 | +module_hid_driver(accutouch_driver); | |
| 49 | + | |
| 50 | +MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk"); | |
| 51 | +MODULE_DESCRIPTION("Elo Accutouch HID TouchScreen driver"); | |
| 52 | +MODULE_LICENSE("GPL"); | |
| @@ -40,8 +40,12 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | #define FEATURE_REPORT_ID 0x0d |
| 42 | 42 | #define INPUT_REPORT_ID 0x5d |
| 43 | +#define FEATURE_KBD_REPORT_ID 0x5a | |
| 43 | 44 | |
| 44 | 45 | #define INPUT_REPORT_SIZE 28 |
| 46 | +#define FEATURE_KBD_REPORT_SIZE 16 | |
| 47 | + | |
| 48 | +#define SUPPORT_KBD_BACKLIGHT BIT(0) | |
| 45 | 49 | |
| 46 | 50 | #define MAX_CONTACTS 5 |
| 47 | 51 | |
| @@ -63,18 +67,31 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); · 15 unmodified lines | ||
| 63 | 67 | #define QUIRK_NO_INIT_REPORTS BIT(1) |
| 64 | 68 | #define QUIRK_SKIP_INPUT_MAPPING BIT(2) |
| 65 | 69 | #define QUIRK_IS_MULTITOUCH BIT(3) |
| 70 | +#define QUIRK_NO_CONSUMER_USAGES BIT(4) | |
| 71 | +#define QUIRK_USE_KBD_BACKLIGHT BIT(5) | |
| 66 | 72 | |
| 67 | −#define KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ | |
| 68 | − QUIRK_NO_INIT_REPORTS) | |
| 69 | −#define TOUCHPAD_QUIRKS (QUIRK_NO_INIT_REPORTS | \ | |
| 73 | +#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ | |
| 74 | + QUIRK_NO_INIT_REPORTS | \ | |
| 75 | + QUIRK_NO_CONSUMER_USAGES) | |
| 76 | +#define I2C_TOUCHPAD_QUIRKS (QUIRK_NO_INIT_REPORTS | \ | |
| 70 | 77 | QUIRK_SKIP_INPUT_MAPPING | \ |
| 71 | 78 | QUIRK_IS_MULTITOUCH) |
| 72 | 79 | |
| 73 | 80 | #define TRKID_SGN ((TRKID_MAX + 1) >> 1) |
| 74 | 81 | |
| 82 | +struct asus_kbd_leds { | |
| 83 | + struct led_classdev cdev; | |
| 84 | + struct hid_device *hdev; | |
| 85 | + struct work_struct work; | |
| 86 | + unsigned int brightness; | |
| 87 | + bool removed; | |
| 88 | +}; | |
| 89 | + | |
| 75 | 90 | struct asus_drvdata { |
| 76 | 91 | unsigned long quirks; |
| 77 | 92 | struct input_dev *input; |
| 93 | + struct asus_kbd_leds *kbd_backlight; | |
| 94 | + bool enable_backlight; | |
| 78 | 95 | }; |
| 79 | 96 | |
| 80 | 97 | static void asus_report_contact_down(struct input_dev *input, |
| @@ -169,6 +186,148 @@ static int asus_raw_event(struct hid_device *hdev, · 88 unmodified lines | ||
| 169 | 186 | return 0; |
| 170 | 187 | } |
| 171 | 188 | |
| 189 | +static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size) | |
| 190 | +{ | |
| 191 | + unsigned char *dmabuf; | |
| 192 | + int ret; | |
| 193 | + | |
| 194 | + dmabuf = kmemdup(buf, buf_size, GFP_KERNEL); | |
| 195 | + if (!dmabuf) | |
| 196 | + return -ENOMEM; | |
| 197 | + | |
| 198 | + ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, dmabuf, | |
| 199 | + buf_size, HID_FEATURE_REPORT, | |
| 200 | + HID_REQ_SET_REPORT); | |
| 201 | + kfree(dmabuf); | |
| 202 | + | |
| 203 | + return ret; | |
| 204 | +} | |
| 205 | + | |
| 206 | +static int asus_kbd_init(struct hid_device *hdev) | |
| 207 | +{ | |
| 208 | + u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54, | |
| 209 | + 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 }; | |
| 210 | + int ret; | |
| 211 | + | |
| 212 | + ret = asus_kbd_set_report(hdev, buf, sizeof(buf)); | |
| 213 | + if (ret < 0) | |
| 214 | + hid_err(hdev, "Asus failed to send init command: %d\n", ret); | |
| 215 | + | |
| 216 | + return ret; | |
| 217 | +} | |
| 218 | + | |
| 219 | +static int asus_kbd_get_functions(struct hid_device *hdev, | |
| 220 | + unsigned char *kbd_func) | |
| 221 | +{ | |
| 222 | + u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 }; | |
| 223 | + u8 *readbuf; | |
| 224 | + int ret; | |
| 225 | + | |
| 226 | + ret = asus_kbd_set_report(hdev, buf, sizeof(buf)); | |
| 227 | + if (ret < 0) { | |
| 228 | + hid_err(hdev, "Asus failed to send configuration command: %d\n", ret); | |
| 229 | + return ret; | |
| 230 | + } | |
| 231 | + | |
| 232 | + readbuf = kzalloc(FEATURE_KBD_REPORT_SIZE, GFP_KERNEL); | |
| 233 | + if (!readbuf) | |
| 234 | + return -ENOMEM; | |
| 235 | + | |
| 236 | + ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, readbuf, | |
| 237 | + FEATURE_KBD_REPORT_SIZE, HID_FEATURE_REPORT, | |
| 238 | + HID_REQ_GET_REPORT); | |
| 239 | + if (ret < 0) { | |
| 240 | + hid_err(hdev, "Asus failed to request functions: %d\n", ret); | |
| 241 | + kfree(readbuf); | |
| 242 | + return ret; | |
| 243 | + } | |
| 244 | + | |
| 245 | + *kbd_func = readbuf[6]; | |
| 246 | + | |
| 247 | + kfree(readbuf); | |
| 248 | + return ret; | |
| 249 | +} | |
| 250 | + | |
| 251 | +static void asus_kbd_backlight_set(struct led_classdev *led_cdev, | |
| 252 | + enum led_brightness brightness) | |
| 253 | +{ | |
| 254 | + struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds, | |
| 255 | + cdev); | |
| 256 | + if (led->brightness == brightness) | |
| 257 | + return; | |
| 258 | + | |
| 259 | + led->brightness = brightness; | |
| 260 | + schedule_work(&led->work); | |
| 261 | +} | |
| 262 | + | |
| 263 | +static enum led_brightness asus_kbd_backlight_get(struct led_classdev *led_cdev) | |
| 264 | +{ | |
| 265 | + struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds, | |
| 266 | + cdev); | |
| 267 | + | |
| 268 | + return led->brightness; | |
| 269 | +} | |
| 270 | + | |
| 271 | +static void asus_kbd_backlight_work(struct work_struct *work) | |
| 272 | +{ | |
| 273 | + struct asus_kbd_leds *led = container_of(work, struct asus_kbd_leds, work); | |
| 274 | + u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4, 0x00 }; | |
| 275 | + int ret; | |
| 276 | + | |
| 277 | + if (led->removed) | |
| 278 | + return; | |
| 279 | + | |
| 280 | + buf[4] = led->brightness; | |
| 281 | + | |
| 282 | + ret = asus_kbd_set_report(led->hdev, buf, sizeof(buf)); | |
| 283 | + if (ret < 0) | |
| 284 | + hid_err(led->hdev, "Asus failed to set keyboard backlight: %d\n", ret); | |
| 285 | +} | |
| 286 | + | |
| 287 | +static int asus_kbd_register_leds(struct hid_device *hdev) | |
| 288 | +{ | |
| 289 | + struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | |
| 290 | + unsigned char kbd_func; | |
| 291 | + int ret; | |
| 292 | + | |
| 293 | + /* Initialize keyboard */ | |
| 294 | + ret = asus_kbd_init(hdev); | |
| 295 | + if (ret < 0) | |
| 296 | + return ret; | |
| 297 | + | |
| 298 | + /* Get keyboard functions */ | |
| 299 | + ret = asus_kbd_get_functions(hdev, &kbd_func); | |
| 300 | + if (ret < 0) | |
| 301 | + return ret; | |
| 302 | + | |
| 303 | + /* Check for backlight support */ | |
| 304 | + if (!(kbd_func & SUPPORT_KBD_BACKLIGHT)) | |
| 305 | + return -ENODEV; | |
| 306 | + | |
| 307 | + drvdata->kbd_backlight = devm_kzalloc(&hdev->dev, | |
| 308 | + sizeof(struct asus_kbd_leds), | |
| 309 | + GFP_KERNEL); | |
| 310 | + if (!drvdata->kbd_backlight) | |
| 311 | + return -ENOMEM; | |
| 312 | + | |
| 313 | + drvdata->kbd_backlight->removed = false; | |
| 314 | + drvdata->kbd_backlight->brightness = 0; | |
| 315 | + drvdata->kbd_backlight->hdev = hdev; | |
| 316 | + drvdata->kbd_backlight->cdev.name = "asus::kbd_backlight"; | |
| 317 | + drvdata->kbd_backlight->cdev.max_brightness = 3; | |
| 318 | + drvdata->kbd_backlight->cdev.brightness_set = asus_kbd_backlight_set; | |
| 319 | + drvdata->kbd_backlight->cdev.brightness_get = asus_kbd_backlight_get; | |
| 320 | + INIT_WORK(&drvdata->kbd_backlight->work, asus_kbd_backlight_work); | |
| 321 | + | |
| 322 | + ret = devm_led_classdev_register(&hdev->dev, &drvdata->kbd_backlight->cdev); | |
| 323 | + if (ret < 0) { | |
| 324 | + /* No need to have this still around */ | |
| 325 | + devm_kfree(&hdev->dev, drvdata->kbd_backlight); | |
| 326 | + } | |
| 327 | + | |
| 328 | + return ret; | |
| 329 | +} | |
| 330 | + | |
| 172 | 331 | static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi) |
| 173 | 332 | { |
| 174 | 333 | struct input_dev *input = hi->input; |
| @@ -196,9 +355,14 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi) · 21 unmodified lines | ||
| 196 | 355 | |
| 197 | 356 | drvdata->input = input; |
| 198 | 357 | |
| 358 | + if (drvdata->enable_backlight && asus_kbd_register_leds(hdev)) | |
| 359 | + hid_warn(hdev, "Failed to initialize backlight.\n"); | |
| 360 | + | |
| 199 | 361 | return 0; |
| 200 | 362 | } |
| 201 | 363 | |
| 364 | +#define asus_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, \ | |
| 365 | + max, EV_KEY, (c)) | |
| 202 | 366 | static int asus_input_mapping(struct hid_device *hdev, |
| 203 | 367 | struct hid_input *hi, struct hid_field *field, |
| 204 | 368 | struct hid_usage *usage, unsigned long **bit, |
| @@ -213,6 +377,65 @@ static int asus_input_mapping(struct hid_device *hdev, · 8 unmodified lines | ||
| 213 | 377 | return -1; |
| 214 | 378 | } |
| 215 | 379 | |
| 380 | + /* ASUS-specific keyboard hotkeys */ | |
| 381 | + if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) { | |
| 382 | + set_bit(EV_REP, hi->input->evbit); | |
| 383 | + switch (usage->hid & HID_USAGE) { | |
| 384 | + case 0x10: asus_map_key_clear(KEY_BRIGHTNESSDOWN); break; | |
| 385 | + case 0x20: asus_map_key_clear(KEY_BRIGHTNESSUP); break; | |
| 386 | + case 0x35: asus_map_key_clear(KEY_DISPLAY_OFF); break; | |
| 387 | + case 0x6c: asus_map_key_clear(KEY_SLEEP); break; | |
| 388 | + case 0x82: asus_map_key_clear(KEY_CAMERA); break; | |
| 389 | + case 0x88: asus_map_key_clear(KEY_RFKILL); break; | |
| 390 | + case 0xb5: asus_map_key_clear(KEY_CALC); break; | |
| 391 | + case 0xc4: asus_map_key_clear(KEY_KBDILLUMUP); break; | |
| 392 | + case 0xc5: asus_map_key_clear(KEY_KBDILLUMDOWN); break; | |
| 393 | + | |
| 394 | + /* ASUS touchpad toggle */ | |
| 395 | + case 0x6b: asus_map_key_clear(KEY_F21); break; | |
| 396 | + | |
| 397 | + /* ROG key */ | |
| 398 | + case 0x38: asus_map_key_clear(KEY_PROG1); break; | |
| 399 | + | |
| 400 | + /* Fn+C ASUS Splendid */ | |
| 401 | + case 0xba: asus_map_key_clear(KEY_PROG2); break; | |
| 402 | + | |
| 403 | + /* Fn+Space Power4Gear Hybrid */ | |
| 404 | + case 0x5c: asus_map_key_clear(KEY_PROG3); break; | |
| 405 | + | |
| 406 | + default: | |
| 407 | + /* ASUS lazily declares 256 usages, ignore the rest, | |
| 408 | + * as some make the keyboard appear as a pointer device. */ | |
| 409 | + return -1; | |
| 410 | + } | |
| 411 | + | |
| 412 | + /* | |
| 413 | + * Check and enable backlight only on devices with UsagePage == | |
| 414 | + * 0xff31 to avoid initializing the keyboard firmware multiple | |
| 415 | + * times on devices with multiple HID descriptors but same | |
| 416 | + * PID/VID. | |
| 417 | + */ | |
| 418 | + if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT) | |
| 419 | + drvdata->enable_backlight = true; | |
| 420 | + | |
| 421 | + return 1; | |
| 422 | + } | |
| 423 | + | |
| 424 | + if (drvdata->quirks & QUIRK_NO_CONSUMER_USAGES && | |
| 425 | + (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) { | |
| 426 | + switch (usage->hid & HID_USAGE) { | |
| 427 | + case 0xe2: /* Mute */ | |
| 428 | + case 0xe9: /* Volume up */ | |
| 429 | + case 0xea: /* Volume down */ | |
| 430 | + return 0; | |
| 431 | + default: | |
| 432 | + /* Ignore dummy Consumer usages which make the | |
| 433 | + * keyboard incorrectly appear as a pointer device. | |
| 434 | + */ | |
| 435 | + return -1; | |
| 436 | + } | |
| 437 | + } | |
| 438 | + | |
| 216 | 439 | return 0; |
| 217 | 440 | } |
| 218 | 441 | |
| @@ -305,6 +528,16 @@ err_stop_hw: · 86 unmodified lines | ||
| 305 | 528 | return ret; |
| 306 | 529 | } |
| 307 | 530 | |
| 531 | +static void asus_remove(struct hid_device *hdev) | |
| 532 | +{ | |
| 533 | + struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | |
| 534 | + | |
| 535 | + if (drvdata->kbd_backlight) { | |
| 536 | + drvdata->kbd_backlight->removed = true; | |
| 537 | + cancel_work_sync(&drvdata->kbd_backlight->work); | |
| 538 | + } | |
| 539 | +} | |
| 540 | + | |
| 308 | 541 | static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 309 | 542 | unsigned int *rsize) |
| 310 | 543 | { |
| @@ -320,9 +553,13 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 9 unmodified lines | ||
| 320 | 553 | |
| 321 | 554 | static const struct hid_device_id asus_devices[] = { |
| 322 | 555 | { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 323 | − USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD), KEYBOARD_QUIRKS}, | |
| 556 | + USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD), I2C_KEYBOARD_QUIRKS}, | |
| 324 | 557 | { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 325 | − USB_DEVICE_ID_ASUSTEK_TOUCHPAD), TOUCHPAD_QUIRKS }, | |
| 558 | + USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD), I2C_TOUCHPAD_QUIRKS }, | |
| 559 | + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, | |
| 560 | + USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) }, | |
| 561 | + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, | |
| 562 | + USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT }, | |
| 326 | 563 | { } |
| 327 | 564 | }; |
| 328 | 565 | MODULE_DEVICE_TABLE(hid, asus_devices); |
| @@ -332,6 +569,7 @@ static struct hid_driver asus_driver = { · 3 unmodified lines | ||
| 332 | 569 | .id_table = asus_devices, |
| 333 | 570 | .report_fixup = asus_report_fixup, |
| 334 | 571 | .probe = asus_probe, |
| 572 | + .remove = asus_remove, | |
| 335 | 573 | .input_mapping = asus_input_mapping, |
| 336 | 574 | .input_configured = asus_input_configured, |
| 337 | 575 | #ifdef CONFIG_PM |
| @@ -1694,7 +1694,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) · 1693 unmodified lines | ||
| 1694 | 1694 | len += sprintf(buf + len, "input"); |
| 1695 | 1695 | if (hdev->claimed & HID_CLAIMED_HIDDEV) |
| 1696 | 1696 | len += sprintf(buf + len, "%shiddev%d", len ? "," : "", |
| 1697 | − hdev->minor); | |
| 1697 | + ((struct hiddev *)hdev->hiddev)->minor); | |
| 1698 | 1698 | if (hdev->claimed & HID_CLAIMED_HIDRAW) |
| 1699 | 1699 | len += sprintf(buf + len, "%shidraw%d", len ? "," : "", |
| 1700 | 1700 | ((struct hidraw *)hdev->hidraw)->minor); |
| @@ -1851,8 +1851,10 @@ static const struct hid_device_id hid_have_special_driver[] = { · 150 unmodified lines | ||
| 1851 | 1851 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) }, |
| 1852 | 1852 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1853 | 1853 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1854 | − { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) }, | |
| 1855 | − { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_TOUCHPAD) }, | |
| 1854 | + { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD) }, | |
| 1855 | + { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) }, | |
| 1856 | + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) }, | |
| 1857 | + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) }, | |
| 1856 | 1858 | { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, |
| 1857 | 1859 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
| 1858 | 1860 | { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, |
| @@ -1891,6 +1893,7 @@ static const struct hid_device_id hid_have_special_driver[] = { · 32 unmodified lines | ||
| 1891 | 1893 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
| 1892 | 1894 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, |
| 1893 | 1895 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) }, |
| 1896 | + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) }, | |
| 1894 | 1897 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, |
| 1895 | 1898 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
| 1896 | 1899 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, |
| @@ -1991,6 +1994,7 @@ static const struct hid_device_id hid_have_special_driver[] = { · 94 unmodified lines | ||
| 1991 | 1994 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) }, |
| 1992 | 1995 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, |
| 1993 | 1996 | { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, |
| 1997 | + { HID_USB_DEVICE(USB_VENDOR_ID_NTI, USB_DEVICE_ID_USB_SUN) }, | |
| 1994 | 1998 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, |
| 1995 | 1999 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, |
| 1996 | 2000 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) }, |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/gpio.h> |
| 28 | 28 | #include <linux/gpio/driver.h> |
| 29 | 29 | #include <linux/hid.h> |
| 30 | +#include <linux/hidraw.h> | |
| 30 | 31 | #include <linux/i2c.h> |
| 31 | 32 | #include <linux/module.h> |
| 32 | 33 | #include <linux/nls.h> |
| @@ -1297,7 +1298,8 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) · 1264 unmodified lines | ||
| 1297 | 1298 | dev->adap.algo_data = dev; |
| 1298 | 1299 | dev->adap.dev.parent = &hdev->dev; |
| 1299 | 1300 | snprintf(dev->adap.name, sizeof(dev->adap.name), |
| 1300 | − "CP2112 SMBus Bridge on hiddev%d", hdev->minor); | |
| 1301 | + "CP2112 SMBus Bridge on hidraw%d", | |
| 1302 | + ((struct hidraw *)hdev->hidraw)->minor); | |
| 1301 | 1303 | dev->hwversion = buf[2]; |
| 1302 | 1304 | init_waitqueue_head(&dev->wait); |
| 1303 | 1305 | |
| @@ -140,9 +140,11 @@ static const struct hid_usage_entry hid_usage_table[] = { · 139 unmodified lines | ||
| 140 | 140 | {0, 0x03, "LightPen"}, |
| 141 | 141 | {0, 0x04, "TouchScreen"}, |
| 142 | 142 | {0, 0x05, "TouchPad"}, |
| 143 | + {0, 0x0e, "DeviceConfiguration"}, | |
| 143 | 144 | {0, 0x20, "Stylus"}, |
| 144 | 145 | {0, 0x21, "Puck"}, |
| 145 | 146 | {0, 0x22, "Finger"}, |
| 147 | + {0, 0x23, "DeviceSettings"}, | |
| 146 | 148 | {0, 0x30, "TipPressure"}, |
| 147 | 149 | {0, 0x31, "BarrelPressure"}, |
| 148 | 150 | {0, 0x32, "InRange"}, |
| @@ -173,8 +173,10 @@ · 172 unmodified lines | ||
| 173 | 173 | #define USB_VENDOR_ID_ASUSTEK 0x0b05 |
| 174 | 174 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 |
| 175 | 175 | #define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b |
| 176 | −#define USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD 0x8585 | |
| 177 | −#define USB_DEVICE_ID_ASUSTEK_TOUCHPAD 0x0101 | |
| 176 | +#define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585 | |
| 177 | +#define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD 0x0101 | |
| 178 | +#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854 | |
| 179 | +#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2 0x1837 | |
| 178 | 180 | |
| 179 | 181 | #define USB_VENDOR_ID_ATEN 0x0557 |
| 180 | 182 | #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 |
| @@ -184,6 +186,7 @@ · 3 unmodified lines | ||
| 184 | 186 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 |
| 185 | 187 | #define USB_DEVICE_ID_ATEN_CS682 0x2213 |
| 186 | 188 | #define USB_DEVICE_ID_ATEN_CS692 0x8021 |
| 189 | +#define USB_DEVICE_ID_ATEN_CS1758 0x2220 | |
| 187 | 190 | |
| 188 | 191 | #define USB_VENDOR_ID_ATMEL 0x03eb |
| 189 | 192 | #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c |
| @@ -366,6 +369,7 @@ · 176 unmodified lines | ||
| 366 | 369 | #define USB_VENDOR_ID_ELO 0x04E7 |
| 367 | 370 | #define USB_DEVICE_ID_ELO_TS2515 0x0022 |
| 368 | 371 | #define USB_DEVICE_ID_ELO_TS2700 0x0020 |
| 372 | +#define USB_DEVICE_ID_ELO_ACCUTOUCH_2216 0x0050 | |
| 369 | 373 | |
| 370 | 374 | #define USB_VENDOR_ID_EMS 0x2006 |
| 371 | 375 | #define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118 |
| @@ -548,6 +552,9 @@ · 176 unmodified lines | ||
| 548 | 552 | #define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 |
| 549 | 553 | #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 |
| 550 | 554 | |
| 555 | +#define USB_VENDOR_ID_INNOMEDIA 0x1292 | |
| 556 | +#define USB_DEVICE_ID_INNEX_GENESIS_ATARI 0x4745 | |
| 557 | + | |
| 551 | 558 | #define USB_VENDOR_ID_ITE 0x048d |
| 552 | 559 | #define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386 |
| 553 | 560 | #define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350 |
| @@ -771,6 +778,9 @@ · 217 unmodified lines | ||
| 771 | 778 | #define USB_DEVICE_ID_NOVATEK_PCT 0x0600 |
| 772 | 779 | #define USB_DEVICE_ID_NOVATEK_MOUSE 0x1602 |
| 773 | 780 | |
| 781 | +#define USB_VENDOR_ID_NTI 0x0757 | |
| 782 | +#define USB_DEVICE_ID_USB_SUN 0x0a00 | |
| 783 | + | |
| 774 | 784 | #define USB_VENDOR_ID_NTRIG 0x1b96 |
| 775 | 785 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 |
| 776 | 786 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 |
| @@ -1150,18 +1150,26 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct · 1149 unmodified lines | ||
| 1150 | 1150 | |
| 1151 | 1151 | /* |
| 1152 | 1152 | * Ignore out-of-range values as per HID specification, |
| 1153 | − * section 5.10 and 6.2.25. | |
| 1153 | + * section 5.10 and 6.2.25, when NULL state bit is present. | |
| 1154 | + * When it's not, clamp the value to match Microsoft's input | |
| 1155 | + * driver as mentioned in "Required HID usages for digitizers": | |
| 1156 | + * https://msdn.microsoft.com/en-us/library/windows/hardware/dn672278(v=vs.85).asp | |
| 1154 | 1157 | * |
| 1155 | 1158 | * The logical_minimum < logical_maximum check is done so that we |
| 1156 | 1159 | * don't unintentionally discard values sent by devices which |
| 1157 | 1160 | * don't specify logical min and max. |
| 1158 | 1161 | */ |
| 1159 | 1162 | if ((field->flags & HID_MAIN_ITEM_VARIABLE) && |
| 1160 | − (field->logical_minimum < field->logical_maximum) && | |
| 1161 | − (value < field->logical_minimum || | |
| 1162 | − value > field->logical_maximum)) { | |
| 1163 | − dbg_hid("Ignoring out-of-range value %x\n", value); | |
| 1164 | − return; | |
| 1163 | + (field->logical_minimum < field->logical_maximum)) { | |
| 1164 | + if (field->flags & HID_MAIN_ITEM_NULL_STATE && | |
| 1165 | + (value < field->logical_minimum || | |
| 1166 | + value > field->logical_maximum)) { | |
| 1167 | + dbg_hid("Ignoring out-of-range value %x\n", value); | |
| 1168 | + return; | |
| 1169 | + } | |
| 1170 | + value = clamp(value, | |
| 1171 | + field->logical_minimum, | |
| 1172 | + field->logical_maximum); | |
| 1165 | 1173 | } |
| 1166 | 1174 | |
| 1167 | 1175 | /* |
| @@ -692,8 +692,12 @@ static void logi_dj_ll_close(struct hid_device *hid) · 691 unmodified lines | ||
| 692 | 692 | dbg_hid("%s:%s\n", __func__, hid->phys); |
| 693 | 693 | } |
| 694 | 694 | |
| 695 | −static u8 unifying_name_query[] = {0x10, 0xff, 0x83, 0xb5, 0x40, 0x00, 0x00}; | |
| 696 | −static u8 unifying_name_answer[] = {0x11, 0xff, 0x83, 0xb5}; | |
| 695 | +/* | |
| 696 | + * Register 0xB5 is "pairing information". It is solely intended for the | |
| 697 | + * receiver, so do not overwrite the device index. | |
| 698 | + */ | |
| 699 | +static u8 unifying_pairing_query[] = {0x10, 0xff, 0x83, 0xb5}; | |
| 700 | +static u8 unifying_pairing_answer[] = {0x11, 0xff, 0x83, 0xb5}; | |
| 697 | 701 | |
| 698 | 702 | static int logi_dj_ll_raw_request(struct hid_device *hid, |
| 699 | 703 | unsigned char reportnum, __u8 *buf, |
| @@ -712,9 +716,9 @@ static int logi_dj_ll_raw_request(struct hid_device *hid, · 12 unmodified lines | ||
| 712 | 716 | |
| 713 | 717 | /* special case where we should not overwrite |
| 714 | 718 | * the device_index */ |
| 715 | − if (count == 7 && !memcmp(buf, unifying_name_query, | |
| 716 | − sizeof(unifying_name_query))) | |
| 717 | − buf[4] |= djdev->device_index - 1; | |
| 719 | + if (count == 7 && !memcmp(buf, unifying_pairing_query, | |
| 720 | + sizeof(unifying_pairing_query))) | |
| 721 | + buf[4] = (buf[4] & 0xf0) | (djdev->device_index - 1); | |
| 718 | 722 | else |
| 719 | 723 | buf[1] = djdev->device_index; |
| 720 | 724 | return hid_hw_raw_request(djrcv_dev->hdev, reportnum, buf, |
| @@ -911,9 +915,8 @@ static int logi_dj_hidpp_event(struct hid_device *hdev, · 190 unmodified lines | ||
| 911 | 915 | /* special case were the device wants to know its unifying |
| 912 | 916 | * name */ |
| 913 | 917 | if (size == HIDPP_REPORT_LONG_LENGTH && |
| 914 | − !memcmp(data, unifying_name_answer, | |
| 915 | − sizeof(unifying_name_answer)) && | |
| 916 | − ((data[4] & 0xF0) == 0x40)) | |
| 918 | + !memcmp(data, unifying_pairing_answer, | |
| 919 | + sizeof(unifying_pairing_answer))) | |
| 917 | 920 | device_index = (data[4] & 0x0F) + 1; |
| 918 | 921 | else |
| 919 | 922 | return false; |
| @@ -56,15 +56,21 @@ MODULE_PARM_DESC(disable_tap_to_click, · 55 unmodified lines | ||
| 56 | 56 | #define HIDPP_QUIRK_CLASS_M560 BIT(1) |
| 57 | 57 | #define HIDPP_QUIRK_CLASS_K400 BIT(2) |
| 58 | 58 | #define HIDPP_QUIRK_CLASS_G920 BIT(3) |
| 59 | +#define HIDPP_QUIRK_CLASS_K750 BIT(4) | |
| 59 | 60 | |
| 60 | 61 | /* bits 2..20 are reserved for classes */ |
| 61 | −#define HIDPP_QUIRK_CONNECT_EVENTS BIT(21) | |
| 62 | +/* #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21) disabled */ | |
| 62 | 63 | #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22) |
| 63 | 64 | #define HIDPP_QUIRK_NO_HIDINPUT BIT(23) |
| 64 | 65 | #define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24) |
| 66 | +#define HIDPP_QUIRK_UNIFYING BIT(25) | |
| 65 | 67 | |
| 66 | −#define HIDPP_QUIRK_DELAYED_INIT (HIDPP_QUIRK_NO_HIDINPUT | \ | |
| 67 | − HIDPP_QUIRK_CONNECT_EVENTS) | |
| 68 | +#define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT | |
| 69 | + | |
| 70 | +#define HIDPP_CAPABILITY_HIDPP10_BATTERY BIT(0) | |
| 71 | +#define HIDPP_CAPABILITY_HIDPP20_BATTERY BIT(1) | |
| 72 | +#define HIDPP_CAPABILITY_BATTERY_MILEAGE BIT(2) | |
| 73 | +#define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS BIT(3) | |
| 68 | 74 | |
| 69 | 75 | /* |
| 70 | 76 | * There are two hidpp protocols in use, the first version hidpp10 is known |
| @@ -110,6 +116,18 @@ struct hidpp_report { · 39 unmodified lines | ||
| 110 | 116 | }; |
| 111 | 117 | } __packed; |
| 112 | 118 | |
| 119 | +struct hidpp_battery { | |
| 120 | + u8 feature_index; | |
| 121 | + u8 solar_feature_index; | |
| 122 | + struct power_supply_desc desc; | |
| 123 | + struct power_supply *ps; | |
| 124 | + char name[64]; | |
| 125 | + int status; | |
| 126 | + int capacity; | |
| 127 | + int level; | |
| 128 | + bool online; | |
| 129 | +}; | |
| 130 | + | |
| 113 | 131 | struct hidpp_device { |
| 114 | 132 | struct hid_device *hid_dev; |
| 115 | 133 | struct mutex send_mutex; |
| @@ -128,8 +146,10 @@ struct hidpp_device { · 12 unmodified lines | ||
| 128 | 146 | struct input_dev *delayed_input; |
| 129 | 147 | |
| 130 | 148 | unsigned long quirks; |
| 131 | −}; | |
| 149 | + unsigned long capabilities; | |
| 132 | 150 | |
| 151 | + struct hidpp_battery battery; | |
| 152 | +}; | |
| 133 | 153 | |
| 134 | 154 | /* HID++ 1.0 error codes */ |
| 135 | 155 | #define HIDPP_ERROR 0x8f |
| @@ -380,15 +400,220 @@ static void hidpp_prefix_name(char **name, int name_length) · 244 unmodified lines | ||
| 380 | 400 | #define HIDPP_SET_LONG_REGISTER 0x82 |
| 381 | 401 | #define HIDPP_GET_LONG_REGISTER 0x83 |
| 382 | 402 | |
| 403 | +#define HIDPP_REG_GENERAL 0x00 | |
| 404 | + | |
| 405 | +static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev) | |
| 406 | +{ | |
| 407 | + struct hidpp_report response; | |
| 408 | + int ret; | |
| 409 | + u8 params[3] = { 0 }; | |
| 410 | + | |
| 411 | + ret = hidpp_send_rap_command_sync(hidpp_dev, | |
| 412 | + REPORT_ID_HIDPP_SHORT, | |
| 413 | + HIDPP_GET_REGISTER, | |
| 414 | + HIDPP_REG_GENERAL, | |
| 415 | + NULL, 0, &response); | |
| 416 | + if (ret) | |
| 417 | + return ret; | |
| 418 | + | |
| 419 | + memcpy(params, response.rap.params, 3); | |
| 420 | + | |
| 421 | + /* Set the battery bit */ | |
| 422 | + params[0] |= BIT(4); | |
| 423 | + | |
| 424 | + return hidpp_send_rap_command_sync(hidpp_dev, | |
| 425 | + REPORT_ID_HIDPP_SHORT, | |
| 426 | + HIDPP_SET_REGISTER, | |
| 427 | + HIDPP_REG_GENERAL, | |
| 428 | + params, 3, &response); | |
| 429 | +} | |
| 430 | + | |
| 431 | +#define HIDPP_REG_BATTERY_STATUS 0x07 | |
| 432 | + | |
| 433 | +static int hidpp10_battery_status_map_level(u8 param) | |
| 434 | +{ | |
| 435 | + int level; | |
| 436 | + | |
| 437 | + switch (param) { | |
| 438 | + case 1 ... 2: | |
| 439 | + level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | |
| 440 | + break; | |
| 441 | + case 3 ... 4: | |
| 442 | + level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | |
| 443 | + break; | |
| 444 | + case 5 ... 6: | |
| 445 | + level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | |
| 446 | + break; | |
| 447 | + case 7: | |
| 448 | + level = POWER_SUPPLY_CAPACITY_LEVEL_HIGH; | |
| 449 | + break; | |
| 450 | + default: | |
| 451 | + level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; | |
| 452 | + } | |
| 453 | + | |
| 454 | + return level; | |
| 455 | +} | |
| 456 | + | |
| 457 | +static int hidpp10_battery_status_map_status(u8 param) | |
| 458 | +{ | |
| 459 | + int status; | |
| 460 | + | |
| 461 | + switch (param) { | |
| 462 | + case 0x00: | |
| 463 | + /* discharging (in use) */ | |
| 464 | + status = POWER_SUPPLY_STATUS_DISCHARGING; | |
| 465 | + break; | |
| 466 | + case 0x21: /* (standard) charging */ | |
| 467 | + case 0x24: /* fast charging */ | |
| 468 | + case 0x25: /* slow charging */ | |
| 469 | + status = POWER_SUPPLY_STATUS_CHARGING; | |
| 470 | + break; | |
| 471 | + case 0x26: /* topping charge */ | |
| 472 | + case 0x22: /* charge complete */ | |
| 473 | + status = POWER_SUPPLY_STATUS_FULL; | |
| 474 | + break; | |
| 475 | + case 0x20: /* unknown */ | |
| 476 | + status = POWER_SUPPLY_STATUS_UNKNOWN; | |
| 477 | + break; | |
| 478 | + /* | |
| 479 | + * 0x01...0x1F = reserved (not charging) | |
| 480 | + * 0x23 = charging error | |
| 481 | + * 0x27..0xff = reserved | |
| 482 | + */ | |
| 483 | + default: | |
| 484 | + status = POWER_SUPPLY_STATUS_NOT_CHARGING; | |
| 485 | + break; | |
| 486 | + } | |
| 487 | + | |
| 488 | + return status; | |
| 489 | +} | |
| 490 | + | |
| 491 | +static int hidpp10_query_battery_status(struct hidpp_device *hidpp) | |
| 492 | +{ | |
| 493 | + struct hidpp_report response; | |
| 494 | + int ret, status; | |
| 495 | + | |
| 496 | + ret = hidpp_send_rap_command_sync(hidpp, | |
| 497 | + REPORT_ID_HIDPP_SHORT, | |
| 498 | + HIDPP_GET_REGISTER, | |
| 499 | + HIDPP_REG_BATTERY_STATUS, | |
| 500 | + NULL, 0, &response); | |
| 501 | + if (ret) | |
| 502 | + return ret; | |
| 503 | + | |
| 504 | + hidpp->battery.level = | |
| 505 | + hidpp10_battery_status_map_level(response.rap.params[0]); | |
| 506 | + status = hidpp10_battery_status_map_status(response.rap.params[1]); | |
| 507 | + hidpp->battery.status = status; | |
| 508 | + /* the capacity is only available when discharging or full */ | |
| 509 | + hidpp->battery.online = status == POWER_SUPPLY_STATUS_DISCHARGING || | |
| 510 | + status == POWER_SUPPLY_STATUS_FULL; | |
| 511 | + | |
| 512 | + return 0; | |
| 513 | +} | |
| 514 | + | |
| 515 | +#define HIDPP_REG_BATTERY_MILEAGE 0x0D | |
| 516 | + | |
| 517 | +static int hidpp10_battery_mileage_map_status(u8 param) | |
| 518 | +{ | |
| 519 | + int status; | |
| 520 | + | |
| 521 | + switch (param >> 6) { | |
| 522 | + case 0x00: | |
| 523 | + /* discharging (in use) */ | |
| 524 | + status = POWER_SUPPLY_STATUS_DISCHARGING; | |
| 525 | + break; | |
| 526 | + case 0x01: /* charging */ | |
| 527 | + status = POWER_SUPPLY_STATUS_CHARGING; | |
| 528 | + break; | |
| 529 | + case 0x02: /* charge complete */ | |
| 530 | + status = POWER_SUPPLY_STATUS_FULL; | |
| 531 | + break; | |
| 532 | + /* | |
| 533 | + * 0x03 = charging error | |
| 534 | + */ | |
| 535 | + default: | |
| 536 | + status = POWER_SUPPLY_STATUS_NOT_CHARGING; | |
| 537 | + break; | |
| 538 | + } | |
| 539 | + | |
| 540 | + return status; | |
| 541 | +} | |
| 542 | + | |
| 543 | +static int hidpp10_query_battery_mileage(struct hidpp_device *hidpp) | |
| 544 | +{ | |
| 545 | + struct hidpp_report response; | |
| 546 | + int ret, status; | |
| 547 | + | |
| 548 | + ret = hidpp_send_rap_command_sync(hidpp, | |
| 549 | + REPORT_ID_HIDPP_SHORT, | |
| 550 | + HIDPP_GET_REGISTER, | |
| 551 | + HIDPP_REG_BATTERY_MILEAGE, | |
| 552 | + NULL, 0, &response); | |
| 553 | + if (ret) | |
| 554 | + return ret; | |
| 555 | + | |
| 556 | + hidpp->battery.capacity = response.rap.params[0]; | |
| 557 | + status = hidpp10_battery_mileage_map_status(response.rap.params[2]); | |
| 558 | + hidpp->battery.status = status; | |
| 559 | + /* the capacity is only available when discharging or full */ | |
| 560 | + hidpp->battery.online = status == POWER_SUPPLY_STATUS_DISCHARGING || | |
| 561 | + status == POWER_SUPPLY_STATUS_FULL; | |
| 562 | + | |
| 563 | + return 0; | |
| 564 | +} | |
| 565 | + | |
| 566 | +static int hidpp10_battery_event(struct hidpp_device *hidpp, u8 *data, int size) | |
| 567 | +{ | |
| 568 | + struct hidpp_report *report = (struct hidpp_report *)data; | |
| 569 | + int status, capacity, level; | |
| 570 | + bool changed; | |
| 571 | + | |
| 572 | + if (report->report_id != REPORT_ID_HIDPP_SHORT) | |
| 573 | + return 0; | |
| 574 | + | |
| 575 | + switch (report->rap.sub_id) { | |
| 576 | + case HIDPP_REG_BATTERY_STATUS: | |
| 577 | + capacity = hidpp->battery.capacity; | |
| 578 | + level = hidpp10_battery_status_map_level(report->rawbytes[1]); | |
| 579 | + status = hidpp10_battery_status_map_status(report->rawbytes[2]); | |
| 580 | + break; | |
| 581 | + case HIDPP_REG_BATTERY_MILEAGE: | |
| 582 | + capacity = report->rap.params[0]; | |
| 583 | + level = hidpp->battery.level; | |
| 584 | + status = hidpp10_battery_mileage_map_status(report->rawbytes[3]); | |
| 585 | + break; | |
| 586 | + default: | |
| 587 | + return 0; | |
| 588 | + } | |
| 589 | + | |
| 590 | + changed = capacity != hidpp->battery.capacity || | |
| 591 | + level != hidpp->battery.level || | |
| 592 | + status != hidpp->battery.status; | |
| 593 | + | |
| 594 | + /* the capacity is only available when discharging or full */ | |
| 595 | + hidpp->battery.online = status == POWER_SUPPLY_STATUS_DISCHARGING || | |
| 596 | + status == POWER_SUPPLY_STATUS_FULL; | |
| 597 | + | |
| 598 | + if (changed) { | |
| 599 | + hidpp->battery.level = level; | |
| 600 | + hidpp->battery.status = status; | |
| 601 | + if (hidpp->battery.ps) | |
| 602 | + power_supply_changed(hidpp->battery.ps); | |
| 603 | + } | |
| 604 | + | |
| 605 | + return 0; | |
| 606 | +} | |
| 607 | + | |
| 383 | 608 | #define HIDPP_REG_PAIRING_INFORMATION 0xB5 |
| 384 | −#define DEVICE_NAME 0x40 | |
| 609 | +#define HIDPP_EXTENDED_PAIRING 0x30 | |
| 610 | +#define HIDPP_DEVICE_NAME 0x40 | |
| 385 | 611 | |
| 386 | −static char *hidpp_get_unifying_name(struct hidpp_device *hidpp_dev) | |
| 612 | +static char *hidpp_unifying_get_name(struct hidpp_device *hidpp_dev) | |
| 387 | 613 | { |
| 388 | 614 | struct hidpp_report response; |
| 389 | 615 | int ret; |
| 390 | − /* hid-logitech-dj is in charge of setting the right device index */ | |
| 391 | − u8 params[1] = { DEVICE_NAME }; | |
| 616 | + u8 params[1] = { HIDPP_DEVICE_NAME }; | |
| 392 | 617 | char *name; |
| 393 | 618 | int len; |
| 394 | 619 | |
| @@ -417,6 +642,54 @@ static char *hidpp_get_unifying_name(struct hidpp_device *hidpp_dev) · 22 unmodified lines | ||
| 417 | 642 | return name; |
| 418 | 643 | } |
| 419 | 644 | |
| 645 | +static int hidpp_unifying_get_serial(struct hidpp_device *hidpp, u32 *serial) | |
| 646 | +{ | |
| 647 | + struct hidpp_report response; | |
| 648 | + int ret; | |
| 649 | + u8 params[1] = { HIDPP_EXTENDED_PAIRING }; | |
| 650 | + | |
| 651 | + ret = hidpp_send_rap_command_sync(hidpp, | |
| 652 | + REPORT_ID_HIDPP_SHORT, | |
| 653 | + HIDPP_GET_LONG_REGISTER, | |
| 654 | + HIDPP_REG_PAIRING_INFORMATION, | |
| 655 | + params, 1, &response); | |
| 656 | + if (ret) | |
| 657 | + return ret; | |
| 658 | + | |
| 659 | + /* | |
| 660 | + * We don't care about LE or BE, we will output it as a string | |
| 661 | + * with %4phD, so we need to keep the order. | |
| 662 | + */ | |
| 663 | + *serial = *((u32 *)&response.rap.params[1]); | |
| 664 | + return 0; | |
| 665 | +} | |
| 666 | + | |
| 667 | +static int hidpp_unifying_init(struct hidpp_device *hidpp) | |
| 668 | +{ | |
| 669 | + struct hid_device *hdev = hidpp->hid_dev; | |
| 670 | + const char *name; | |
| 671 | + u32 serial; | |
| 672 | + int ret; | |
| 673 | + | |
| 674 | + ret = hidpp_unifying_get_serial(hidpp, &serial); | |
| 675 | + if (ret) | |
| 676 | + return ret; | |
| 677 | + | |
| 678 | + snprintf(hdev->uniq, sizeof(hdev->uniq), "%04x-%4phD", | |
| 679 | + hdev->product, &serial); | |
| 680 | + dbg_hid("HID++ Unifying: Got serial: %s\n", hdev->uniq); | |
| 681 | + | |
| 682 | + name = hidpp_unifying_get_name(hidpp); | |
| 683 | + if (!name) | |
| 684 | + return -EIO; | |
| 685 | + | |
| 686 | + snprintf(hdev->name, sizeof(hdev->name), "%s", name); | |
| 687 | + dbg_hid("HID++ Unifying: Got name: %s\n", name); | |
| 688 | + | |
| 689 | + kfree(name); | |
| 690 | + return 0; | |
| 691 | +} | |
| 692 | + | |
| 420 | 693 | /* -------------------------------------------------------------------------- */ |
| 421 | 694 | /* 0x0000: Root */ |
| 422 | 695 | /* -------------------------------------------------------------------------- */ |
| @@ -441,6 +714,9 @@ static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature, · 18 unmodified lines | ||
| 441 | 714 | if (ret) |
| 442 | 715 | return ret; |
| 443 | 716 | |
| 717 | + if (response.fap.params[0] == 0) | |
| 718 | + return -ENOENT; | |
| 719 | + | |
| 444 | 720 | *feature_index = response.fap.params[0]; |
| 445 | 721 | *feature_type = response.fap.params[1]; |
| 446 | 722 | |
| @@ -606,6 +882,355 @@ static char *hidpp_get_device_name(struct hidpp_device *hidpp) · 159 unmodified lines | ||
| 606 | 882 | return name; |
| 607 | 883 | } |
| 608 | 884 | |
| 885 | +/* -------------------------------------------------------------------------- */ | |
| 886 | +/* 0x1000: Battery level status */ | |
| 887 | +/* -------------------------------------------------------------------------- */ | |
| 888 | + | |
| 889 | +#define HIDPP_PAGE_BATTERY_LEVEL_STATUS 0x1000 | |
| 890 | + | |
| 891 | +#define CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_LEVEL_STATUS 0x00 | |
| 892 | +#define CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_CAPABILITY 0x10 | |
| 893 | + | |
| 894 | +#define EVENT_BATTERY_LEVEL_STATUS_BROADCAST 0x00 | |
| 895 | + | |
| 896 | +#define FLAG_BATTERY_LEVEL_DISABLE_OSD BIT(0) | |
| 897 | +#define FLAG_BATTERY_LEVEL_MILEAGE BIT(1) | |
| 898 | +#define FLAG_BATTERY_LEVEL_RECHARGEABLE BIT(2) | |
| 899 | + | |
| 900 | +static int hidpp_map_battery_level(int capacity) | |
| 901 | +{ | |
| 902 | + if (capacity < 11) | |
| 903 | + return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | |
| 904 | + else if (capacity < 31) | |
| 905 | + return POWER_SUPPLY_CAPACITY_LEVEL_LOW; | |
| 906 | + else if (capacity < 81) | |
| 907 | + return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | |
| 908 | + return POWER_SUPPLY_CAPACITY_LEVEL_FULL; | |
| 909 | +} | |
| 910 | + | |
| 911 | +static int hidpp20_batterylevel_map_status_capacity(u8 data[3], int *capacity, | |
| 912 | + int *next_capacity, | |
| 913 | + int *level) | |
| 914 | +{ | |
| 915 | + int status; | |
| 916 | + | |
| 917 | + *capacity = data[0]; | |
| 918 | + *next_capacity = data[1]; | |
| 919 | + *level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; | |
| 920 | + | |
| 921 | + /* When discharging, we can rely on the device reported capacity. | |
| 922 | + * For all other states the device reports 0 (unknown). | |
| 923 | + */ | |
| 924 | + switch (data[2]) { | |
| 925 | + case 0: /* discharging (in use) */ | |
| 926 | + status = POWER_SUPPLY_STATUS_DISCHARGING; | |
| 927 | + *level = hidpp_map_battery_level(*capacity); | |
| 928 | + break; | |
| 929 | + case 1: /* recharging */ | |
| 930 | + status = POWER_SUPPLY_STATUS_CHARGING; | |
| 931 | + break; | |
| 932 | + case 2: /* charge in final stage */ | |
| 933 | + status = POWER_SUPPLY_STATUS_CHARGING; | |
| 934 | + break; | |
| 935 | + case 3: /* charge complete */ | |
| 936 | + status = POWER_SUPPLY_STATUS_FULL; | |
| 937 | + *level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | |
| 938 | + *capacity = 100; | |
| 939 | + break; | |
| 940 | + case 4: /* recharging below optimal speed */ | |
| 941 | + status = POWER_SUPPLY_STATUS_CHARGING; | |
| 942 | + break; | |
| 943 | + /* 5 = invalid battery type | |
| 944 | + 6 = thermal error | |
| 945 | + 7 = other charging error */ | |
| 946 | + default: | |
| 947 | + status = POWER_SUPPLY_STATUS_NOT_CHARGING; | |
| 948 | + break; | |
| 949 | + } | |
| 950 | + | |
| 951 | + return status; | |
| 952 | +} | |
| 953 | + | |
| 954 | +static int hidpp20_batterylevel_get_battery_capacity(struct hidpp_device *hidpp, | |
| 955 | + u8 feature_index, | |
| 956 | + int *status, | |
| 957 | + int *capacity, | |
| 958 | + int *next_capacity, | |
| 959 | + int *level) | |
| 960 | +{ | |
| 961 | + struct hidpp_report response; | |
| 962 | + int ret; | |
| 963 | + u8 *params = (u8 *)response.fap.params; | |
| 964 | + | |
| 965 | + ret = hidpp_send_fap_command_sync(hidpp, feature_index, | |
| 966 | + CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_LEVEL_STATUS, | |
| 967 | + NULL, 0, &response); | |
| 968 | + if (ret > 0) { | |
| 969 | + hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", | |
| 970 | + __func__, ret); | |
| 971 | + return -EPROTO; | |
| 972 | + } | |
| 973 | + if (ret) | |
| 974 | + return ret; | |
| 975 | + | |
| 976 | + *status = hidpp20_batterylevel_map_status_capacity(params, capacity, | |
| 977 | + next_capacity, | |
| 978 | + level); | |
| 979 | + | |
| 980 | + return 0; | |
| 981 | +} | |
| 982 | + | |
| 983 | +static int hidpp20_batterylevel_get_battery_info(struct hidpp_device *hidpp, | |
| 984 | + u8 feature_index) | |
| 985 | +{ | |
| 986 | + struct hidpp_report response; | |
| 987 | + int ret; | |
| 988 | + u8 *params = (u8 *)response.fap.params; | |
| 989 | + unsigned int level_count, flags; | |
| 990 | + | |
| 991 | + ret = hidpp_send_fap_command_sync(hidpp, feature_index, | |
| 992 | + CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_CAPABILITY, | |
| 993 | + NULL, 0, &response); | |
| 994 | + if (ret > 0) { | |
| 995 | + hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", | |
| 996 | + __func__, ret); | |
| 997 | + return -EPROTO; | |
| 998 | + } | |
| 999 | + if (ret) | |
| 1000 | + return ret; | |
| 1001 | + | |
| 1002 | + level_count = params[0]; | |
| 1003 | + flags = params[1]; | |
| 1004 | + | |
| 1005 | + if (level_count < 10 || !(flags & FLAG_BATTERY_LEVEL_MILEAGE)) | |
| 1006 | + hidpp->capabilities |= HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS; | |
| 1007 | + else | |
| 1008 | + hidpp->capabilities |= HIDPP_CAPABILITY_BATTERY_MILEAGE; | |
| 1009 | + | |
| 1010 | + return 0; | |
| 1011 | +} | |
| 1012 | + | |
| 1013 | +static int hidpp20_query_battery_info(struct hidpp_device *hidpp) | |
| 1014 | +{ | |
| 1015 | + u8 feature_type; | |
| 1016 | + int ret; | |
| 1017 | + int status, capacity, next_capacity, level; | |
| 1018 | + | |
| 1019 | + if (hidpp->battery.feature_index == 0xff) { | |
| 1020 | + ret = hidpp_root_get_feature(hidpp, | |
| 1021 | + HIDPP_PAGE_BATTERY_LEVEL_STATUS, | |
| 1022 | + &hidpp->battery.feature_index, | |
| 1023 | + &feature_type); | |
| 1024 | + if (ret) | |
| 1025 | + return ret; | |
| 1026 | + } | |
| 1027 | + | |
| 1028 | + ret = hidpp20_batterylevel_get_battery_capacity(hidpp, | |
| 1029 | + hidpp->battery.feature_index, | |
| 1030 | + &status, &capacity, | |
| 1031 | + &next_capacity, &level); | |
| 1032 | + if (ret) | |
| 1033 | + return ret; | |
| 1034 | + | |
| 1035 | + ret = hidpp20_batterylevel_get_battery_info(hidpp, | |
| 1036 | + hidpp->battery.feature_index); | |
| 1037 | + if (ret) | |
| 1038 | + return ret; | |
| 1039 | + | |
| 1040 | + hidpp->battery.status = status; | |
| 1041 | + hidpp->battery.capacity = capacity; | |
| 1042 | + hidpp->battery.level = level; | |
| 1043 | + /* the capacity is only available when discharging or full */ | |
| 1044 | + hidpp->battery.online = status == POWER_SUPPLY_STATUS_DISCHARGING || | |
| 1045 | + status == POWER_SUPPLY_STATUS_FULL; | |
| 1046 | + | |
| 1047 | + return 0; | |
| 1048 | +} | |
| 1049 | + | |
| 1050 | +static int hidpp20_battery_event(struct hidpp_device *hidpp, | |
| 1051 | + u8 *data, int size) | |
| 1052 | +{ | |
| 1053 | + struct hidpp_report *report = (struct hidpp_report *)data; | |
| 1054 | + int status, capacity, next_capacity, level; | |
| 1055 | + bool changed; | |
| 1056 | + | |
| 1057 | + if (report->fap.feature_index != hidpp->battery.feature_index || | |
| 1058 | + report->fap.funcindex_clientid != EVENT_BATTERY_LEVEL_STATUS_BROADCAST) | |
| 1059 | + return 0; | |
| 1060 | + | |
| 1061 | + status = hidpp20_batterylevel_map_status_capacity(report->fap.params, | |
| 1062 | + &capacity, | |
| 1063 | + &next_capacity, | |
| 1064 | + &level); | |
| 1065 | + | |
| 1066 | + /* the capacity is only available when discharging or full */ | |
| 1067 | + hidpp->battery.online = status == POWER_SUPPLY_STATUS_DISCHARGING || | |
| 1068 | + status == POWER_SUPPLY_STATUS_FULL; | |
| 1069 | + | |
| 1070 | + changed = capacity != hidpp->battery.capacity || | |
| 1071 | + level != hidpp->battery.level || | |
| 1072 | + status != hidpp->battery.status; | |
| 1073 | + | |
| 1074 | + if (changed) { | |
| 1075 | + hidpp->battery.level = level; | |
| 1076 | + hidpp->battery.capacity = capacity; | |
| 1077 | + hidpp->battery.status = status; | |
| 1078 | + if (hidpp->battery.ps) | |
| 1079 | + power_supply_changed(hidpp->battery.ps); | |
| 1080 | + } | |
| 1081 | + | |
| 1082 | + return 0; | |
| 1083 | +} | |
| 1084 | + | |
| 1085 | +static enum power_supply_property hidpp_battery_props[] = { | |
| 1086 | + POWER_SUPPLY_PROP_ONLINE, | |
| 1087 | + POWER_SUPPLY_PROP_STATUS, | |
| 1088 | + POWER_SUPPLY_PROP_SCOPE, | |
| 1089 | + POWER_SUPPLY_PROP_MODEL_NAME, | |
| 1090 | + POWER_SUPPLY_PROP_MANUFACTURER, | |
| 1091 | + POWER_SUPPLY_PROP_SERIAL_NUMBER, | |
| 1092 | + 0, /* placeholder for POWER_SUPPLY_PROP_CAPACITY, */ | |
| 1093 | + 0, /* placeholder for POWER_SUPPLY_PROP_CAPACITY_LEVEL, */ | |
| 1094 | +}; | |
| 1095 | + | |
| 1096 | +static int hidpp_battery_get_property(struct power_supply *psy, | |
| 1097 | + enum power_supply_property psp, | |
| 1098 | + union power_supply_propval *val) | |
| 1099 | +{ | |
| 1100 | + struct hidpp_device *hidpp = power_supply_get_drvdata(psy); | |
| 1101 | + int ret = 0; | |
| 1102 | + | |
| 1103 | + switch(psp) { | |
| 1104 | + case POWER_SUPPLY_PROP_STATUS: | |
| 1105 | + val->intval = hidpp->battery.status; | |
| 1106 | + break; | |
| 1107 | + case POWER_SUPPLY_PROP_CAPACITY: | |
| 1108 | + val->intval = hidpp->battery.capacity; | |
| 1109 | + break; | |
| 1110 | + case POWER_SUPPLY_PROP_CAPACITY_LEVEL: | |
| 1111 | + val->intval = hidpp->battery.level; | |
| 1112 | + break; | |
| 1113 | + case POWER_SUPPLY_PROP_SCOPE: | |
| 1114 | + val->intval = POWER_SUPPLY_SCOPE_DEVICE; | |
| 1115 | + break; | |
| 1116 | + case POWER_SUPPLY_PROP_ONLINE: | |
| 1117 | + val->intval = hidpp->battery.online; | |
| 1118 | + break; | |
| 1119 | + case POWER_SUPPLY_PROP_MODEL_NAME: | |
| 1120 | + if (!strncmp(hidpp->name, "Logitech ", 9)) | |
| 1121 | + val->strval = hidpp->name + 9; | |
| 1122 | + else | |
| 1123 | + val->strval = hidpp->name; | |
| 1124 | + break; | |
| 1125 | + case POWER_SUPPLY_PROP_MANUFACTURER: | |
| 1126 | + val->strval = "Logitech"; | |
| 1127 | + break; | |
| 1128 | + case POWER_SUPPLY_PROP_SERIAL_NUMBER: | |
| 1129 | + val->strval = hidpp->hid_dev->uniq; | |
| 1130 | + break; | |
| 1131 | + default: | |
| 1132 | + ret = -EINVAL; | |
| 1133 | + break; | |
| 1134 | + } | |
| 1135 | + | |
| 1136 | + return ret; | |
| 1137 | +} | |
| 1138 | + | |
| 1139 | +/* -------------------------------------------------------------------------- */ | |
| 1140 | +/* 0x4301: Solar Keyboard */ | |
| 1141 | +/* -------------------------------------------------------------------------- */ | |
| 1142 | + | |
| 1143 | +#define HIDPP_PAGE_SOLAR_KEYBOARD 0x4301 | |
| 1144 | + | |
| 1145 | +#define CMD_SOLAR_SET_LIGHT_MEASURE 0x00 | |
| 1146 | + | |
| 1147 | +#define EVENT_SOLAR_BATTERY_BROADCAST 0x00 | |
| 1148 | +#define EVENT_SOLAR_BATTERY_LIGHT_MEASURE 0x10 | |
| 1149 | +#define EVENT_SOLAR_CHECK_LIGHT_BUTTON 0x20 | |
| 1150 | + | |
| 1151 | +static int hidpp_solar_request_battery_event(struct hidpp_device *hidpp) | |
| 1152 | +{ | |
| 1153 | + struct hidpp_report response; | |
| 1154 | + u8 params[2] = { 1, 1 }; | |
| 1155 | + u8 feature_type; | |
| 1156 | + int ret; | |
| 1157 | + | |
| 1158 | + if (hidpp->battery.feature_index == 0xff) { | |
| 1159 | + ret = hidpp_root_get_feature(hidpp, | |
| 1160 | + HIDPP_PAGE_SOLAR_KEYBOARD, | |
| 1161 | + &hidpp->battery.solar_feature_index, | |
| 1162 | + &feature_type); | |
| 1163 | + if (ret) | |
| 1164 | + return ret; | |
| 1165 | + } | |
| 1166 | + | |
| 1167 | + ret = hidpp_send_fap_command_sync(hidpp, | |
| 1168 | + hidpp->battery.solar_feature_index, | |
| 1169 | + CMD_SOLAR_SET_LIGHT_MEASURE, | |
| 1170 | + params, 2, &response); | |
| 1171 | + if (ret > 0) { | |
| 1172 | + hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", | |
| 1173 | + __func__, ret); | |
| 1174 | + return -EPROTO; | |
| 1175 | + } | |
| 1176 | + if (ret) | |
| 1177 | + return ret; | |
| 1178 | + | |
| 1179 | + hidpp->capabilities |= HIDPP_CAPABILITY_BATTERY_MILEAGE; | |
| 1180 | + | |
| 1181 | + return 0; | |
| 1182 | +} | |
| 1183 | + | |
| 1184 | +static int hidpp_solar_battery_event(struct hidpp_device *hidpp, | |
| 1185 | + u8 *data, int size) | |
| 1186 | +{ | |
| 1187 | + struct hidpp_report *report = (struct hidpp_report *)data; | |
| 1188 | + int capacity, lux, status; | |
| 1189 | + u8 function; | |
| 1190 | + | |
| 1191 | + function = report->fap.funcindex_clientid; | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + if (report->fap.feature_index != hidpp->battery.solar_feature_index || | |
| 1195 | + !(function == EVENT_SOLAR_BATTERY_BROADCAST || | |
| 1196 | + function == EVENT_SOLAR_BATTERY_LIGHT_MEASURE || | |
| 1197 | + function == EVENT_SOLAR_CHECK_LIGHT_BUTTON)) | |
| 1198 | + return 0; | |
| 1199 | + | |
| 1200 | + capacity = report->fap.params[0]; | |
| 1201 | + | |
| 1202 | + switch (function) { | |
| 1203 | + case EVENT_SOLAR_BATTERY_LIGHT_MEASURE: | |
| 1204 | + lux = (report->fap.params[1] << 8) | report->fap.params[2]; | |
| 1205 | + if (lux > 200) | |
| 1206 | + status = POWER_SUPPLY_STATUS_CHARGING; | |
| 1207 | + else | |
| 1208 | + status = POWER_SUPPLY_STATUS_DISCHARGING; | |
| 1209 | + break; | |
| 1210 | + case EVENT_SOLAR_CHECK_LIGHT_BUTTON: | |
| 1211 | + default: | |
| 1212 | + if (capacity < hidpp->battery.capacity) | |
| 1213 | + status = POWER_SUPPLY_STATUS_DISCHARGING; | |
| 1214 | + else | |
| 1215 | + status = POWER_SUPPLY_STATUS_CHARGING; | |
| 1216 | + | |
| 1217 | + } | |
| 1218 | + | |
| 1219 | + if (capacity == 100) | |
| 1220 | + status = POWER_SUPPLY_STATUS_FULL; | |
| 1221 | + | |
| 1222 | + hidpp->battery.online = true; | |
| 1223 | + if (capacity != hidpp->battery.capacity || | |
| 1224 | + status != hidpp->battery.status) { | |
| 1225 | + hidpp->battery.capacity = capacity; | |
| 1226 | + hidpp->battery.status = status; | |
| 1227 | + if (hidpp->battery.ps) | |
| 1228 | + power_supply_changed(hidpp->battery.ps); | |
| 1229 | + } | |
| 1230 | + | |
| 1231 | + return 0; | |
| 1232 | +} | |
| 1233 | + | |
| 609 | 1234 | /* -------------------------------------------------------------------------- */ |
| 610 | 1235 | /* 0x6010: Touchpad FW items */ |
| 611 | 1236 | /* -------------------------------------------------------------------------- */ |
| @@ -1599,9 +2224,6 @@ static int wtp_connect(struct hid_device *hdev, bool connected) · 987 unmodified lines | ||
| 1599 | 2224 | struct wtp_data *wd = hidpp->private_data; |
| 1600 | 2225 | int ret; |
| 1601 | 2226 | |
| 1602 | − if (!connected) | |
| 1603 | − return 0; | |
| 1604 | − | |
| 1605 | 2227 | if (!wd->x_size) { |
| 1606 | 2228 | ret = wtp_get_config(hidpp); |
| 1607 | 2229 | if (ret) { |
| @@ -1669,9 +2291,6 @@ static int m560_send_config_command(struct hid_device *hdev, bool connected) · 61 unmodified lines | ||
| 1669 | 2291 | |
| 1670 | 2292 | hidpp_dev = hid_get_drvdata(hdev); |
| 1671 | 2293 | |
| 1672 | − if (!connected) | |
| 1673 | − return -ENODEV; | |
| 1674 | − | |
| 1675 | 2294 | return hidpp_send_rap_command_sync( |
| 1676 | 2295 | hidpp_dev, |
| 1677 | 2296 | REPORT_ID_HIDPP_SHORT, |
| @@ -1875,9 +2494,6 @@ static int k400_connect(struct hid_device *hdev, bool connected) · 197 unmodified lines | ||
| 1875 | 2494 | { |
| 1876 | 2495 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); |
| 1877 | 2496 | |
| 1878 | − if (!connected) | |
| 1879 | − return 0; | |
| 1880 | − | |
| 1881 | 2497 | if (!disable_tap_to_click) |
| 1882 | 2498 | return 0; |
| 1883 | 2499 | |
| @@ -1974,6 +2590,7 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, · 90 unmodified lines | ||
| 1974 | 2590 | struct hidpp_report *question = hidpp->send_receive_buf; |
| 1975 | 2591 | struct hidpp_report *answer = hidpp->send_receive_buf; |
| 1976 | 2592 | struct hidpp_report *report = (struct hidpp_report *)data; |
| 2593 | + int ret; | |
| 1977 | 2594 | |
| 1978 | 2595 | /* |
| 1979 | 2596 | * If the mutex is locked then we have a pending answer from a |
| @@ -2002,12 +2619,26 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, · 22 unmodified lines | ||
| 2002 | 2619 | if (unlikely(hidpp_report_is_connect_event(report))) { |
| 2003 | 2620 | atomic_set(&hidpp->connected, |
| 2004 | 2621 | !(report->rap.params[0] & (1 << 6))); |
| 2005 | − if ((hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) && | |
| 2006 | − (schedule_work(&hidpp->work) == 0)) | |
| 2622 | + if (schedule_work(&hidpp->work) == 0) | |
| 2007 | 2623 | dbg_hid("%s: connect event already queued\n", __func__); |
| 2008 | 2624 | return 1; |
| 2009 | 2625 | } |
| 2010 | 2626 | |
| 2627 | + if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_BATTERY) { | |
| 2628 | + ret = hidpp20_battery_event(hidpp, data, size); | |
| 2629 | + if (ret != 0) | |
| 2630 | + return ret; | |
| 2631 | + ret = hidpp_solar_battery_event(hidpp, data, size); | |
| 2632 | + if (ret != 0) | |
| 2633 | + return ret; | |
| 2634 | + } | |
| 2635 | + | |
| 2636 | + if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) { | |
| 2637 | + ret = hidpp10_battery_event(hidpp, data, size); | |
| 2638 | + if (ret != 0) | |
| 2639 | + return ret; | |
| 2640 | + } | |
| 2641 | + | |
| 2011 | 2642 | return 0; |
| 2012 | 2643 | } |
| 2013 | 2644 | |
| @@ -2058,20 +2689,90 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report, · 44 unmodified lines | ||
| 2058 | 2689 | return 0; |
| 2059 | 2690 | } |
| 2060 | 2691 | |
| 2061 | −static void hidpp_overwrite_name(struct hid_device *hdev, bool use_unifying) | |
| 2692 | +static int hidpp_initialize_battery(struct hidpp_device *hidpp) | |
| 2693 | +{ | |
| 2694 | + static atomic_t battery_no = ATOMIC_INIT(0); | |
| 2695 | + struct power_supply_config cfg = { .drv_data = hidpp }; | |
| 2696 | + struct power_supply_desc *desc = &hidpp->battery.desc; | |
| 2697 | + enum power_supply_property *battery_props; | |
| 2698 | + struct hidpp_battery *battery; | |
| 2699 | + unsigned int num_battery_props; | |
| 2700 | + unsigned long n; | |
| 2701 | + int ret; | |
| 2702 | + | |
| 2703 | + if (hidpp->battery.ps) | |
| 2704 | + return 0; | |
| 2705 | + | |
| 2706 | + hidpp->battery.feature_index = 0xff; | |
| 2707 | + hidpp->battery.solar_feature_index = 0xff; | |
| 2708 | + | |
| 2709 | + if (hidpp->protocol_major >= 2) { | |
| 2710 | + if (hidpp->quirks & HIDPP_QUIRK_CLASS_K750) | |
| 2711 | + ret = hidpp_solar_request_battery_event(hidpp); | |
| 2712 | + else | |
| 2713 | + ret = hidpp20_query_battery_info(hidpp); | |
| 2714 | + | |
| 2715 | + if (ret) | |
| 2716 | + return ret; | |
| 2717 | + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_BATTERY; | |
| 2718 | + } else { | |
| 2719 | + ret = hidpp10_query_battery_status(hidpp); | |
| 2720 | + if (ret) { | |
| 2721 | + ret = hidpp10_query_battery_mileage(hidpp); | |
| 2722 | + if (ret) | |
| 2723 | + return -ENOENT; | |
| 2724 | + hidpp->capabilities |= HIDPP_CAPABILITY_BATTERY_MILEAGE; | |
| 2725 | + } else { | |
| 2726 | + hidpp->capabilities |= HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS; | |
| 2727 | + } | |
| 2728 | + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP10_BATTERY; | |
| 2729 | + } | |
| 2730 | + | |
| 2731 | + battery_props = devm_kmemdup(&hidpp->hid_dev->dev, | |
| 2732 | + hidpp_battery_props, | |
| 2733 | + sizeof(hidpp_battery_props), | |
| 2734 | + GFP_KERNEL); | |
| 2735 | + num_battery_props = ARRAY_SIZE(hidpp_battery_props) - 2; | |
| 2736 | + | |
| 2737 | + if (hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_MILEAGE) | |
| 2738 | + battery_props[num_battery_props++] = | |
| 2739 | + POWER_SUPPLY_PROP_CAPACITY; | |
| 2740 | + | |
| 2741 | + if (hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS) | |
| 2742 | + battery_props[num_battery_props++] = | |
| 2743 | + POWER_SUPPLY_PROP_CAPACITY_LEVEL; | |
| 2744 | + | |
| 2745 | + battery = &hidpp->battery; | |
| 2746 | + | |
| 2747 | + n = atomic_inc_return(&battery_no) - 1; | |
| 2748 | + desc->properties = battery_props; | |
| 2749 | + desc->num_properties = num_battery_props; | |
| 2750 | + desc->get_property = hidpp_battery_get_property; | |
| 2751 | + sprintf(battery->name, "hidpp_battery_%ld", n); | |
| 2752 | + desc->name = battery->name; | |
| 2753 | + desc->type = POWER_SUPPLY_TYPE_BATTERY; | |
| 2754 | + desc->use_for_apm = 0; | |
| 2755 | + | |
| 2756 | + battery->ps = devm_power_supply_register(&hidpp->hid_dev->dev, | |
| 2757 | + &battery->desc, | |
| 2758 | + &cfg); | |
| 2759 | + if (IS_ERR(battery->ps)) | |
| 2760 | + return PTR_ERR(battery->ps); | |
| 2761 | + | |
| 2762 | + power_supply_powers(battery->ps, &hidpp->hid_dev->dev); | |
| 2763 | + | |
| 2764 | + return ret; | |
| 2765 | +} | |
| 2766 | + | |
| 2767 | +static void hidpp_overwrite_name(struct hid_device *hdev) | |
| 2062 | 2768 | { |
| 2063 | 2769 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); |
| 2064 | 2770 | char *name; |
| 2065 | 2771 | |
| 2066 | − if (use_unifying) | |
| 2067 | − /* | |
| 2068 | − * the device is connected through an Unifying receiver, and | |
| 2069 | − * might not be already connected. | |
| 2070 | − * Ask the receiver for its name. | |
| 2071 | − */ | |
| 2072 | − name = hidpp_get_unifying_name(hidpp); | |
| 2073 | − else | |
| 2074 | − name = hidpp_get_device_name(hidpp); | |
| 2772 | + if (hidpp->protocol_major < 2) | |
| 2773 | + return; | |
| 2774 | + | |
| 2775 | + name = hidpp_get_device_name(hidpp); | |
| 2075 | 2776 | |
| 2076 | 2777 | if (!name) { |
| 2077 | 2778 | hid_err(hdev, "unable to retrieve the name of the device"); |
| @@ -2129,6 +2830,16 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) · 51 unmodified lines | ||
| 2129 | 2830 | struct input_dev *input; |
| 2130 | 2831 | char *name, *devm_name; |
| 2131 | 2832 | |
| 2833 | + if (!connected) { | |
| 2834 | + if (hidpp->battery.ps) { | |
| 2835 | + hidpp->battery.online = false; | |
| 2836 | + hidpp->battery.status = POWER_SUPPLY_STATUS_UNKNOWN; | |
| 2837 | + hidpp->battery.level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; | |
| 2838 | + power_supply_changed(hidpp->battery.ps); | |
| 2839 | + } | |
| 2840 | + return; | |
| 2841 | + } | |
| 2842 | + | |
| 2132 | 2843 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) { |
| 2133 | 2844 | ret = wtp_connect(hdev, connected); |
| 2134 | 2845 | if (ret) |
| @@ -2143,9 +2854,6 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) · 8 unmodified lines | ||
| 2143 | 2854 | return; |
| 2144 | 2855 | } |
| 2145 | 2856 | |
| 2146 | − if (!connected || hidpp->delayed_input) | |
| 2147 | − return; | |
| 2148 | − | |
| 2149 | 2857 | /* the device is already connected, we can ask for its name and |
| 2150 | 2858 | * protocol */ |
| 2151 | 2859 | if (!hidpp->protocol_major) { |
| @@ -2158,11 +2866,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) · 6 unmodified lines | ||
| 2158 | 2866 | hidpp->protocol_major, hidpp->protocol_minor); |
| 2159 | 2867 | } |
| 2160 | 2868 | |
| 2161 | − if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)) | |
| 2162 | − /* if HID created the input nodes for us, we can stop now */ | |
| 2163 | − return; | |
| 2164 | − | |
| 2165 | − if (!hidpp->name || hidpp->name == hdev->name) { | |
| 2869 | + if (hidpp->name == hdev->name && hidpp->protocol_major >= 2) { | |
| 2166 | 2870 | name = hidpp_get_device_name(hidpp); |
| 2167 | 2871 | if (!name) { |
| 2168 | 2872 | hid_err(hdev, |
| @@ -2178,6 +2882,25 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) · 9 unmodified lines | ||
| 2178 | 2882 | hidpp->name = devm_name; |
| 2179 | 2883 | } |
| 2180 | 2884 | |
| 2885 | + hidpp_initialize_battery(hidpp); | |
| 2886 | + | |
| 2887 | + /* forward current battery state */ | |
| 2888 | + if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) { | |
| 2889 | + hidpp10_enable_battery_reporting(hidpp); | |
| 2890 | + if (hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_MILEAGE) | |
| 2891 | + hidpp10_query_battery_mileage(hidpp); | |
| 2892 | + else | |
| 2893 | + hidpp10_query_battery_status(hidpp); | |
| 2894 | + } else if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_BATTERY) { | |
| 2895 | + hidpp20_query_battery_info(hidpp); | |
| 2896 | + } | |
| 2897 | + if (hidpp->battery.ps) | |
| 2898 | + power_supply_changed(hidpp->battery.ps); | |
| 2899 | + | |
| 2900 | + if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input) | |
| 2901 | + /* if the input nodes are already created, we can stop now */ | |
| 2902 | + return; | |
| 2903 | + | |
| 2181 | 2904 | input = hidpp_allocate_input(hdev); |
| 2182 | 2905 | if (!input) { |
| 2183 | 2906 | hid_err(hdev, "cannot allocate new input device: %d\n", ret); |
| @@ -2193,6 +2916,17 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) · 9 unmodified lines | ||
| 2193 | 2916 | hidpp->delayed_input = input; |
| 2194 | 2917 | } |
| 2195 | 2918 | |
| 2919 | +static DEVICE_ATTR(builtin_power_supply, 0000, NULL, NULL); | |
| 2920 | + | |
| 2921 | +static struct attribute *sysfs_attrs[] = { | |
| 2922 | + &dev_attr_builtin_power_supply.attr, | |
| 2923 | + NULL | |
| 2924 | +}; | |
| 2925 | + | |
| 2926 | +static struct attribute_group ps_attribute_group = { | |
| 2927 | + .attrs = sysfs_attrs | |
| 2928 | +}; | |
| 2929 | + | |
| 2196 | 2930 | static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 2197 | 2931 | { |
| 2198 | 2932 | struct hidpp_device *hidpp; |
| @@ -2211,9 +2945,11 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) · 12 unmodified lines | ||
| 2211 | 2945 | |
| 2212 | 2946 | hidpp->quirks = id->driver_data; |
| 2213 | 2947 | |
| 2948 | + if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE) | |
| 2949 | + hidpp->quirks |= HIDPP_QUIRK_UNIFYING; | |
| 2950 | + | |
| 2214 | 2951 | if (disable_raw_mode) { |
| 2215 | 2952 | hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP; |
| 2216 | − hidpp->quirks &= ~HIDPP_QUIRK_CONNECT_EVENTS; | |
| 2217 | 2953 | hidpp->quirks &= ~HIDPP_QUIRK_NO_HIDINPUT; |
| 2218 | 2954 | } |
| 2219 | 2955 | |
| @@ -2235,6 +2971,12 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) · 15 unmodified lines | ||
| 2235 | 2971 | mutex_init(&hidpp->send_mutex); |
| 2236 | 2972 | init_waitqueue_head(&hidpp->wait); |
| 2237 | 2973 | |
| 2974 | + /* indicates we are handling the battery properties in the kernel */ | |
| 2975 | + ret = sysfs_create_group(&hdev->dev.kobj, &ps_attribute_group); | |
| 2976 | + if (ret) | |
| 2977 | + hid_warn(hdev, "Cannot allocate sysfs group for %s\n", | |
| 2978 | + hdev->name); | |
| 2979 | + | |
| 2238 | 2980 | ret = hid_parse(hdev); |
| 2239 | 2981 | if (ret) { |
| 2240 | 2982 | hid_err(hdev, "%s:parse failed\n", __func__); |
| @@ -2263,8 +3005,12 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) · 22 unmodified lines | ||
| 2263 | 3005 | /* Allow incoming packets */ |
| 2264 | 3006 | hid_device_io_start(hdev); |
| 2265 | 3007 | |
| 3008 | + if (hidpp->quirks & HIDPP_QUIRK_UNIFYING) | |
| 3009 | + hidpp_unifying_init(hidpp); | |
| 3010 | + | |
| 2266 | 3011 | connected = hidpp_is_connected(hidpp); |
| 2267 | − if (id->group != HID_GROUP_LOGITECH_DJ_DEVICE) { | |
| 3012 | + atomic_set(&hidpp->connected, connected); | |
| 3013 | + if (!(hidpp->quirks & HIDPP_QUIRK_UNIFYING)) { | |
| 2268 | 3014 | if (!connected) { |
| 2269 | 3015 | ret = -ENODEV; |
| 2270 | 3016 | hid_err(hdev, "Device not connected"); |
| @@ -2273,10 +3019,9 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) · 2 unmodified lines | ||
| 2273 | 3019 | |
| 2274 | 3020 | hid_info(hdev, "HID++ %u.%u device connected.\n", |
| 2275 | 3021 | hidpp->protocol_major, hidpp->protocol_minor); |
| 2276 | − } | |
| 2277 | 3022 | |
| 2278 | − hidpp_overwrite_name(hdev, id->group == HID_GROUP_LOGITECH_DJ_DEVICE); | |
| 2279 | − atomic_set(&hidpp->connected, connected); | |
| 3023 | + hidpp_overwrite_name(hdev); | |
| 3024 | + } | |
| 2280 | 3025 | |
| 2281 | 3026 | if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) { |
| 2282 | 3027 | ret = wtp_get_config(hidpp); |
| @@ -2299,12 +3044,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) · 16 unmodified lines | ||
| 2299 | 3044 | } |
| 2300 | 3045 | } |
| 2301 | 3046 | |
| 2302 | − if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) { | |
| 2303 | − /* Allow incoming packets */ | |
| 2304 | − hid_device_io_start(hdev); | |
| 3047 | + /* Allow incoming packets */ | |
| 3048 | + hid_device_io_start(hdev); | |
| 2305 | 3049 | |
| 2306 | − hidpp_connect_event(hidpp); | |
| 2307 | − } | |
| 3050 | + hidpp_connect_event(hidpp); | |
| 2308 | 3051 | |
| 2309 | 3052 | return ret; |
| 2310 | 3053 | |
| @@ -2316,6 +3059,7 @@ hid_hw_open_failed: · 5 unmodified lines | ||
| 2316 | 3059 | } |
| 2317 | 3060 | hid_hw_start_fail: |
| 2318 | 3061 | hid_parse_fail: |
| 3062 | + sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group); | |
| 2319 | 3063 | cancel_work_sync(&hidpp->work); |
| 2320 | 3064 | mutex_destroy(&hidpp->send_mutex); |
| 2321 | 3065 | allocate_fail: |
| @@ -2327,6 +3071,8 @@ static void hidpp_remove(struct hid_device *hdev) · 5 unmodified lines | ||
| 2327 | 3071 | { |
| 2328 | 3072 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); |
| 2329 | 3073 | |
| 3074 | + sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group); | |
| 3075 | + | |
| 2330 | 3076 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { |
| 2331 | 3077 | hidpp_ff_deinit(hdev); |
| 2332 | 3078 | hid_hw_close(hdev); |
| @@ -2357,7 +3103,11 @@ static const struct hid_device_id hidpp_devices[] = { · 24 unmodified lines | ||
| 2357 | 3103 | { /* Keyboard logitech K400 */ |
| 2358 | 3104 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, |
| 2359 | 3105 | USB_VENDOR_ID_LOGITECH, 0x4024), |
| 2360 | − .driver_data = HIDPP_QUIRK_CONNECT_EVENTS | HIDPP_QUIRK_CLASS_K400 }, | |
| 3106 | + .driver_data = HIDPP_QUIRK_CLASS_K400 }, | |
| 3107 | + { /* Solar Keyboard Logitech K750 */ | |
| 3108 | + HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | |
| 3109 | + USB_VENDOR_ID_LOGITECH, 0x4002), | |
| 3110 | + .driver_data = HIDPP_QUIRK_CLASS_K750 }, | |
| 2361 | 3111 | |
| 2362 | 3112 | { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, |
| 2363 | 3113 | USB_VENDOR_ID_LOGITECH, HID_ANY_ID)}, |
| @@ -69,6 +69,7 @@ MODULE_LICENSE("GPL"); · 68 unmodified lines | ||
| 69 | 69 | #define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12) |
| 70 | 70 | #define MT_QUIRK_FORCE_GET_FEATURE (1 << 13) |
| 71 | 71 | #define MT_QUIRK_FIX_CONST_CONTACT_ID (1 << 14) |
| 72 | +#define MT_QUIRK_TOUCH_SIZE_SCALING (1 << 15) | |
| 72 | 73 | |
| 73 | 74 | #define MT_INPUTMODE_TOUCHSCREEN 0x02 |
| 74 | 75 | #define MT_INPUTMODE_TOUCHPAD 0x03 |
| @@ -222,7 +223,8 @@ static struct mt_class mt_classes[] = { · 147 unmodified lines | ||
| 222 | 223 | */ |
| 223 | 224 | { .name = MT_CLS_3M, |
| 224 | 225 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | |
| 225 | − MT_QUIRK_SLOT_IS_CONTACTID, | |
| 226 | + MT_QUIRK_SLOT_IS_CONTACTID | | |
| 227 | + MT_QUIRK_TOUCH_SIZE_SCALING, | |
| 226 | 228 | .sn_move = 2048, |
| 227 | 229 | .sn_width = 128, |
| 228 | 230 | .sn_height = 128, |
| @@ -658,9 +660,17 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input) · 429 unmodified lines | ||
| 658 | 660 | if (active) { |
| 659 | 661 | /* this finger is in proximity of the sensor */ |
| 660 | 662 | int wide = (s->w > s->h); |
| 661 | − /* divided by two to match visual scale of touch */ | |
| 662 | − int major = max(s->w, s->h) >> 1; | |
| 663 | − int minor = min(s->w, s->h) >> 1; | |
| 663 | + int major = max(s->w, s->h); | |
| 664 | + int minor = min(s->w, s->h); | |
| 665 | + | |
| 666 | + /* | |
| 667 | + * divided by two to match visual scale of touch | |
| 668 | + * for devices with this quirk | |
| 669 | + */ | |
| 670 | + if (td->mtclass.quirks & MT_QUIRK_TOUCH_SIZE_SCALING) { | |
| 671 | + major = major >> 1; | |
| 672 | + minor = minor >> 1; | |
| 673 | + } | |
| 664 | 674 | |
| 665 | 675 | input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); |
| 666 | 676 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); |
| @@ -0,0 +1,59 @@ | ||
| 1 | +/* | |
| 2 | + * USB HID quirks support for Network Technologies, Inc. "USB-SUN" USB | |
| 3 | + * adapter for pre-USB Sun keyboards | |
| 4 | + * | |
| 5 | + * Copyright (c) 2011 Google, Inc. | |
| 6 | + * | |
| 7 | + * Based on HID apple driver by | |
| 8 | + * Copyright (c) 1999 Andreas Gal | |
| 9 | + * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | |
| 10 | + * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | |
| 11 | + * Copyright (c) 2006-2007 Jiri Kosina | |
| 12 | + * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> | |
| 13 | + */ | |
| 14 | + | |
| 15 | +/* | |
| 16 | + * This program is free software; you can redistribute it and/or modify it | |
| 17 | + * under the terms of the GNU General Public License as published by the Free | |
| 18 | + * Software Foundation; either version 2 of the License, or (at your option) | |
| 19 | + * any later version. | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#include <linux/device.h> | |
| 23 | +#include <linux/input.h> | |
| 24 | +#include <linux/hid.h> | |
| 25 | +#include <linux/module.h> | |
| 26 | + | |
| 27 | +#include "hid-ids.h" | |
| 28 | + | |
| 29 | +MODULE_AUTHOR("Jonathan Klabunde Tomer <jktomer@google.com>"); | |
| 30 | +MODULE_DESCRIPTION("HID driver for Network Technologies USB-SUN keyboard adapter"); | |
| 31 | + | |
| 32 | +/* | |
| 33 | + * NTI Sun keyboard adapter has wrong logical maximum in report descriptor | |
| 34 | + */ | |
| 35 | +static __u8 *nti_usbsun_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |
| 36 | + unsigned int *rsize) | |
| 37 | +{ | |
| 38 | + if (*rsize >= 60 && rdesc[53] == 0x65 && rdesc[59] == 0x65) { | |
| 39 | + hid_info(hdev, "fixing up NTI USB-SUN keyboard adapter report descriptor\n"); | |
| 40 | + rdesc[53] = rdesc[59] = 0xe7; | |
| 41 | + } | |
| 42 | + return rdesc; | |
| 43 | +} | |
| 44 | + | |
| 45 | +static const struct hid_device_id nti_devices[] = { | |
| 46 | + { HID_USB_DEVICE(USB_VENDOR_ID_NTI, USB_DEVICE_ID_USB_SUN) }, | |
| 47 | + { } | |
| 48 | +}; | |
| 49 | +MODULE_DEVICE_TABLE(hid, nti_devices); | |
| 50 | + | |
| 51 | +static struct hid_driver nti_driver = { | |
| 52 | + .name = "nti", | |
| 53 | + .id_table = nti_devices, | |
| 54 | + .report_fixup = nti_usbsun_report_fixup | |
| 55 | +}; | |
| 56 | + | |
| 57 | +module_hid_driver(nti_driver); | |
| 58 | + | |
| 59 | +MODULE_LICENSE("GPL"); | |
| @@ -48,19 +48,21 @@ · 47 unmodified lines | ||
| 48 | 48 | #define PS3REMOTE BIT(4) |
| 49 | 49 | #define DUALSHOCK4_CONTROLLER_USB BIT(5) |
| 50 | 50 | #define DUALSHOCK4_CONTROLLER_BT BIT(6) |
| 51 | −#define MOTION_CONTROLLER_USB BIT(7) | |
| 52 | −#define MOTION_CONTROLLER_BT BIT(8) | |
| 53 | −#define NAVIGATION_CONTROLLER_USB BIT(9) | |
| 54 | −#define NAVIGATION_CONTROLLER_BT BIT(10) | |
| 55 | −#define SINO_LITE_CONTROLLER BIT(11) | |
| 56 | −#define FUTUREMAX_DANCE_MAT BIT(12) | |
| 51 | +#define DUALSHOCK4_DONGLE BIT(7) | |
| 52 | +#define MOTION_CONTROLLER_USB BIT(8) | |
| 53 | +#define MOTION_CONTROLLER_BT BIT(9) | |
| 54 | +#define NAVIGATION_CONTROLLER_USB BIT(10) | |
| 55 | +#define NAVIGATION_CONTROLLER_BT BIT(11) | |
| 56 | +#define SINO_LITE_CONTROLLER BIT(12) | |
| 57 | +#define FUTUREMAX_DANCE_MAT BIT(13) | |
| 57 | 58 | |
| 58 | 59 | #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) |
| 59 | 60 | #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) |
| 60 | 61 | #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\ |
| 61 | 62 | NAVIGATION_CONTROLLER_BT) |
| 62 | 63 | #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ |
| 63 | − DUALSHOCK4_CONTROLLER_BT) | |
| 64 | + DUALSHOCK4_CONTROLLER_BT | \ | |
| 65 | + DUALSHOCK4_DONGLE) | |
| 64 | 66 | #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ |
| 65 | 67 | DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\ |
| 66 | 68 | NAVIGATION_CONTROLLER) |
| @@ -73,89 +75,6 @@ · 6 unmodified lines | ||
| 73 | 75 | |
| 74 | 76 | #define MAX_LEDS 4 |
| 75 | 77 | |
| 76 | −/* | |
| 77 | − * The Sixaxis reports both digital and analog values for each button on the | |
| 78 | − * controller except for Start, Select and the PS button. The controller ends | |
| 79 | − * up reporting 27 axes which causes them to spill over into the multi-touch | |
| 80 | − * axis values. Additionally, the controller only has 20 actual, physical axes | |
| 81 | − * so there are several unused axes in between the used ones. | |
| 82 | − */ | |
| 83 | −static u8 sixaxis_rdesc[] = { | |
| 84 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 85 | − 0x09, 0x04, /* Usage (Joystick), */ | |
| 86 | − 0xA1, 0x01, /* Collection (Application), */ | |
| 87 | − 0xA1, 0x02, /* Collection (Logical), */ | |
| 88 | − 0x85, 0x01, /* Report ID (1), */ | |
| 89 | − 0x75, 0x08, /* Report Size (8), */ | |
| 90 | − 0x95, 0x01, /* Report Count (1), */ | |
| 91 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 92 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 93 | − 0x81, 0x03, /* Input (Constant, Variable), */ | |
| 94 | − 0x75, 0x01, /* Report Size (1), */ | |
| 95 | − 0x95, 0x13, /* Report Count (19), */ | |
| 96 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 97 | − 0x25, 0x01, /* Logical Maximum (1), */ | |
| 98 | − 0x35, 0x00, /* Physical Minimum (0), */ | |
| 99 | − 0x45, 0x01, /* Physical Maximum (1), */ | |
| 100 | − 0x05, 0x09, /* Usage Page (Button), */ | |
| 101 | − 0x19, 0x01, /* Usage Minimum (01h), */ | |
| 102 | − 0x29, 0x13, /* Usage Maximum (13h), */ | |
| 103 | − 0x81, 0x02, /* Input (Variable), */ | |
| 104 | − 0x75, 0x01, /* Report Size (1), */ | |
| 105 | − 0x95, 0x0D, /* Report Count (13), */ | |
| 106 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 107 | − 0x81, 0x03, /* Input (Constant, Variable), */ | |
| 108 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 109 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 110 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 111 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 112 | − 0xA1, 0x00, /* Collection (Physical), */ | |
| 113 | − 0x75, 0x08, /* Report Size (8), */ | |
| 114 | − 0x95, 0x04, /* Report Count (4), */ | |
| 115 | − 0x35, 0x00, /* Physical Minimum (0), */ | |
| 116 | − 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ | |
| 117 | − 0x09, 0x30, /* Usage (X), */ | |
| 118 | − 0x09, 0x31, /* Usage (Y), */ | |
| 119 | − 0x09, 0x32, /* Usage (Z), */ | |
| 120 | − 0x09, 0x35, /* Usage (Rz), */ | |
| 121 | − 0x81, 0x02, /* Input (Variable), */ | |
| 122 | − 0xC0, /* End Collection, */ | |
| 123 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 124 | − 0x95, 0x13, /* Report Count (19), */ | |
| 125 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 126 | − 0x81, 0x02, /* Input (Variable), */ | |
| 127 | − 0x95, 0x0C, /* Report Count (12), */ | |
| 128 | − 0x81, 0x01, /* Input (Constant), */ | |
| 129 | − 0x75, 0x10, /* Report Size (16), */ | |
| 130 | − 0x95, 0x04, /* Report Count (4), */ | |
| 131 | − 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | |
| 132 | − 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ | |
| 133 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 134 | − 0x81, 0x02, /* Input (Variable), */ | |
| 135 | − 0xC0, /* End Collection, */ | |
| 136 | − 0xA1, 0x02, /* Collection (Logical), */ | |
| 137 | − 0x85, 0x02, /* Report ID (2), */ | |
| 138 | − 0x75, 0x08, /* Report Size (8), */ | |
| 139 | − 0x95, 0x30, /* Report Count (48), */ | |
| 140 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 141 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 142 | − 0xC0, /* End Collection, */ | |
| 143 | − 0xA1, 0x02, /* Collection (Logical), */ | |
| 144 | − 0x85, 0xEE, /* Report ID (238), */ | |
| 145 | − 0x75, 0x08, /* Report Size (8), */ | |
| 146 | − 0x95, 0x30, /* Report Count (48), */ | |
| 147 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 148 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 149 | − 0xC0, /* End Collection, */ | |
| 150 | − 0xA1, 0x02, /* Collection (Logical), */ | |
| 151 | − 0x85, 0xEF, /* Report ID (239), */ | |
| 152 | − 0x75, 0x08, /* Report Size (8), */ | |
| 153 | − 0x95, 0x30, /* Report Count (48), */ | |
| 154 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 155 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 156 | − 0xC0, /* End Collection, */ | |
| 157 | − 0xC0 /* End Collection */ | |
| 158 | −}; | |
| 159 | 78 | |
| 160 | 79 | /* PS/3 Motion controller */ |
| 161 | 80 | static u8 motion_rdesc[] = { |
| @@ -254,567 +173,6 @@ static u8 motion_rdesc[] = { · 92 unmodified lines | ||
| 254 | 173 | 0xC0 /* End Collection */ |
| 255 | 174 | }; |
| 256 | 175 | |
| 257 | −/* PS/3 Navigation controller */ | |
| 258 | −static u8 navigation_rdesc[] = { | |
| 259 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 260 | − 0x09, 0x04, /* Usage (Joystick), */ | |
| 261 | − 0xA1, 0x01, /* Collection (Application), */ | |
| 262 | − 0xA1, 0x02, /* Collection (Logical), */ | |
| 263 | − 0x85, 0x01, /* Report ID (1), */ | |
| 264 | − 0x75, 0x08, /* Report Size (8), */ | |
| 265 | − 0x95, 0x01, /* Report Count (1), */ | |
| 266 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 267 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 268 | − 0x81, 0x03, /* Input (Constant, Variable), */ | |
| 269 | − 0x75, 0x01, /* Report Size (1), */ | |
| 270 | − 0x95, 0x13, /* Report Count (19), */ | |
| 271 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 272 | − 0x25, 0x01, /* Logical Maximum (1), */ | |
| 273 | − 0x35, 0x00, /* Physical Minimum (0), */ | |
| 274 | − 0x45, 0x01, /* Physical Maximum (1), */ | |
| 275 | − 0x05, 0x09, /* Usage Page (Button), */ | |
| 276 | − 0x19, 0x01, /* Usage Minimum (01h), */ | |
| 277 | − 0x29, 0x13, /* Usage Maximum (13h), */ | |
| 278 | − 0x81, 0x02, /* Input (Variable), */ | |
| 279 | − 0x75, 0x01, /* Report Size (1), */ | |
| 280 | − 0x95, 0x0D, /* Report Count (13), */ | |
| 281 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 282 | − 0x81, 0x03, /* Input (Constant, Variable), */ | |
| 283 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 284 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 285 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 286 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 287 | − 0xA1, 0x00, /* Collection (Physical), */ | |
| 288 | − 0x75, 0x08, /* Report Size (8), */ | |
| 289 | − 0x95, 0x02, /* Report Count (2), */ | |
| 290 | − 0x35, 0x00, /* Physical Minimum (0), */ | |
| 291 | − 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ | |
| 292 | − 0x09, 0x30, /* Usage (X), */ | |
| 293 | − 0x09, 0x31, /* Usage (Y), */ | |
| 294 | − 0x81, 0x02, /* Input (Variable), */ | |
| 295 | − 0xC0, /* End Collection, */ | |
| 296 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 297 | − 0x95, 0x06, /* Report Count (6), */ | |
| 298 | − 0x81, 0x03, /* Input (Constant, Variable), */ | |
| 299 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 300 | − 0x75, 0x08, /* Report Size (8), */ | |
| 301 | − 0x95, 0x05, /* Report Count (5), */ | |
| 302 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 303 | − 0x81, 0x02, /* Input (Variable), */ | |
| 304 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 305 | − 0x95, 0x01, /* Report Count (1), */ | |
| 306 | − 0x81, 0x02, /* Input (Variable), */ | |
| 307 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 308 | − 0x95, 0x01, /* Report Count (1), */ | |
| 309 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 310 | − 0x81, 0x02, /* Input (Variable), */ | |
| 311 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 312 | − 0x95, 0x1E, /* Report Count (24), */ | |
| 313 | − 0x81, 0x02, /* Input (Variable), */ | |
| 314 | − 0x75, 0x08, /* Report Size (8), */ | |
| 315 | − 0x95, 0x30, /* Report Count (48), */ | |
| 316 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 317 | − 0x91, 0x02, /* Output (Variable), */ | |
| 318 | − 0x75, 0x08, /* Report Size (8), */ | |
| 319 | − 0x95, 0x30, /* Report Count (48), */ | |
| 320 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 321 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 322 | − 0xC0, /* End Collection, */ | |
| 323 | − 0xA1, 0x02, /* Collection (Logical), */ | |
| 324 | − 0x85, 0x02, /* Report ID (2), */ | |
| 325 | − 0x75, 0x08, /* Report Size (8), */ | |
| 326 | − 0x95, 0x30, /* Report Count (48), */ | |
| 327 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 328 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 329 | − 0xC0, /* End Collection, */ | |
| 330 | − 0xA1, 0x02, /* Collection (Logical), */ | |
| 331 | − 0x85, 0xEE, /* Report ID (238), */ | |
| 332 | − 0x75, 0x08, /* Report Size (8), */ | |
| 333 | − 0x95, 0x30, /* Report Count (48), */ | |
| 334 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 335 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 336 | − 0xC0, /* End Collection, */ | |
| 337 | − 0xA1, 0x02, /* Collection (Logical), */ | |
| 338 | − 0x85, 0xEF, /* Report ID (239), */ | |
| 339 | − 0x75, 0x08, /* Report Size (8), */ | |
| 340 | − 0x95, 0x30, /* Report Count (48), */ | |
| 341 | − 0x09, 0x01, /* Usage (Pointer), */ | |
| 342 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 343 | − 0xC0, /* End Collection, */ | |
| 344 | − 0xC0 /* End Collection */ | |
| 345 | −}; | |
| 346 | − | |
| 347 | −/* | |
| 348 | − * The default descriptor doesn't provide mapping for the accelerometers | |
| 349 | − * or orientation sensors. This fixed descriptor maps the accelerometers | |
| 350 | − * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors | |
| 351 | − * to usage values 0x43, 0x44 and 0x45. | |
| 352 | − */ | |
| 353 | −static u8 dualshock4_usb_rdesc[] = { | |
| 354 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 355 | − 0x09, 0x05, /* Usage (Gamepad), */ | |
| 356 | − 0xA1, 0x01, /* Collection (Application), */ | |
| 357 | − 0x85, 0x01, /* Report ID (1), */ | |
| 358 | − 0x09, 0x30, /* Usage (X), */ | |
| 359 | − 0x09, 0x31, /* Usage (Y), */ | |
| 360 | − 0x09, 0x32, /* Usage (Z), */ | |
| 361 | − 0x09, 0x35, /* Usage (Rz), */ | |
| 362 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 363 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 364 | − 0x75, 0x08, /* Report Size (8), */ | |
| 365 | − 0x95, 0x04, /* Report Count (4), */ | |
| 366 | − 0x81, 0x02, /* Input (Variable), */ | |
| 367 | − 0x09, 0x39, /* Usage (Hat Switch), */ | |
| 368 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 369 | − 0x25, 0x07, /* Logical Maximum (7), */ | |
| 370 | − 0x35, 0x00, /* Physical Minimum (0), */ | |
| 371 | − 0x46, 0x3B, 0x01, /* Physical Maximum (315), */ | |
| 372 | − 0x65, 0x14, /* Unit (Degrees), */ | |
| 373 | − 0x75, 0x04, /* Report Size (4), */ | |
| 374 | − 0x95, 0x01, /* Report Count (1), */ | |
| 375 | − 0x81, 0x42, /* Input (Variable, Null State), */ | |
| 376 | − 0x65, 0x00, /* Unit, */ | |
| 377 | − 0x05, 0x09, /* Usage Page (Button), */ | |
| 378 | − 0x19, 0x01, /* Usage Minimum (01h), */ | |
| 379 | − 0x29, 0x0D, /* Usage Maximum (0Dh), */ | |
| 380 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 381 | − 0x25, 0x01, /* Logical Maximum (1), */ | |
| 382 | − 0x75, 0x01, /* Report Size (1), */ | |
| 383 | − 0x95, 0x0E, /* Report Count (14), */ | |
| 384 | − 0x81, 0x02, /* Input (Variable), */ | |
| 385 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 386 | − 0x09, 0x20, /* Usage (20h), */ | |
| 387 | − 0x75, 0x06, /* Report Size (6), */ | |
| 388 | − 0x95, 0x01, /* Report Count (1), */ | |
| 389 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 390 | − 0x25, 0x3F, /* Logical Maximum (63), */ | |
| 391 | − 0x81, 0x02, /* Input (Variable), */ | |
| 392 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 393 | − 0x09, 0x33, /* Usage (Rx), */ | |
| 394 | − 0x09, 0x34, /* Usage (Ry), */ | |
| 395 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 396 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 397 | − 0x75, 0x08, /* Report Size (8), */ | |
| 398 | − 0x95, 0x02, /* Report Count (2), */ | |
| 399 | − 0x81, 0x02, /* Input (Variable), */ | |
| 400 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 401 | − 0x09, 0x21, /* Usage (21h), */ | |
| 402 | − 0x95, 0x03, /* Report Count (3), */ | |
| 403 | − 0x81, 0x02, /* Input (Variable), */ | |
| 404 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 405 | − 0x19, 0x40, /* Usage Minimum (40h), */ | |
| 406 | − 0x29, 0x42, /* Usage Maximum (42h), */ | |
| 407 | − 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ | |
| 408 | − 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | |
| 409 | − 0x75, 0x10, /* Report Size (16), */ | |
| 410 | − 0x95, 0x03, /* Report Count (3), */ | |
| 411 | − 0x81, 0x02, /* Input (Variable), */ | |
| 412 | − 0x19, 0x43, /* Usage Minimum (43h), */ | |
| 413 | − 0x29, 0x45, /* Usage Maximum (45h), */ | |
| 414 | − 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ | |
| 415 | − 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | |
| 416 | − 0x95, 0x03, /* Report Count (3), */ | |
| 417 | − 0x81, 0x02, /* Input (Variable), */ | |
| 418 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 419 | − 0x09, 0x21, /* Usage (21h), */ | |
| 420 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 421 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 422 | − 0x75, 0x08, /* Report Size (8), */ | |
| 423 | − 0x95, 0x27, /* Report Count (39), */ | |
| 424 | − 0x81, 0x02, /* Input (Variable), */ | |
| 425 | − 0x85, 0x05, /* Report ID (5), */ | |
| 426 | − 0x09, 0x22, /* Usage (22h), */ | |
| 427 | − 0x95, 0x1F, /* Report Count (31), */ | |
| 428 | − 0x91, 0x02, /* Output (Variable), */ | |
| 429 | − 0x85, 0x04, /* Report ID (4), */ | |
| 430 | − 0x09, 0x23, /* Usage (23h), */ | |
| 431 | − 0x95, 0x24, /* Report Count (36), */ | |
| 432 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 433 | − 0x85, 0x02, /* Report ID (2), */ | |
| 434 | − 0x09, 0x24, /* Usage (24h), */ | |
| 435 | − 0x95, 0x24, /* Report Count (36), */ | |
| 436 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 437 | − 0x85, 0x08, /* Report ID (8), */ | |
| 438 | − 0x09, 0x25, /* Usage (25h), */ | |
| 439 | − 0x95, 0x03, /* Report Count (3), */ | |
| 440 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 441 | − 0x85, 0x10, /* Report ID (16), */ | |
| 442 | − 0x09, 0x26, /* Usage (26h), */ | |
| 443 | − 0x95, 0x04, /* Report Count (4), */ | |
| 444 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 445 | − 0x85, 0x11, /* Report ID (17), */ | |
| 446 | − 0x09, 0x27, /* Usage (27h), */ | |
| 447 | − 0x95, 0x02, /* Report Count (2), */ | |
| 448 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 449 | − 0x85, 0x12, /* Report ID (18), */ | |
| 450 | − 0x06, 0x02, 0xFF, /* Usage Page (FF02h), */ | |
| 451 | − 0x09, 0x21, /* Usage (21h), */ | |
| 452 | − 0x95, 0x0F, /* Report Count (15), */ | |
| 453 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 454 | − 0x85, 0x13, /* Report ID (19), */ | |
| 455 | − 0x09, 0x22, /* Usage (22h), */ | |
| 456 | − 0x95, 0x16, /* Report Count (22), */ | |
| 457 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 458 | − 0x85, 0x14, /* Report ID (20), */ | |
| 459 | − 0x06, 0x05, 0xFF, /* Usage Page (FF05h), */ | |
| 460 | − 0x09, 0x20, /* Usage (20h), */ | |
| 461 | − 0x95, 0x10, /* Report Count (16), */ | |
| 462 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 463 | − 0x85, 0x15, /* Report ID (21), */ | |
| 464 | − 0x09, 0x21, /* Usage (21h), */ | |
| 465 | − 0x95, 0x2C, /* Report Count (44), */ | |
| 466 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 467 | − 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ | |
| 468 | − 0x85, 0x80, /* Report ID (128), */ | |
| 469 | − 0x09, 0x20, /* Usage (20h), */ | |
| 470 | − 0x95, 0x06, /* Report Count (6), */ | |
| 471 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 472 | − 0x85, 0x81, /* Report ID (129), */ | |
| 473 | − 0x09, 0x21, /* Usage (21h), */ | |
| 474 | − 0x95, 0x06, /* Report Count (6), */ | |
| 475 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 476 | − 0x85, 0x82, /* Report ID (130), */ | |
| 477 | − 0x09, 0x22, /* Usage (22h), */ | |
| 478 | − 0x95, 0x05, /* Report Count (5), */ | |
| 479 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 480 | − 0x85, 0x83, /* Report ID (131), */ | |
| 481 | − 0x09, 0x23, /* Usage (23h), */ | |
| 482 | − 0x95, 0x01, /* Report Count (1), */ | |
| 483 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 484 | − 0x85, 0x84, /* Report ID (132), */ | |
| 485 | − 0x09, 0x24, /* Usage (24h), */ | |
| 486 | − 0x95, 0x04, /* Report Count (4), */ | |
| 487 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 488 | − 0x85, 0x85, /* Report ID (133), */ | |
| 489 | − 0x09, 0x25, /* Usage (25h), */ | |
| 490 | − 0x95, 0x06, /* Report Count (6), */ | |
| 491 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 492 | − 0x85, 0x86, /* Report ID (134), */ | |
| 493 | − 0x09, 0x26, /* Usage (26h), */ | |
| 494 | − 0x95, 0x06, /* Report Count (6), */ | |
| 495 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 496 | − 0x85, 0x87, /* Report ID (135), */ | |
| 497 | − 0x09, 0x27, /* Usage (27h), */ | |
| 498 | − 0x95, 0x23, /* Report Count (35), */ | |
| 499 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 500 | − 0x85, 0x88, /* Report ID (136), */ | |
| 501 | − 0x09, 0x28, /* Usage (28h), */ | |
| 502 | − 0x95, 0x22, /* Report Count (34), */ | |
| 503 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 504 | − 0x85, 0x89, /* Report ID (137), */ | |
| 505 | − 0x09, 0x29, /* Usage (29h), */ | |
| 506 | − 0x95, 0x02, /* Report Count (2), */ | |
| 507 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 508 | − 0x85, 0x90, /* Report ID (144), */ | |
| 509 | − 0x09, 0x30, /* Usage (30h), */ | |
| 510 | − 0x95, 0x05, /* Report Count (5), */ | |
| 511 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 512 | − 0x85, 0x91, /* Report ID (145), */ | |
| 513 | − 0x09, 0x31, /* Usage (31h), */ | |
| 514 | − 0x95, 0x03, /* Report Count (3), */ | |
| 515 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 516 | − 0x85, 0x92, /* Report ID (146), */ | |
| 517 | − 0x09, 0x32, /* Usage (32h), */ | |
| 518 | − 0x95, 0x03, /* Report Count (3), */ | |
| 519 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 520 | − 0x85, 0x93, /* Report ID (147), */ | |
| 521 | − 0x09, 0x33, /* Usage (33h), */ | |
| 522 | − 0x95, 0x0C, /* Report Count (12), */ | |
| 523 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 524 | − 0x85, 0xA0, /* Report ID (160), */ | |
| 525 | − 0x09, 0x40, /* Usage (40h), */ | |
| 526 | − 0x95, 0x06, /* Report Count (6), */ | |
| 527 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 528 | − 0x85, 0xA1, /* Report ID (161), */ | |
| 529 | − 0x09, 0x41, /* Usage (41h), */ | |
| 530 | − 0x95, 0x01, /* Report Count (1), */ | |
| 531 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 532 | − 0x85, 0xA2, /* Report ID (162), */ | |
| 533 | − 0x09, 0x42, /* Usage (42h), */ | |
| 534 | − 0x95, 0x01, /* Report Count (1), */ | |
| 535 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 536 | − 0x85, 0xA3, /* Report ID (163), */ | |
| 537 | − 0x09, 0x43, /* Usage (43h), */ | |
| 538 | − 0x95, 0x30, /* Report Count (48), */ | |
| 539 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 540 | − 0x85, 0xA4, /* Report ID (164), */ | |
| 541 | − 0x09, 0x44, /* Usage (44h), */ | |
| 542 | − 0x95, 0x0D, /* Report Count (13), */ | |
| 543 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 544 | − 0x85, 0xA5, /* Report ID (165), */ | |
| 545 | − 0x09, 0x45, /* Usage (45h), */ | |
| 546 | − 0x95, 0x15, /* Report Count (21), */ | |
| 547 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 548 | − 0x85, 0xA6, /* Report ID (166), */ | |
| 549 | − 0x09, 0x46, /* Usage (46h), */ | |
| 550 | − 0x95, 0x15, /* Report Count (21), */ | |
| 551 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 552 | − 0x85, 0xF0, /* Report ID (240), */ | |
| 553 | − 0x09, 0x47, /* Usage (47h), */ | |
| 554 | − 0x95, 0x3F, /* Report Count (63), */ | |
| 555 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 556 | − 0x85, 0xF1, /* Report ID (241), */ | |
| 557 | − 0x09, 0x48, /* Usage (48h), */ | |
| 558 | − 0x95, 0x3F, /* Report Count (63), */ | |
| 559 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 560 | − 0x85, 0xF2, /* Report ID (242), */ | |
| 561 | − 0x09, 0x49, /* Usage (49h), */ | |
| 562 | − 0x95, 0x0F, /* Report Count (15), */ | |
| 563 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 564 | − 0x85, 0xA7, /* Report ID (167), */ | |
| 565 | − 0x09, 0x4A, /* Usage (4Ah), */ | |
| 566 | − 0x95, 0x01, /* Report Count (1), */ | |
| 567 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 568 | − 0x85, 0xA8, /* Report ID (168), */ | |
| 569 | − 0x09, 0x4B, /* Usage (4Bh), */ | |
| 570 | − 0x95, 0x01, /* Report Count (1), */ | |
| 571 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 572 | − 0x85, 0xA9, /* Report ID (169), */ | |
| 573 | − 0x09, 0x4C, /* Usage (4Ch), */ | |
| 574 | − 0x95, 0x08, /* Report Count (8), */ | |
| 575 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 576 | − 0x85, 0xAA, /* Report ID (170), */ | |
| 577 | − 0x09, 0x4E, /* Usage (4Eh), */ | |
| 578 | − 0x95, 0x01, /* Report Count (1), */ | |
| 579 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 580 | − 0x85, 0xAB, /* Report ID (171), */ | |
| 581 | − 0x09, 0x4F, /* Usage (4Fh), */ | |
| 582 | − 0x95, 0x39, /* Report Count (57), */ | |
| 583 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 584 | − 0x85, 0xAC, /* Report ID (172), */ | |
| 585 | − 0x09, 0x50, /* Usage (50h), */ | |
| 586 | − 0x95, 0x39, /* Report Count (57), */ | |
| 587 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 588 | − 0x85, 0xAD, /* Report ID (173), */ | |
| 589 | − 0x09, 0x51, /* Usage (51h), */ | |
| 590 | − 0x95, 0x0B, /* Report Count (11), */ | |
| 591 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 592 | − 0x85, 0xAE, /* Report ID (174), */ | |
| 593 | − 0x09, 0x52, /* Usage (52h), */ | |
| 594 | − 0x95, 0x01, /* Report Count (1), */ | |
| 595 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 596 | − 0x85, 0xAF, /* Report ID (175), */ | |
| 597 | − 0x09, 0x53, /* Usage (53h), */ | |
| 598 | − 0x95, 0x02, /* Report Count (2), */ | |
| 599 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 600 | − 0x85, 0xB0, /* Report ID (176), */ | |
| 601 | − 0x09, 0x54, /* Usage (54h), */ | |
| 602 | − 0x95, 0x3F, /* Report Count (63), */ | |
| 603 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 604 | − 0xC0 /* End Collection */ | |
| 605 | −}; | |
| 606 | − | |
| 607 | −/* | |
| 608 | − * The default behavior of the Dualshock 4 is to send reports using report | |
| 609 | − * type 1 when running over Bluetooth. However, when feature report 2 is | |
| 610 | − * requested during the controller initialization it starts sending input | |
| 611 | − * reports in report 17. Since report 17 is undefined in the default HID | |
| 612 | − * descriptor the button and axis definitions must be moved to report 17 or | |
| 613 | − * the HID layer won't process the received input. | |
| 614 | − */ | |
| 615 | −static u8 dualshock4_bt_rdesc[] = { | |
| 616 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 617 | − 0x09, 0x05, /* Usage (Gamepad), */ | |
| 618 | − 0xA1, 0x01, /* Collection (Application), */ | |
| 619 | − 0x85, 0x01, /* Report ID (1), */ | |
| 620 | − 0x75, 0x08, /* Report Size (8), */ | |
| 621 | − 0x95, 0x0A, /* Report Count (9), */ | |
| 622 | − 0x81, 0x02, /* Input (Variable), */ | |
| 623 | − 0x06, 0x04, 0xFF, /* Usage Page (FF04h), */ | |
| 624 | − 0x85, 0x02, /* Report ID (2), */ | |
| 625 | − 0x09, 0x24, /* Usage (24h), */ | |
| 626 | − 0x95, 0x24, /* Report Count (36), */ | |
| 627 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 628 | − 0x85, 0xA3, /* Report ID (163), */ | |
| 629 | − 0x09, 0x25, /* Usage (25h), */ | |
| 630 | − 0x95, 0x30, /* Report Count (48), */ | |
| 631 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 632 | − 0x85, 0x05, /* Report ID (5), */ | |
| 633 | − 0x09, 0x26, /* Usage (26h), */ | |
| 634 | − 0x95, 0x28, /* Report Count (40), */ | |
| 635 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 636 | − 0x85, 0x06, /* Report ID (6), */ | |
| 637 | − 0x09, 0x27, /* Usage (27h), */ | |
| 638 | − 0x95, 0x34, /* Report Count (52), */ | |
| 639 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 640 | − 0x85, 0x07, /* Report ID (7), */ | |
| 641 | − 0x09, 0x28, /* Usage (28h), */ | |
| 642 | − 0x95, 0x30, /* Report Count (48), */ | |
| 643 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 644 | − 0x85, 0x08, /* Report ID (8), */ | |
| 645 | − 0x09, 0x29, /* Usage (29h), */ | |
| 646 | − 0x95, 0x2F, /* Report Count (47), */ | |
| 647 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 648 | − 0x06, 0x03, 0xFF, /* Usage Page (FF03h), */ | |
| 649 | − 0x85, 0x03, /* Report ID (3), */ | |
| 650 | − 0x09, 0x21, /* Usage (21h), */ | |
| 651 | − 0x95, 0x26, /* Report Count (38), */ | |
| 652 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 653 | − 0x85, 0x04, /* Report ID (4), */ | |
| 654 | − 0x09, 0x22, /* Usage (22h), */ | |
| 655 | − 0x95, 0x2E, /* Report Count (46), */ | |
| 656 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 657 | − 0x85, 0xF0, /* Report ID (240), */ | |
| 658 | − 0x09, 0x47, /* Usage (47h), */ | |
| 659 | − 0x95, 0x3F, /* Report Count (63), */ | |
| 660 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 661 | − 0x85, 0xF1, /* Report ID (241), */ | |
| 662 | − 0x09, 0x48, /* Usage (48h), */ | |
| 663 | − 0x95, 0x3F, /* Report Count (63), */ | |
| 664 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 665 | − 0x85, 0xF2, /* Report ID (242), */ | |
| 666 | − 0x09, 0x49, /* Usage (49h), */ | |
| 667 | − 0x95, 0x0F, /* Report Count (15), */ | |
| 668 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 669 | − 0x85, 0x11, /* Report ID (17), */ | |
| 670 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 671 | − 0x09, 0x20, /* Usage (20h), */ | |
| 672 | − 0x95, 0x02, /* Report Count (2), */ | |
| 673 | − 0x81, 0x02, /* Input (Variable), */ | |
| 674 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 675 | − 0x09, 0x30, /* Usage (X), */ | |
| 676 | − 0x09, 0x31, /* Usage (Y), */ | |
| 677 | − 0x09, 0x32, /* Usage (Z), */ | |
| 678 | − 0x09, 0x35, /* Usage (Rz), */ | |
| 679 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 680 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 681 | − 0x75, 0x08, /* Report Size (8), */ | |
| 682 | − 0x95, 0x04, /* Report Count (4), */ | |
| 683 | − 0x81, 0x02, /* Input (Variable), */ | |
| 684 | − 0x09, 0x39, /* Usage (Hat Switch), */ | |
| 685 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 686 | − 0x25, 0x07, /* Logical Maximum (7), */ | |
| 687 | − 0x75, 0x04, /* Report Size (4), */ | |
| 688 | − 0x95, 0x01, /* Report Count (1), */ | |
| 689 | − 0x81, 0x42, /* Input (Variable, Null State), */ | |
| 690 | − 0x05, 0x09, /* Usage Page (Button), */ | |
| 691 | − 0x19, 0x01, /* Usage Minimum (01h), */ | |
| 692 | − 0x29, 0x0D, /* Usage Maximum (0Dh), */ | |
| 693 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 694 | − 0x25, 0x01, /* Logical Maximum (1), */ | |
| 695 | − 0x75, 0x01, /* Report Size (1), */ | |
| 696 | − 0x95, 0x0E, /* Report Count (14), */ | |
| 697 | − 0x81, 0x02, /* Input (Variable), */ | |
| 698 | − 0x75, 0x06, /* Report Size (6), */ | |
| 699 | − 0x95, 0x01, /* Report Count (1), */ | |
| 700 | − 0x81, 0x01, /* Input (Constant), */ | |
| 701 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 702 | − 0x09, 0x33, /* Usage (Rx), */ | |
| 703 | − 0x09, 0x34, /* Usage (Ry), */ | |
| 704 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 705 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 706 | − 0x75, 0x08, /* Report Size (8), */ | |
| 707 | − 0x95, 0x02, /* Report Count (2), */ | |
| 708 | − 0x81, 0x02, /* Input (Variable), */ | |
| 709 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 710 | − 0x09, 0x20, /* Usage (20h), */ | |
| 711 | − 0x95, 0x03, /* Report Count (3), */ | |
| 712 | − 0x81, 0x02, /* Input (Variable), */ | |
| 713 | − 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 714 | − 0x19, 0x40, /* Usage Minimum (40h), */ | |
| 715 | − 0x29, 0x42, /* Usage Maximum (42h), */ | |
| 716 | − 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ | |
| 717 | − 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | |
| 718 | − 0x75, 0x10, /* Report Size (16), */ | |
| 719 | − 0x95, 0x03, /* Report Count (3), */ | |
| 720 | − 0x81, 0x02, /* Input (Variable), */ | |
| 721 | − 0x19, 0x43, /* Usage Minimum (43h), */ | |
| 722 | − 0x29, 0x45, /* Usage Maximum (45h), */ | |
| 723 | − 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ | |
| 724 | − 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | |
| 725 | − 0x95, 0x03, /* Report Count (3), */ | |
| 726 | − 0x81, 0x02, /* Input (Variable), */ | |
| 727 | − 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ | |
| 728 | − 0x09, 0x20, /* Usage (20h), */ | |
| 729 | − 0x15, 0x00, /* Logical Minimum (0), */ | |
| 730 | − 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | |
| 731 | − 0x75, 0x08, /* Report Size (8), */ | |
| 732 | − 0x95, 0x31, /* Report Count (51), */ | |
| 733 | − 0x81, 0x02, /* Input (Variable), */ | |
| 734 | − 0x09, 0x21, /* Usage (21h), */ | |
| 735 | − 0x75, 0x08, /* Report Size (8), */ | |
| 736 | − 0x95, 0x4D, /* Report Count (77), */ | |
| 737 | − 0x91, 0x02, /* Output (Variable), */ | |
| 738 | − 0x85, 0x12, /* Report ID (18), */ | |
| 739 | − 0x09, 0x22, /* Usage (22h), */ | |
| 740 | − 0x95, 0x8D, /* Report Count (141), */ | |
| 741 | − 0x81, 0x02, /* Input (Variable), */ | |
| 742 | − 0x09, 0x23, /* Usage (23h), */ | |
| 743 | − 0x91, 0x02, /* Output (Variable), */ | |
| 744 | − 0x85, 0x13, /* Report ID (19), */ | |
| 745 | − 0x09, 0x24, /* Usage (24h), */ | |
| 746 | − 0x95, 0xCD, /* Report Count (205), */ | |
| 747 | − 0x81, 0x02, /* Input (Variable), */ | |
| 748 | − 0x09, 0x25, /* Usage (25h), */ | |
| 749 | − 0x91, 0x02, /* Output (Variable), */ | |
| 750 | − 0x85, 0x14, /* Report ID (20), */ | |
| 751 | − 0x09, 0x26, /* Usage (26h), */ | |
| 752 | − 0x96, 0x0D, 0x01, /* Report Count (269), */ | |
| 753 | − 0x81, 0x02, /* Input (Variable), */ | |
| 754 | − 0x09, 0x27, /* Usage (27h), */ | |
| 755 | − 0x91, 0x02, /* Output (Variable), */ | |
| 756 | − 0x85, 0x15, /* Report ID (21), */ | |
| 757 | − 0x09, 0x28, /* Usage (28h), */ | |
| 758 | − 0x96, 0x4D, 0x01, /* Report Count (333), */ | |
| 759 | − 0x81, 0x02, /* Input (Variable), */ | |
| 760 | − 0x09, 0x29, /* Usage (29h), */ | |
| 761 | − 0x91, 0x02, /* Output (Variable), */ | |
| 762 | − 0x85, 0x16, /* Report ID (22), */ | |
| 763 | − 0x09, 0x2A, /* Usage (2Ah), */ | |
| 764 | − 0x96, 0x8D, 0x01, /* Report Count (397), */ | |
| 765 | − 0x81, 0x02, /* Input (Variable), */ | |
| 766 | − 0x09, 0x2B, /* Usage (2Bh), */ | |
| 767 | − 0x91, 0x02, /* Output (Variable), */ | |
| 768 | − 0x85, 0x17, /* Report ID (23), */ | |
| 769 | − 0x09, 0x2C, /* Usage (2Ch), */ | |
| 770 | − 0x96, 0xCD, 0x01, /* Report Count (461), */ | |
| 771 | − 0x81, 0x02, /* Input (Variable), */ | |
| 772 | − 0x09, 0x2D, /* Usage (2Dh), */ | |
| 773 | − 0x91, 0x02, /* Output (Variable), */ | |
| 774 | − 0x85, 0x18, /* Report ID (24), */ | |
| 775 | − 0x09, 0x2E, /* Usage (2Eh), */ | |
| 776 | − 0x96, 0x0D, 0x02, /* Report Count (525), */ | |
| 777 | − 0x81, 0x02, /* Input (Variable), */ | |
| 778 | − 0x09, 0x2F, /* Usage (2Fh), */ | |
| 779 | − 0x91, 0x02, /* Output (Variable), */ | |
| 780 | − 0x85, 0x19, /* Report ID (25), */ | |
| 781 | − 0x09, 0x30, /* Usage (30h), */ | |
| 782 | − 0x96, 0x22, 0x02, /* Report Count (546), */ | |
| 783 | − 0x81, 0x02, /* Input (Variable), */ | |
| 784 | − 0x09, 0x31, /* Usage (31h), */ | |
| 785 | − 0x91, 0x02, /* Output (Variable), */ | |
| 786 | − 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ | |
| 787 | − 0x85, 0x82, /* Report ID (130), */ | |
| 788 | − 0x09, 0x22, /* Usage (22h), */ | |
| 789 | − 0x95, 0x3F, /* Report Count (63), */ | |
| 790 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 791 | − 0x85, 0x83, /* Report ID (131), */ | |
| 792 | − 0x09, 0x23, /* Usage (23h), */ | |
| 793 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 794 | − 0x85, 0x84, /* Report ID (132), */ | |
| 795 | − 0x09, 0x24, /* Usage (24h), */ | |
| 796 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 797 | − 0x85, 0x90, /* Report ID (144), */ | |
| 798 | − 0x09, 0x30, /* Usage (30h), */ | |
| 799 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 800 | − 0x85, 0x91, /* Report ID (145), */ | |
| 801 | − 0x09, 0x31, /* Usage (31h), */ | |
| 802 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 803 | − 0x85, 0x92, /* Report ID (146), */ | |
| 804 | − 0x09, 0x32, /* Usage (32h), */ | |
| 805 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 806 | − 0x85, 0x93, /* Report ID (147), */ | |
| 807 | − 0x09, 0x33, /* Usage (33h), */ | |
| 808 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 809 | − 0x85, 0xA0, /* Report ID (160), */ | |
| 810 | − 0x09, 0x40, /* Usage (40h), */ | |
| 811 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 812 | − 0x85, 0xA4, /* Report ID (164), */ | |
| 813 | − 0x09, 0x44, /* Usage (44h), */ | |
| 814 | − 0xB1, 0x02, /* Feature (Variable), */ | |
| 815 | − 0xC0 /* End Collection */ | |
| 816 | −}; | |
| 817 | − | |
| 818 | 176 | static u8 ps3remote_rdesc[] = { |
| 819 | 177 | 0x05, 0x01, /* GUsagePage Generic Desktop */ |
| 820 | 178 | 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ |
| @@ -977,6 +335,67 @@ static const unsigned int buzz_keymap[] = { · 156 unmodified lines | ||
| 977 | 335 | [20] = BTN_TRIGGER_HAPPY20, |
| 978 | 336 | }; |
| 979 | 337 | |
| 338 | +/* The Navigation controller is a partial DS3 and uses the same HID report | |
| 339 | + * and hence the same keymap indices, however not not all axes/buttons | |
| 340 | + * are physically present. We use the same axis and button mapping as | |
| 341 | + * the DS3, which uses the Linux gamepad spec. | |
| 342 | + */ | |
| 343 | +static const unsigned int navigation_absmap[] = { | |
| 344 | + [0x30] = ABS_X, | |
| 345 | + [0x31] = ABS_Y, | |
| 346 | + [0x33] = ABS_Z, /* L2 */ | |
| 347 | +}; | |
| 348 | + | |
| 349 | +/* Buttons not physically available on the device, but still available | |
| 350 | + * in the reports are explicitly set to 0 for documentation purposes. | |
| 351 | + */ | |
| 352 | +static const unsigned int navigation_keymap[] = { | |
| 353 | + [0x01] = 0, /* Select */ | |
| 354 | + [0x02] = BTN_THUMBL, /* L3 */ | |
| 355 | + [0x03] = 0, /* R3 */ | |
| 356 | + [0x04] = 0, /* Start */ | |
| 357 | + [0x05] = BTN_DPAD_UP, /* Up */ | |
| 358 | + [0x06] = BTN_DPAD_RIGHT, /* Right */ | |
| 359 | + [0x07] = BTN_DPAD_DOWN, /* Down */ | |
| 360 | + [0x08] = BTN_DPAD_LEFT, /* Left */ | |
| 361 | + [0x09] = BTN_TL2, /* L2 */ | |
| 362 | + [0x0a] = 0, /* R2 */ | |
| 363 | + [0x0b] = BTN_TL, /* L1 */ | |
| 364 | + [0x0c] = 0, /* R1 */ | |
| 365 | + [0x0d] = BTN_NORTH, /* Triangle */ | |
| 366 | + [0x0e] = BTN_EAST, /* Circle */ | |
| 367 | + [0x0f] = BTN_SOUTH, /* Cross */ | |
| 368 | + [0x10] = BTN_WEST, /* Square */ | |
| 369 | + [0x11] = BTN_MODE, /* PS */ | |
| 370 | +}; | |
| 371 | + | |
| 372 | +static const unsigned int sixaxis_absmap[] = { | |
| 373 | + [0x30] = ABS_X, | |
| 374 | + [0x31] = ABS_Y, | |
| 375 | + [0x32] = ABS_RX, /* right stick X */ | |
| 376 | + [0x35] = ABS_RY, /* right stick Y */ | |
| 377 | +}; | |
| 378 | + | |
| 379 | +static const unsigned int sixaxis_keymap[] = { | |
| 380 | + [0x01] = BTN_SELECT, /* Select */ | |
| 381 | + [0x02] = BTN_THUMBL, /* L3 */ | |
| 382 | + [0x03] = BTN_THUMBR, /* R3 */ | |
| 383 | + [0x04] = BTN_START, /* Start */ | |
| 384 | + [0x05] = BTN_DPAD_UP, /* Up */ | |
| 385 | + [0x06] = BTN_DPAD_RIGHT, /* Right */ | |
| 386 | + [0x07] = BTN_DPAD_DOWN, /* Down */ | |
| 387 | + [0x08] = BTN_DPAD_LEFT, /* Left */ | |
| 388 | + [0x09] = BTN_TL2, /* L2 */ | |
| 389 | + [0x0a] = BTN_TR2, /* R2 */ | |
| 390 | + [0x0b] = BTN_TL, /* L1 */ | |
| 391 | + [0x0c] = BTN_TR, /* R1 */ | |
| 392 | + [0x0d] = BTN_NORTH, /* Triangle */ | |
| 393 | + [0x0e] = BTN_EAST, /* Circle */ | |
| 394 | + [0x0f] = BTN_SOUTH, /* Cross */ | |
| 395 | + [0x10] = BTN_WEST, /* Square */ | |
| 396 | + [0x11] = BTN_MODE, /* PS */ | |
| 397 | +}; | |
| 398 | + | |
| 980 | 399 | static const unsigned int ds4_absmap[] = { |
| 981 | 400 | [0x30] = ABS_X, |
| 982 | 401 | [0x31] = ABS_Y, |
| @@ -1002,6 +421,10 @@ static const unsigned int ds4_keymap[] = { · 19 unmodified lines | ||
| 1002 | 421 | [0xd] = BTN_MODE, /* PS */ |
| 1003 | 422 | }; |
| 1004 | 423 | |
| 424 | +static const struct {int x; int y; } ds4_hat_mapping[] = { | |
| 425 | + {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, | |
| 426 | + {0, 0} | |
| 427 | +}; | |
| 1005 | 428 | |
| 1006 | 429 | static enum power_supply_property sony_battery_props[] = { |
| 1007 | 430 | POWER_SUPPLY_PROP_PRESENT, |
| @@ -1048,6 +471,7 @@ struct motion_output_report_02 { · 40 unmodified lines | ||
| 1048 | 471 | }; |
| 1049 | 472 | |
| 1050 | 473 | #define DS4_FEATURE_REPORT_0x02_SIZE 37 |
| 474 | +#define DS4_FEATURE_REPORT_0x05_SIZE 41 | |
| 1051 | 475 | #define DS4_FEATURE_REPORT_0x81_SIZE 7 |
| 1052 | 476 | #define DS4_INPUT_REPORT_0x11_SIZE 78 |
| 1053 | 477 | #define DS4_OUTPUT_REPORT_0x05_SIZE 32 |
| @@ -1059,23 +483,62 @@ struct motion_output_report_02 { · 5 unmodified lines | ||
| 1059 | 483 | /* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an |
| 1060 | 484 | * additional +2. |
| 1061 | 485 | */ |
| 486 | +#define DS4_INPUT_REPORT_AXIS_OFFSET 1 | |
| 1062 | 487 | #define DS4_INPUT_REPORT_BUTTON_OFFSET 5 |
| 488 | +#define DS4_INPUT_REPORT_TIMESTAMP_OFFSET 10 | |
| 489 | +#define DS4_INPUT_REPORT_GYRO_X_OFFSET 13 | |
| 1063 | 490 | #define DS4_INPUT_REPORT_BATTERY_OFFSET 30 |
| 1064 | 491 | #define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33 |
| 1065 | 492 | |
| 493 | +#define SENSOR_SUFFIX " Motion Sensors" | |
| 1066 | 494 | #define DS4_TOUCHPAD_SUFFIX " Touchpad" |
| 1067 | 495 | |
| 496 | +/* Default to 4ms poll interval, which is same as USB (not adjustable). */ | |
| 497 | +#define DS4_BT_DEFAULT_POLL_INTERVAL_MS 4 | |
| 498 | +#define DS4_BT_MAX_POLL_INTERVAL_MS 62 | |
| 499 | +#define DS4_GYRO_RES_PER_DEG_S 1024 | |
| 500 | +#define DS4_ACC_RES_PER_G 8192 | |
| 501 | + | |
| 502 | +#define SIXAXIS_INPUT_REPORT_ACC_X_OFFSET 41 | |
| 503 | +#define SIXAXIS_ACC_RES_PER_G 113 | |
| 504 | + | |
| 1068 | 505 | static DEFINE_SPINLOCK(sony_dev_list_lock); |
| 1069 | 506 | static LIST_HEAD(sony_device_list); |
| 1070 | 507 | static DEFINE_IDA(sony_device_id_allocator); |
| 1071 | 508 | |
| 509 | +/* Used for calibration of DS4 accelerometer and gyro. */ | |
| 510 | +struct ds4_calibration_data { | |
| 511 | + int abs_code; | |
| 512 | + short bias; | |
| 513 | + /* Calibration requires scaling against a sensitivity value, which is a | |
| 514 | + * float. Store sensitivity as a fraction to limit floating point | |
| 515 | + * calculations until final calibration. | |
| 516 | + */ | |
| 517 | + int sens_numer; | |
| 518 | + int sens_denom; | |
| 519 | +}; | |
| 520 | + | |
| 521 | +enum ds4_dongle_state { | |
| 522 | + DONGLE_DISCONNECTED, | |
| 523 | + DONGLE_CALIBRATING, | |
| 524 | + DONGLE_CONNECTED, | |
| 525 | + DONGLE_DISABLED | |
| 526 | +}; | |
| 527 | + | |
| 528 | +enum sony_worker { | |
| 529 | + SONY_WORKER_STATE, | |
| 530 | + SONY_WORKER_HOTPLUG | |
| 531 | +}; | |
| 532 | + | |
| 1072 | 533 | struct sony_sc { |
| 1073 | 534 | spinlock_t lock; |
| 1074 | 535 | struct list_head list_node; |
| 1075 | 536 | struct hid_device *hdev; |
| 1076 | 537 | struct input_dev *touchpad; |
| 538 | + struct input_dev *sensor_dev; | |
| 1077 | 539 | struct led_classdev *leds[MAX_LEDS]; |
| 1078 | 540 | unsigned long quirks; |
| 541 | + struct work_struct hotplug_worker; | |
| 1079 | 542 | struct work_struct state_worker; |
| 1080 | 543 | void (*send_output_report)(struct sony_sc *); |
| 1081 | 544 | struct power_supply *battery; |
| @@ -1089,46 +552,87 @@ struct sony_sc { · 7 unmodified lines | ||
| 1089 | 552 | #endif |
| 1090 | 553 | |
| 1091 | 554 | u8 mac_address[6]; |
| 1092 | − u8 worker_initialized; | |
| 555 | + u8 hotplug_worker_initialized; | |
| 556 | + u8 state_worker_initialized; | |
| 1093 | 557 | u8 defer_initialization; |
| 1094 | 558 | u8 cable_state; |
| 1095 | 559 | u8 battery_charging; |
| 1096 | 560 | u8 battery_capacity; |
| 1097 | 561 | u8 led_state[MAX_LEDS]; |
| 1098 | − u8 resume_led_state[MAX_LEDS]; | |
| 1099 | 562 | u8 led_delay_on[MAX_LEDS]; |
| 1100 | 563 | u8 led_delay_off[MAX_LEDS]; |
| 1101 | 564 | u8 led_count; |
| 1102 | − bool ds4_dongle_connected; | |
| 565 | + | |
| 566 | + bool timestamp_initialized; | |
| 567 | + u16 prev_timestamp; | |
| 568 | + unsigned int timestamp_us; | |
| 569 | + | |
| 570 | + u8 ds4_bt_poll_interval; | |
| 571 | + enum ds4_dongle_state ds4_dongle_state; | |
| 572 | + /* DS4 calibration data */ | |
| 573 | + struct ds4_calibration_data ds4_calib_data[6]; | |
| 1103 | 574 | }; |
| 1104 | 575 | |
| 1105 | 576 | static void sony_set_leds(struct sony_sc *sc); |
| 1106 | 577 | |
| 1107 | −static inline void sony_schedule_work(struct sony_sc *sc) | |
| 578 | +static inline void sony_schedule_work(struct sony_sc *sc, | |
| 579 | + enum sony_worker which) | |
| 1108 | 580 | { |
| 1109 | − if (!sc->defer_initialization) | |
| 1110 | − schedule_work(&sc->state_worker); | |
| 581 | + switch (which) { | |
| 582 | + case SONY_WORKER_STATE: | |
| 583 | + if (!sc->defer_initialization) | |
| 584 | + schedule_work(&sc->state_worker); | |
| 585 | + break; | |
| 586 | + case SONY_WORKER_HOTPLUG: | |
| 587 | + if (sc->hotplug_worker_initialized) | |
| 588 | + schedule_work(&sc->hotplug_worker); | |
| 589 | + break; | |
| 590 | + } | |
| 1111 | 591 | } |
| 1112 | 592 | |
| 1113 | −static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc, | |
| 1114 | − unsigned int *rsize) | |
| 593 | +static ssize_t ds4_show_poll_interval(struct device *dev, | |
| 594 | + struct device_attribute | |
| 595 | + *attr, char *buf) | |
| 1115 | 596 | { |
| 1116 | − *rsize = sizeof(sixaxis_rdesc); | |
| 1117 | − return sixaxis_rdesc; | |
| 597 | + struct hid_device *hdev = to_hid_device(dev); | |
| 598 | + struct sony_sc *sc = hid_get_drvdata(hdev); | |
| 599 | + | |
| 600 | + return snprintf(buf, PAGE_SIZE, "%i\n", sc->ds4_bt_poll_interval); | |
| 1118 | 601 | } |
| 1119 | 602 | |
| 1120 | −static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, | |
| 1121 | − unsigned int *rsize) | |
| 603 | +static ssize_t ds4_store_poll_interval(struct device *dev, | |
| 604 | + struct device_attribute *attr, | |
| 605 | + const char *buf, size_t count) | |
| 1122 | 606 | { |
| 1123 | − *rsize = sizeof(motion_rdesc); | |
| 1124 | − return motion_rdesc; | |
| 607 | + struct hid_device *hdev = to_hid_device(dev); | |
| 608 | + struct sony_sc *sc = hid_get_drvdata(hdev); | |
| 609 | + unsigned long flags; | |
| 610 | + u8 interval; | |
| 611 | + | |
| 612 | + if (kstrtou8(buf, 0, &interval)) | |
| 613 | + return -EINVAL; | |
| 614 | + | |
| 615 | + if (interval > DS4_BT_MAX_POLL_INTERVAL_MS) | |
| 616 | + return -EINVAL; | |
| 617 | + | |
| 618 | + spin_lock_irqsave(&sc->lock, flags); | |
| 619 | + sc->ds4_bt_poll_interval = interval; | |
| 620 | + spin_unlock_irqrestore(&sc->lock, flags); | |
| 621 | + | |
| 622 | + sony_schedule_work(sc, SONY_WORKER_STATE); | |
| 623 | + | |
| 624 | + return count; | |
| 1125 | 625 | } |
| 1126 | 626 | |
| 1127 | −static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc, | |
| 627 | +static DEVICE_ATTR(bt_poll_interval, 0644, ds4_show_poll_interval, | |
| 628 | + ds4_store_poll_interval); | |
| 629 | + | |
| 630 | + | |
| 631 | +static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, | |
| 1128 | 632 | unsigned int *rsize) |
| 1129 | 633 | { |
| 1130 | − *rsize = sizeof(navigation_rdesc); | |
| 1131 | − return navigation_rdesc; | |
| 634 | + *rsize = sizeof(motion_rdesc); | |
| 635 | + return motion_rdesc; | |
| 1132 | 636 | } |
| 1133 | 637 | |
| 1134 | 638 | static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc, |
| @@ -1172,6 +676,102 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, · 37 unmodified lines | ||
| 1172 | 676 | return 1; |
| 1173 | 677 | } |
| 1174 | 678 | |
| 679 | +static int navigation_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 680 | + struct hid_field *field, struct hid_usage *usage, | |
| 681 | + unsigned long **bit, int *max) | |
| 682 | +{ | |
| 683 | + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { | |
| 684 | + unsigned int key = usage->hid & HID_USAGE; | |
| 685 | + | |
| 686 | + if (key >= ARRAY_SIZE(sixaxis_keymap)) | |
| 687 | + return -1; | |
| 688 | + | |
| 689 | + key = navigation_keymap[key]; | |
| 690 | + if (!key) | |
| 691 | + return -1; | |
| 692 | + | |
| 693 | + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); | |
| 694 | + return 1; | |
| 695 | + } else if (usage->hid == HID_GD_POINTER) { | |
| 696 | + /* See comment in sixaxis_mapping, basically the L2 (and R2) | |
| 697 | + * triggers are reported through GD Pointer. | |
| 698 | + * In addition we ignore any analog button 'axes' and only | |
| 699 | + * support digital buttons. | |
| 700 | + */ | |
| 701 | + switch (usage->usage_index) { | |
| 702 | + case 8: /* L2 */ | |
| 703 | + usage->hid = HID_GD_Z; | |
| 704 | + break; | |
| 705 | + default: | |
| 706 | + return -1; | |
| 707 | + } | |
| 708 | + | |
| 709 | + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, usage->hid & 0xf); | |
| 710 | + return 1; | |
| 711 | + } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { | |
| 712 | + unsigned int abs = usage->hid & HID_USAGE; | |
| 713 | + | |
| 714 | + if (abs >= ARRAY_SIZE(navigation_absmap)) | |
| 715 | + return -1; | |
| 716 | + | |
| 717 | + abs = navigation_absmap[abs]; | |
| 718 | + | |
| 719 | + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); | |
| 720 | + return 1; | |
| 721 | + } | |
| 722 | + | |
| 723 | + return -1; | |
| 724 | +} | |
| 725 | + | |
| 726 | + | |
| 727 | +static int sixaxis_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 728 | + struct hid_field *field, struct hid_usage *usage, | |
| 729 | + unsigned long **bit, int *max) | |
| 730 | +{ | |
| 731 | + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { | |
| 732 | + unsigned int key = usage->hid & HID_USAGE; | |
| 733 | + | |
| 734 | + if (key >= ARRAY_SIZE(sixaxis_keymap)) | |
| 735 | + return -1; | |
| 736 | + | |
| 737 | + key = sixaxis_keymap[key]; | |
| 738 | + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); | |
| 739 | + return 1; | |
| 740 | + } else if (usage->hid == HID_GD_POINTER) { | |
| 741 | + /* The DS3 provides analog values for most buttons and even | |
| 742 | + * for HAT axes through GD Pointer. L2 and R2 are reported | |
| 743 | + * among these as well instead of as GD Z / RZ. Remap L2 | |
| 744 | + * and R2 and ignore other analog 'button axes' as there is | |
| 745 | + * no good way for reporting them. | |
| 746 | + */ | |
| 747 | + switch (usage->usage_index) { | |
| 748 | + case 8: /* L2 */ | |
| 749 | + usage->hid = HID_GD_Z; | |
| 750 | + break; | |
| 751 | + case 9: /* R2 */ | |
| 752 | + usage->hid = HID_GD_RZ; | |
| 753 | + break; | |
| 754 | + default: | |
| 755 | + return -1; | |
| 756 | + } | |
| 757 | + | |
| 758 | + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, usage->hid & 0xf); | |
| 759 | + return 1; | |
| 760 | + } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { | |
| 761 | + unsigned int abs = usage->hid & HID_USAGE; | |
| 762 | + | |
| 763 | + if (abs >= ARRAY_SIZE(sixaxis_absmap)) | |
| 764 | + return -1; | |
| 765 | + | |
| 766 | + abs = sixaxis_absmap[abs]; | |
| 767 | + | |
| 768 | + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); | |
| 769 | + return 1; | |
| 770 | + } | |
| 771 | + | |
| 772 | + return -1; | |
| 773 | +} | |
| 774 | + | |
| 1175 | 775 | static int ds4_mapping(struct hid_device *hdev, struct hid_input *hi, |
| 1176 | 776 | struct hid_field *field, struct hid_usage *usage, |
| 1177 | 777 | unsigned long **bit, int *max) |
| @@ -1227,30 +827,9 @@ static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, · 49 unmodified lines | ||
| 1227 | 827 | rdesc[55] = 0x06; |
| 1228 | 828 | } |
| 1229 | 829 | |
| 1230 | − /* | |
| 1231 | − * The default Dualshock 4 USB descriptor doesn't assign | |
| 1232 | − * the gyroscope values to corresponding axes so we need a | |
| 1233 | − * modified one. | |
| 1234 | − */ | |
| 1235 | − if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | |
| 1236 | − hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n"); | |
| 1237 | − rdesc = dualshock4_usb_rdesc; | |
| 1238 | − *rsize = sizeof(dualshock4_usb_rdesc); | |
| 1239 | − } else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { | |
| 1240 | − hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n"); | |
| 1241 | − rdesc = dualshock4_bt_rdesc; | |
| 1242 | − *rsize = sizeof(dualshock4_bt_rdesc); | |
| 1243 | − } | |
| 1244 | − | |
| 1245 | − if (sc->quirks & SIXAXIS_CONTROLLER) | |
| 1246 | − return sixaxis_fixup(hdev, rdesc, rsize); | |
| 1247 | − | |
| 1248 | 830 | if (sc->quirks & MOTION_CONTROLLER) |
| 1249 | 831 | return motion_fixup(hdev, rdesc, rsize); |
| 1250 | 832 | |
| 1251 | − if (sc->quirks & NAVIGATION_CONTROLLER) | |
| 1252 | − return navigation_fixup(hdev, rdesc, rsize); | |
| 1253 | − | |
| 1254 | 833 | if (sc->quirks & PS3REMOTE) |
| 1255 | 834 | return ps3remote_fixup(hdev, rdesc, rsize); |
| 1256 | 835 | |
| @@ -1288,21 +867,131 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) · 31 unmodified lines | ||
| 1288 | 867 | sc->battery_capacity = battery_capacity; |
| 1289 | 868 | sc->battery_charging = battery_charging; |
| 1290 | 869 | spin_unlock_irqrestore(&sc->lock, flags); |
| 870 | + | |
| 871 | + if (sc->quirks & SIXAXIS_CONTROLLER) { | |
| 872 | + int val; | |
| 873 | + | |
| 874 | + offset = SIXAXIS_INPUT_REPORT_ACC_X_OFFSET; | |
| 875 | + val = ((rd[offset+1] << 8) | rd[offset]) - 511; | |
| 876 | + input_report_abs(sc->sensor_dev, ABS_X, val); | |
| 877 | + | |
| 878 | + /* Y and Z are swapped and inversed */ | |
| 879 | + val = 511 - ((rd[offset+5] << 8) | rd[offset+4]); | |
| 880 | + input_report_abs(sc->sensor_dev, ABS_Y, val); | |
| 881 | + | |
| 882 | + val = 511 - ((rd[offset+3] << 8) | rd[offset+2]); | |
| 883 | + input_report_abs(sc->sensor_dev, ABS_Z, val); | |
| 884 | + | |
| 885 | + input_sync(sc->sensor_dev); | |
| 886 | + } | |
| 1291 | 887 | } |
| 1292 | 888 | |
| 1293 | 889 | static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) |
| 1294 | 890 | { |
| 891 | + struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, | |
| 892 | + struct hid_input, list); | |
| 893 | + struct input_dev *input_dev = hidinput->input; | |
| 1295 | 894 | unsigned long flags; |
| 1296 | 895 | int n, m, offset, num_touch_data, max_touch_data; |
| 1297 | 896 | u8 cable_state, battery_capacity, battery_charging; |
| 897 | + u16 timestamp; | |
| 1298 | 898 | |
| 1299 | 899 | /* When using Bluetooth the header is 2 bytes longer, so skip these. */ |
| 1300 | − int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2; | |
| 900 | + int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_BT) ? 2 : 0; | |
| 1301 | 901 | |
| 1302 | 902 | /* Second bit of third button byte is for the touchpad button. */ |
| 1303 | 903 | offset = data_offset + DS4_INPUT_REPORT_BUTTON_OFFSET; |
| 1304 | 904 | input_report_key(sc->touchpad, BTN_LEFT, rd[offset+2] & 0x2); |
| 1305 | 905 | |
| 906 | + /* | |
| 907 | + * The default behavior of the Dualshock 4 is to send reports using | |
| 908 | + * report type 1 when running over Bluetooth. However, when feature | |
| 909 | + * report 2 is requested during the controller initialization it starts | |
| 910 | + * sending input reports in report 17. Since report 17 is undefined | |
| 911 | + * in the default HID descriptor, the HID layer won't generate events. | |
| 912 | + * While it is possible (and this was done before) to fixup the HID | |
| 913 | + * descriptor to add this mapping, it was better to do this manually. | |
| 914 | + * The reason is there were various pieces software both open and closed | |
| 915 | + * source, relying on the descriptors to be the same across various | |
| 916 | + * operating systems. If the descriptors wouldn't match some | |
| 917 | + * applications e.g. games on Wine would not be able to function due | |
| 918 | + * to different descriptors, which such applications are not parsing. | |
| 919 | + */ | |
| 920 | + if (rd[0] == 17) { | |
| 921 | + int value; | |
| 922 | + | |
| 923 | + offset = data_offset + DS4_INPUT_REPORT_AXIS_OFFSET; | |
| 924 | + input_report_abs(input_dev, ABS_X, rd[offset]); | |
| 925 | + input_report_abs(input_dev, ABS_Y, rd[offset+1]); | |
| 926 | + input_report_abs(input_dev, ABS_RX, rd[offset+2]); | |
| 927 | + input_report_abs(input_dev, ABS_RY, rd[offset+3]); | |
| 928 | + | |
| 929 | + value = rd[offset+4] & 0xf; | |
| 930 | + if (value > 7) | |
| 931 | + value = 8; /* Center 0, 0 */ | |
| 932 | + input_report_abs(input_dev, ABS_HAT0X, ds4_hat_mapping[value].x); | |
| 933 | + input_report_abs(input_dev, ABS_HAT0Y, ds4_hat_mapping[value].y); | |
| 934 | + | |
| 935 | + input_report_key(input_dev, BTN_WEST, rd[offset+4] & 0x10); | |
| 936 | + input_report_key(input_dev, BTN_SOUTH, rd[offset+4] & 0x20); | |
| 937 | + input_report_key(input_dev, BTN_EAST, rd[offset+4] & 0x40); | |
| 938 | + input_report_key(input_dev, BTN_NORTH, rd[offset+4] & 0x80); | |
| 939 | + | |
| 940 | + input_report_key(input_dev, BTN_TL, rd[offset+5] & 0x1); | |
| 941 | + input_report_key(input_dev, BTN_TR, rd[offset+5] & 0x2); | |
| 942 | + input_report_key(input_dev, BTN_TL2, rd[offset+5] & 0x4); | |
| 943 | + input_report_key(input_dev, BTN_TR2, rd[offset+5] & 0x8); | |
| 944 | + input_report_key(input_dev, BTN_SELECT, rd[offset+5] & 0x10); | |
| 945 | + input_report_key(input_dev, BTN_START, rd[offset+5] & 0x20); | |
| 946 | + input_report_key(input_dev, BTN_THUMBL, rd[offset+5] & 0x40); | |
| 947 | + input_report_key(input_dev, BTN_THUMBR, rd[offset+5] & 0x80); | |
| 948 | + | |
| 949 | + input_report_key(input_dev, BTN_MODE, rd[offset+6] & 0x1); | |
| 950 | + | |
| 951 | + input_report_abs(input_dev, ABS_Z, rd[offset+7]); | |
| 952 | + input_report_abs(input_dev, ABS_RZ, rd[offset+8]); | |
| 953 | + | |
| 954 | + input_sync(input_dev); | |
| 955 | + } | |
| 956 | + | |
| 957 | + /* Convert timestamp (in 5.33us unit) to timestamp_us */ | |
| 958 | + offset = data_offset + DS4_INPUT_REPORT_TIMESTAMP_OFFSET; | |
| 959 | + timestamp = get_unaligned_le16(&rd[offset]); | |
| 960 | + if (!sc->timestamp_initialized) { | |
| 961 | + sc->timestamp_us = ((unsigned int)timestamp * 16) / 3; | |
| 962 | + sc->timestamp_initialized = true; | |
| 963 | + } else { | |
| 964 | + u16 delta; | |
| 965 | + | |
| 966 | + if (sc->prev_timestamp > timestamp) | |
| 967 | + delta = (U16_MAX - sc->prev_timestamp + timestamp + 1); | |
| 968 | + else | |
| 969 | + delta = timestamp - sc->prev_timestamp; | |
| 970 | + sc->timestamp_us += (delta * 16) / 3; | |
| 971 | + } | |
| 972 | + sc->prev_timestamp = timestamp; | |
| 973 | + input_event(sc->sensor_dev, EV_MSC, MSC_TIMESTAMP, sc->timestamp_us); | |
| 974 | + | |
| 975 | + offset = data_offset + DS4_INPUT_REPORT_GYRO_X_OFFSET; | |
| 976 | + for (n = 0; n < 6; n++) { | |
| 977 | + /* Store data in int for more precision during mult_frac. */ | |
| 978 | + int raw_data = (short)((rd[offset+1] << 8) | rd[offset]); | |
| 979 | + struct ds4_calibration_data *calib = &sc->ds4_calib_data[n]; | |
| 980 | + | |
| 981 | + /* High precision is needed during calibration, but the | |
| 982 | + * calibrated values are within 32-bit. | |
| 983 | + * Note: we swap numerator 'x' and 'numer' in mult_frac for | |
| 984 | + * precision reasons so we don't need 64-bit. | |
| 985 | + */ | |
| 986 | + int calib_data = mult_frac(calib->sens_numer, | |
| 987 | + raw_data - calib->bias, | |
| 988 | + calib->sens_denom); | |
| 989 | + | |
| 990 | + input_report_abs(sc->sensor_dev, calib->abs_code, calib_data); | |
| 991 | + offset += 2; | |
| 992 | + } | |
| 993 | + input_sync(sc->sensor_dev); | |
| 994 | + | |
| 1306 | 995 | /* |
| 1307 | 996 | * The lower 4 bits of byte 30 (or 32 for BT) contain the battery level |
| 1308 | 997 | * and the 5th bit contains the USB cable state. |
| @@ -1341,7 +1030,7 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) · 32 unmodified lines | ||
| 1341 | 1030 | * Trackpad data starts 2 bytes later (e.g. 35 for USB). |
| 1342 | 1031 | */ |
| 1343 | 1032 | offset = data_offset + DS4_INPUT_REPORT_TOUCHPAD_OFFSET; |
| 1344 | − max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 3 : 4; | |
| 1033 | + max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_BT) ? 4 : 3; | |
| 1345 | 1034 | if (rd[offset] > 0 && rd[offset] <= max_touch_data) |
| 1346 | 1035 | num_touch_data = rd[offset]; |
| 1347 | 1036 | else |
| @@ -1415,47 +1104,79 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, · 67 unmodified lines | ||
| 1415 | 1104 | } else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 && |
| 1416 | 1105 | size == 49) { |
| 1417 | 1106 | sixaxis_parse_report(sc, rd, size); |
| 1418 | − } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && | |
| 1419 | − size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) | |
| 1420 | − && rd[0] == 0x11 && size == 78)) { | |
| 1421 | − if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { | |
| 1422 | − /* CRC check */ | |
| 1423 | − u8 bthdr = 0xA1; | |
| 1424 | − u32 crc; | |
| 1425 | − u32 report_crc; | |
| 1107 | + } else if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && | |
| 1108 | + size == 64) { | |
| 1109 | + dualshock4_parse_report(sc, rd, size); | |
| 1110 | + } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && rd[0] == 0x11 && | |
| 1111 | + size == 78)) { | |
| 1112 | + /* CRC check */ | |
| 1113 | + u8 bthdr = 0xA1; | |
| 1114 | + u32 crc; | |
| 1115 | + u32 report_crc; | |
| 1426 | 1116 | |
| 1427 | − crc = crc32_le(0xFFFFFFFF, &bthdr, 1); | |
| 1428 | − crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4); | |
| 1429 | − report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]); | |
| 1430 | − if (crc != report_crc) { | |
| 1431 | − hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n", | |
| 1432 | − report_crc, crc); | |
| 1433 | − return -EILSEQ; | |
| 1434 | − } | |
| 1117 | + crc = crc32_le(0xFFFFFFFF, &bthdr, 1); | |
| 1118 | + crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4); | |
| 1119 | + report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]); | |
| 1120 | + if (crc != report_crc) { | |
| 1121 | + hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n", | |
| 1122 | + report_crc, crc); | |
| 1123 | + return -EILSEQ; | |
| 1435 | 1124 | } |
| 1436 | 1125 | |
| 1126 | + dualshock4_parse_report(sc, rd, size); | |
| 1127 | + } else if ((sc->quirks & DUALSHOCK4_DONGLE) && rd[0] == 0x01 && | |
| 1128 | + size == 64) { | |
| 1129 | + unsigned long flags; | |
| 1130 | + enum ds4_dongle_state dongle_state; | |
| 1131 | + | |
| 1437 | 1132 | /* |
| 1438 | 1133 | * In the case of a DS4 USB dongle, bit[2] of byte 31 indicates |
| 1439 | 1134 | * if a DS4 is actually connected (indicated by '0'). |
| 1440 | 1135 | * For non-dongle, this bit is always 0 (connected). |
| 1441 | 1136 | */ |
| 1442 | − if (sc->hdev->vendor == USB_VENDOR_ID_SONY && | |
| 1443 | − sc->hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) { | |
| 1444 | − bool connected = (rd[31] & 0x04) ? false : true; | |
| 1445 | − | |
| 1446 | − if (!sc->ds4_dongle_connected && connected) { | |
| 1447 | − hid_info(sc->hdev, "DualShock 4 USB dongle: controller connected\n"); | |
| 1448 | − sony_set_leds(sc); | |
| 1449 | − sc->ds4_dongle_connected = true; | |
| 1450 | − } else if (sc->ds4_dongle_connected && !connected) { | |
| 1451 | − hid_info(sc->hdev, "DualShock 4 USB dongle: controller disconnected\n"); | |
| 1452 | − sc->ds4_dongle_connected = false; | |
| 1453 | − /* Return 0, so hidraw can get the report. */ | |
| 1454 | − return 0; | |
| 1455 | − } else if (!sc->ds4_dongle_connected) { | |
| 1456 | − /* Return 0, so hidraw can get the report. */ | |
| 1457 | − return 0; | |
| 1458 | − } | |
| 1137 | + bool connected = (rd[31] & 0x04) ? false : true; | |
| 1138 | + | |
| 1139 | + spin_lock_irqsave(&sc->lock, flags); | |
| 1140 | + dongle_state = sc->ds4_dongle_state; | |
| 1141 | + spin_unlock_irqrestore(&sc->lock, flags); | |
| 1142 | + | |
| 1143 | + /* | |
| 1144 | + * The dongle always sends input reports even when no | |
| 1145 | + * DS4 is attached. When a DS4 is connected, we need to | |
| 1146 | + * obtain calibration data before we can use it. | |
| 1147 | + * The code below tracks dongle state and kicks of | |
| 1148 | + * calibration when needed and only allows us to process | |
| 1149 | + * input if a DS4 is actually connected. | |
| 1150 | + */ | |
| 1151 | + if (dongle_state == DONGLE_DISCONNECTED && connected) { | |
| 1152 | + hid_info(sc->hdev, "DualShock 4 USB dongle: controller connected\n"); | |
| 1153 | + sony_set_leds(sc); | |
| 1154 | + | |
| 1155 | + spin_lock_irqsave(&sc->lock, flags); | |
| 1156 | + sc->ds4_dongle_state = DONGLE_CALIBRATING; | |
| 1157 | + spin_unlock_irqrestore(&sc->lock, flags); | |
| 1158 | + | |
| 1159 | + sony_schedule_work(sc, SONY_WORKER_HOTPLUG); | |
| 1160 | + | |
| 1161 | + /* Don't process the report since we don't have | |
| 1162 | + * calibration data, but let hidraw have it anyway. | |
| 1163 | + */ | |
| 1164 | + return 0; | |
| 1165 | + } else if ((dongle_state == DONGLE_CONNECTED || | |
| 1166 | + dongle_state == DONGLE_DISABLED) && !connected) { | |
| 1167 | + hid_info(sc->hdev, "DualShock 4 USB dongle: controller disconnected\n"); | |
| 1168 | + | |
| 1169 | + spin_lock_irqsave(&sc->lock, flags); | |
| 1170 | + sc->ds4_dongle_state = DONGLE_DISCONNECTED; | |
| 1171 | + spin_unlock_irqrestore(&sc->lock, flags); | |
| 1172 | + | |
| 1173 | + /* Return 0, so hidraw can get the report. */ | |
| 1174 | + return 0; | |
| 1175 | + } else if (dongle_state == DONGLE_CALIBRATING || | |
| 1176 | + dongle_state == DONGLE_DISABLED || | |
| 1177 | + dongle_state == DONGLE_DISCONNECTED) { | |
| 1178 | + /* Return 0, so hidraw can get the report. */ | |
| 1179 | + return 0; | |
| 1459 | 1180 | } |
| 1460 | 1181 | |
| 1461 | 1182 | dualshock4_parse_report(sc, rd, size); |
| @@ -1463,7 +1184,7 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, · 1 unmodified line | ||
| 1463 | 1184 | |
| 1464 | 1185 | if (sc->defer_initialization) { |
| 1465 | 1186 | sc->defer_initialization = 0; |
| 1466 | − sony_schedule_work(sc); | |
| 1187 | + sony_schedule_work(sc, SONY_WORKER_STATE); | |
| 1467 | 1188 | } |
| 1468 | 1189 | |
| 1469 | 1190 | return 0; |
| @@ -1501,10 +1222,16 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, · 31 unmodified lines | ||
| 1501 | 1222 | if (sc->quirks & PS3REMOTE) |
| 1502 | 1223 | return ps3remote_mapping(hdev, hi, field, usage, bit, max); |
| 1503 | 1224 | |
| 1225 | + if (sc->quirks & NAVIGATION_CONTROLLER) | |
| 1226 | + return navigation_mapping(hdev, hi, field, usage, bit, max); | |
| 1227 | + | |
| 1228 | + if (sc->quirks & SIXAXIS_CONTROLLER) | |
| 1229 | + return sixaxis_mapping(hdev, hi, field, usage, bit, max); | |
| 1504 | 1230 | |
| 1505 | 1231 | if (sc->quirks & DUALSHOCK4_CONTROLLER) |
| 1506 | 1232 | return ds4_mapping(hdev, hi, field, usage, bit, max); |
| 1507 | 1233 | |
| 1234 | + | |
| 1508 | 1235 | /* Let hid-core decide for the others */ |
| 1509 | 1236 | return 0; |
| 1510 | 1237 | } |
| @@ -1541,7 +1268,7 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count, · 30 unmodified lines | ||
| 1541 | 1268 | snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name); |
| 1542 | 1269 | sc->touchpad->name = name; |
| 1543 | 1270 | |
| 1544 | − ret = input_mt_init_slots(sc->touchpad, touch_count, 0); | |
| 1271 | + ret = input_mt_init_slots(sc->touchpad, touch_count, INPUT_MT_POINTER); | |
| 1545 | 1272 | if (ret < 0) |
| 1546 | 1273 | goto err; |
| 1547 | 1274 | |
| @@ -1581,6 +1308,103 @@ static void sony_unregister_touchpad(struct sony_sc *sc) · 33 unmodified lines | ||
| 1581 | 1308 | sc->touchpad = NULL; |
| 1582 | 1309 | } |
| 1583 | 1310 | |
| 1311 | +static int sony_register_sensors(struct sony_sc *sc) | |
| 1312 | +{ | |
| 1313 | + size_t name_sz; | |
| 1314 | + char *name; | |
| 1315 | + int ret; | |
| 1316 | + int range; | |
| 1317 | + | |
| 1318 | + sc->sensor_dev = input_allocate_device(); | |
| 1319 | + if (!sc->sensor_dev) | |
| 1320 | + return -ENOMEM; | |
| 1321 | + | |
| 1322 | + input_set_drvdata(sc->sensor_dev, sc); | |
| 1323 | + sc->sensor_dev->dev.parent = &sc->hdev->dev; | |
| 1324 | + sc->sensor_dev->phys = sc->hdev->phys; | |
| 1325 | + sc->sensor_dev->uniq = sc->hdev->uniq; | |
| 1326 | + sc->sensor_dev->id.bustype = sc->hdev->bus; | |
| 1327 | + sc->sensor_dev->id.vendor = sc->hdev->vendor; | |
| 1328 | + sc->sensor_dev->id.product = sc->hdev->product; | |
| 1329 | + sc->sensor_dev->id.version = sc->hdev->version; | |
| 1330 | + | |
| 1331 | + /* Append a suffix to the controller name as there are various | |
| 1332 | + * DS4 compatible non-Sony devices with different names. | |
| 1333 | + */ | |
| 1334 | + name_sz = strlen(sc->hdev->name) + sizeof(SENSOR_SUFFIX); | |
| 1335 | + name = kzalloc(name_sz, GFP_KERNEL); | |
| 1336 | + if (!name) { | |
| 1337 | + ret = -ENOMEM; | |
| 1338 | + goto err; | |
| 1339 | + } | |
| 1340 | + snprintf(name, name_sz, "%s" SENSOR_SUFFIX, sc->hdev->name); | |
| 1341 | + sc->sensor_dev->name = name; | |
| 1342 | + | |
| 1343 | + if (sc->quirks & SIXAXIS_CONTROLLER) { | |
| 1344 | + /* For the DS3 we only support the accelerometer, which works | |
| 1345 | + * quite well even without calibration. The device also has | |
| 1346 | + * a 1-axis gyro, but it is very difficult to manage from within | |
| 1347 | + * the driver even to get data, the sensor is inaccurate and | |
| 1348 | + * the behavior is very different between hardware revisions. | |
| 1349 | + */ | |
| 1350 | + input_set_abs_params(sc->sensor_dev, ABS_X, -512, 511, 4, 0); | |
| 1351 | + input_set_abs_params(sc->sensor_dev, ABS_Y, -512, 511, 4, 0); | |
| 1352 | + input_set_abs_params(sc->sensor_dev, ABS_Z, -512, 511, 4, 0); | |
| 1353 | + input_abs_set_res(sc->sensor_dev, ABS_X, SIXAXIS_ACC_RES_PER_G); | |
| 1354 | + input_abs_set_res(sc->sensor_dev, ABS_Y, SIXAXIS_ACC_RES_PER_G); | |
| 1355 | + input_abs_set_res(sc->sensor_dev, ABS_Z, SIXAXIS_ACC_RES_PER_G); | |
| 1356 | + } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { | |
| 1357 | + range = DS4_ACC_RES_PER_G*4; | |
| 1358 | + input_set_abs_params(sc->sensor_dev, ABS_X, -range, range, 16, 0); | |
| 1359 | + input_set_abs_params(sc->sensor_dev, ABS_Y, -range, range, 16, 0); | |
| 1360 | + input_set_abs_params(sc->sensor_dev, ABS_Z, -range, range, 16, 0); | |
| 1361 | + input_abs_set_res(sc->sensor_dev, ABS_X, DS4_ACC_RES_PER_G); | |
| 1362 | + input_abs_set_res(sc->sensor_dev, ABS_Y, DS4_ACC_RES_PER_G); | |
| 1363 | + input_abs_set_res(sc->sensor_dev, ABS_Z, DS4_ACC_RES_PER_G); | |
| 1364 | + | |
| 1365 | + range = DS4_GYRO_RES_PER_DEG_S*2048; | |
| 1366 | + input_set_abs_params(sc->sensor_dev, ABS_RX, -range, range, 16, 0); | |
| 1367 | + input_set_abs_params(sc->sensor_dev, ABS_RY, -range, range, 16, 0); | |
| 1368 | + input_set_abs_params(sc->sensor_dev, ABS_RZ, -range, range, 16, 0); | |
| 1369 | + input_abs_set_res(sc->sensor_dev, ABS_RX, DS4_GYRO_RES_PER_DEG_S); | |
| 1370 | + input_abs_set_res(sc->sensor_dev, ABS_RY, DS4_GYRO_RES_PER_DEG_S); | |
| 1371 | + input_abs_set_res(sc->sensor_dev, ABS_RZ, DS4_GYRO_RES_PER_DEG_S); | |
| 1372 | + | |
| 1373 | + __set_bit(EV_MSC, sc->sensor_dev->evbit); | |
| 1374 | + __set_bit(MSC_TIMESTAMP, sc->sensor_dev->mscbit); | |
| 1375 | + } | |
| 1376 | + | |
| 1377 | + __set_bit(INPUT_PROP_ACCELEROMETER, sc->sensor_dev->propbit); | |
| 1378 | + | |
| 1379 | + ret = input_register_device(sc->sensor_dev); | |
| 1380 | + if (ret < 0) | |
| 1381 | + goto err; | |
| 1382 | + | |
| 1383 | + return 0; | |
| 1384 | + | |
| 1385 | +err: | |
| 1386 | + kfree(sc->sensor_dev->name); | |
| 1387 | + sc->sensor_dev->name = NULL; | |
| 1388 | + | |
| 1389 | + input_free_device(sc->sensor_dev); | |
| 1390 | + sc->sensor_dev = NULL; | |
| 1391 | + | |
| 1392 | + return ret; | |
| 1393 | +} | |
| 1394 | + | |
| 1395 | +static void sony_unregister_sensors(struct sony_sc *sc) | |
| 1396 | +{ | |
| 1397 | + if (!sc->sensor_dev) | |
| 1398 | + return; | |
| 1399 | + | |
| 1400 | + kfree(sc->sensor_dev->name); | |
| 1401 | + sc->sensor_dev->name = NULL; | |
| 1402 | + | |
| 1403 | + input_unregister_device(sc->sensor_dev); | |
| 1404 | + sc->sensor_dev = NULL; | |
| 1405 | +} | |
| 1406 | + | |
| 1407 | + | |
| 1584 | 1408 | /* |
| 1585 | 1409 | * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller |
| 1586 | 1410 | * to "operational". Without this, the ps3 controller will not report any |
| @@ -1646,26 +1470,176 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) · 59 unmodified lines | ||
| 1646 | 1470 | } |
| 1647 | 1471 | |
| 1648 | 1472 | /* |
| 1649 | − * Requesting feature report 0x02 in Bluetooth mode changes the state of the | |
| 1650 | − * controller so that it sends full input reports of type 0x11. | |
| 1473 | + * Request DS4 calibration data for the motion sensors. | |
| 1474 | + * For Bluetooth this also affects the operating mode (see below). | |
| 1651 | 1475 | */ |
| 1652 | −static int dualshock4_set_operational_bt(struct hid_device *hdev) | |
| 1476 | +static int dualshock4_get_calibration_data(struct sony_sc *sc) | |
| 1653 | 1477 | { |
| 1654 | 1478 | u8 *buf; |
| 1655 | 1479 | int ret; |
| 1480 | + short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus; | |
| 1481 | + short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus; | |
| 1482 | + short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus; | |
| 1483 | + short gyro_speed_plus, gyro_speed_minus; | |
| 1484 | + short acc_x_plus, acc_x_minus; | |
| 1485 | + short acc_y_plus, acc_y_minus; | |
| 1486 | + short acc_z_plus, acc_z_minus; | |
| 1487 | + int speed_2x; | |
| 1488 | + int range_2g; | |
| 1489 | + | |
| 1490 | + /* For Bluetooth we use a different request, which supports CRC. | |
| 1491 | + * Note: in Bluetooth mode feature report 0x02 also changes the state | |
| 1492 | + * of the controller, so that it sends input reports of type 0x11. | |
| 1493 | + */ | |
| 1494 | + if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { | |
| 1495 | + buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL); | |
| 1496 | + if (!buf) | |
| 1497 | + return -ENOMEM; | |
| 1656 | 1498 | |
| 1657 | − buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL); | |
| 1658 | − if (!buf) | |
| 1659 | − return -ENOMEM; | |
| 1499 | + ret = hid_hw_raw_request(sc->hdev, 0x02, buf, | |
| 1500 | + DS4_FEATURE_REPORT_0x02_SIZE, | |
| 1501 | + HID_FEATURE_REPORT, | |
| 1502 | + HID_REQ_GET_REPORT); | |
| 1503 | + if (ret < 0) | |
| 1504 | + goto err_stop; | |
| 1505 | + } else { | |
| 1506 | + u8 bthdr = 0xA3; | |
| 1507 | + u32 crc; | |
| 1508 | + u32 report_crc; | |
| 1509 | + int retries; | |
| 1510 | + | |
| 1511 | + buf = kmalloc(DS4_FEATURE_REPORT_0x05_SIZE, GFP_KERNEL); | |
| 1512 | + if (!buf) | |
| 1513 | + return -ENOMEM; | |
| 1660 | 1514 | |
| 1661 | − ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_FEATURE_REPORT_0x02_SIZE, | |
| 1662 | − HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | |
| 1515 | + for (retries = 0; retries < 3; retries++) { | |
| 1516 | + ret = hid_hw_raw_request(sc->hdev, 0x05, buf, | |
| 1517 | + DS4_FEATURE_REPORT_0x05_SIZE, | |
| 1518 | + HID_FEATURE_REPORT, | |
| 1519 | + HID_REQ_GET_REPORT); | |
| 1520 | + if (ret < 0) | |
| 1521 | + goto err_stop; | |
| 1663 | 1522 | |
| 1664 | − kfree(buf); | |
| 1523 | + /* CRC check */ | |
| 1524 | + crc = crc32_le(0xFFFFFFFF, &bthdr, 1); | |
| 1525 | + crc = ~crc32_le(crc, buf, DS4_FEATURE_REPORT_0x05_SIZE-4); | |
| 1526 | + report_crc = get_unaligned_le32(&buf[DS4_FEATURE_REPORT_0x05_SIZE-4]); | |
| 1527 | + if (crc != report_crc) { | |
| 1528 | + hid_warn(sc->hdev, "DualShock 4 calibration report's CRC check failed, received crc 0x%0x != 0x%0x\n", | |
| 1529 | + report_crc, crc); | |
| 1530 | + if (retries < 2) { | |
| 1531 | + hid_warn(sc->hdev, "Retrying DualShock 4 get calibration report request\n"); | |
| 1532 | + continue; | |
| 1533 | + } else { | |
| 1534 | + ret = -EILSEQ; | |
| 1535 | + goto err_stop; | |
| 1536 | + } | |
| 1537 | + } else { | |
| 1538 | + break; | |
| 1539 | + } | |
| 1540 | + } | |
| 1541 | + } | |
| 1665 | 1542 | |
| 1543 | + gyro_pitch_bias = get_unaligned_le16(&buf[1]); | |
| 1544 | + gyro_yaw_bias = get_unaligned_le16(&buf[3]); | |
| 1545 | + gyro_roll_bias = get_unaligned_le16(&buf[5]); | |
| 1546 | + if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | |
| 1547 | + gyro_pitch_plus = get_unaligned_le16(&buf[7]); | |
| 1548 | + gyro_pitch_minus = get_unaligned_le16(&buf[9]); | |
| 1549 | + gyro_yaw_plus = get_unaligned_le16(&buf[11]); | |
| 1550 | + gyro_yaw_minus = get_unaligned_le16(&buf[13]); | |
| 1551 | + gyro_roll_plus = get_unaligned_le16(&buf[15]); | |
| 1552 | + gyro_roll_minus = get_unaligned_le16(&buf[17]); | |
| 1553 | + } else { | |
| 1554 | + /* BT + Dongle */ | |
| 1555 | + gyro_pitch_plus = get_unaligned_le16(&buf[7]); | |
| 1556 | + gyro_yaw_plus = get_unaligned_le16(&buf[9]); | |
| 1557 | + gyro_roll_plus = get_unaligned_le16(&buf[11]); | |
| 1558 | + gyro_pitch_minus = get_unaligned_le16(&buf[13]); | |
| 1559 | + gyro_yaw_minus = get_unaligned_le16(&buf[15]); | |
| 1560 | + gyro_roll_minus = get_unaligned_le16(&buf[17]); | |
| 1561 | + } | |
| 1562 | + gyro_speed_plus = get_unaligned_le16(&buf[19]); | |
| 1563 | + gyro_speed_minus = get_unaligned_le16(&buf[21]); | |
| 1564 | + acc_x_plus = get_unaligned_le16(&buf[23]); | |
| 1565 | + acc_x_minus = get_unaligned_le16(&buf[25]); | |
| 1566 | + acc_y_plus = get_unaligned_le16(&buf[27]); | |
| 1567 | + acc_y_minus = get_unaligned_le16(&buf[29]); | |
| 1568 | + acc_z_plus = get_unaligned_le16(&buf[31]); | |
| 1569 | + acc_z_minus = get_unaligned_le16(&buf[33]); | |
| 1570 | + | |
| 1571 | + /* Set gyroscope calibration and normalization parameters. | |
| 1572 | + * Data values will be normalized to 1/DS4_GYRO_RES_PER_DEG_S degree/s. | |
| 1573 | + */ | |
| 1574 | + speed_2x = (gyro_speed_plus + gyro_speed_minus); | |
| 1575 | + sc->ds4_calib_data[0].abs_code = ABS_RX; | |
| 1576 | + sc->ds4_calib_data[0].bias = gyro_pitch_bias; | |
| 1577 | + sc->ds4_calib_data[0].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S; | |
| 1578 | + sc->ds4_calib_data[0].sens_denom = gyro_pitch_plus - gyro_pitch_minus; | |
| 1579 | + | |
| 1580 | + sc->ds4_calib_data[1].abs_code = ABS_RY; | |
| 1581 | + sc->ds4_calib_data[1].bias = gyro_yaw_bias; | |
| 1582 | + sc->ds4_calib_data[1].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S; | |
| 1583 | + sc->ds4_calib_data[1].sens_denom = gyro_yaw_plus - gyro_yaw_minus; | |
| 1584 | + | |
| 1585 | + sc->ds4_calib_data[2].abs_code = ABS_RZ; | |
| 1586 | + sc->ds4_calib_data[2].bias = gyro_roll_bias; | |
| 1587 | + sc->ds4_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S; | |
| 1588 | + sc->ds4_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus; | |
| 1589 | + | |
| 1590 | + /* Set accelerometer calibration and normalization parameters. | |
| 1591 | + * Data values will be normalized to 1/DS4_ACC_RES_PER_G G. | |
| 1592 | + */ | |
| 1593 | + range_2g = acc_x_plus - acc_x_minus; | |
| 1594 | + sc->ds4_calib_data[3].abs_code = ABS_X; | |
| 1595 | + sc->ds4_calib_data[3].bias = acc_x_plus - range_2g / 2; | |
| 1596 | + sc->ds4_calib_data[3].sens_numer = 2*DS4_ACC_RES_PER_G; | |
| 1597 | + sc->ds4_calib_data[3].sens_denom = range_2g; | |
| 1598 | + | |
| 1599 | + range_2g = acc_y_plus - acc_y_minus; | |
| 1600 | + sc->ds4_calib_data[4].abs_code = ABS_Y; | |
| 1601 | + sc->ds4_calib_data[4].bias = acc_y_plus - range_2g / 2; | |
| 1602 | + sc->ds4_calib_data[4].sens_numer = 2*DS4_ACC_RES_PER_G; | |
| 1603 | + sc->ds4_calib_data[4].sens_denom = range_2g; | |
| 1604 | + | |
| 1605 | + range_2g = acc_z_plus - acc_z_minus; | |
| 1606 | + sc->ds4_calib_data[5].abs_code = ABS_Z; | |
| 1607 | + sc->ds4_calib_data[5].bias = acc_z_plus - range_2g / 2; | |
| 1608 | + sc->ds4_calib_data[5].sens_numer = 2*DS4_ACC_RES_PER_G; | |
| 1609 | + sc->ds4_calib_data[5].sens_denom = range_2g; | |
| 1610 | + | |
| 1611 | +err_stop: | |
| 1612 | + kfree(buf); | |
| 1666 | 1613 | return ret; |
| 1667 | 1614 | } |
| 1668 | 1615 | |
| 1616 | +static void dualshock4_calibration_work(struct work_struct *work) | |
| 1617 | +{ | |
| 1618 | + struct sony_sc *sc = container_of(work, struct sony_sc, hotplug_worker); | |
| 1619 | + unsigned long flags; | |
| 1620 | + enum ds4_dongle_state dongle_state; | |
| 1621 | + int ret; | |
| 1622 | + | |
| 1623 | + ret = dualshock4_get_calibration_data(sc); | |
| 1624 | + if (ret < 0) { | |
| 1625 | + /* This call is very unlikely to fail for the dongle. When it | |
| 1626 | + * fails we are probably in a very bad state, so mark the | |
| 1627 | + * dongle as disabled. We will re-enable the dongle if a new | |
| 1628 | + * DS4 hotplug is detect from sony_raw_event as any issues | |
| 1629 | + * are likely resolved then (the dongle is quite stupid). | |
| 1630 | + */ | |
| 1631 | + hid_err(sc->hdev, "DualShock 4 USB dongle: calibration failed, disabling device\n"); | |
| 1632 | + dongle_state = DONGLE_DISABLED; | |
| 1633 | + } else { | |
| 1634 | + hid_info(sc->hdev, "DualShock 4 USB dongle: calibration completed\n"); | |
| 1635 | + dongle_state = DONGLE_CONNECTED; | |
| 1636 | + } | |
| 1637 | + | |
| 1638 | + spin_lock_irqsave(&sc->lock, flags); | |
| 1639 | + sc->ds4_dongle_state = dongle_state; | |
| 1640 | + spin_unlock_irqrestore(&sc->lock, flags); | |
| 1641 | +} | |
| 1642 | + | |
| 1669 | 1643 | static void sixaxis_set_leds_from_id(struct sony_sc *sc) |
| 1670 | 1644 | { |
| 1671 | 1645 | static const u8 sixaxis_leds[10][4] = { |
| @@ -1696,10 +1670,10 @@ static void dualshock4_set_leds_from_id(struct sony_sc *sc) · 24 unmodified lines | ||
| 1696 | 1670 | { |
| 1697 | 1671 | /* The first 4 color/index entries match what the PS4 assigns */ |
| 1698 | 1672 | static const u8 color_code[7][3] = { |
| 1699 | − /* Blue */ { 0x00, 0x00, 0x01 }, | |
| 1700 | − /* Red */ { 0x01, 0x00, 0x00 }, | |
| 1701 | − /* Green */ { 0x00, 0x01, 0x00 }, | |
| 1702 | − /* Pink */ { 0x02, 0x00, 0x01 }, | |
| 1673 | + /* Blue */ { 0x00, 0x00, 0x40 }, | |
| 1674 | + /* Red */ { 0x40, 0x00, 0x00 }, | |
| 1675 | + /* Green */ { 0x00, 0x40, 0x00 }, | |
| 1676 | + /* Pink */ { 0x20, 0x00, 0x20 }, | |
| 1703 | 1677 | /* Orange */ { 0x02, 0x01, 0x00 }, |
| 1704 | 1678 | /* Teal */ { 0x00, 0x01, 0x01 }, |
| 1705 | 1679 | /* White */ { 0x01, 0x01, 0x01 } |
| @@ -1740,7 +1714,7 @@ static void buzz_set_leds(struct sony_sc *sc) · 34 unmodified lines | ||
| 1740 | 1714 | static void sony_set_leds(struct sony_sc *sc) |
| 1741 | 1715 | { |
| 1742 | 1716 | if (!(sc->quirks & BUZZ_CONTROLLER)) |
| 1743 | − sony_schedule_work(sc); | |
| 1717 | + sony_schedule_work(sc, SONY_WORKER_STATE); | |
| 1744 | 1718 | else |
| 1745 | 1719 | buzz_set_leds(sc); |
| 1746 | 1720 | } |
| @@ -1851,7 +1825,7 @@ static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on, · 104 unmodified lines | ||
| 1851 | 1825 | new_off != drv_data->led_delay_off[n]) { |
| 1852 | 1826 | drv_data->led_delay_on[n] = new_on; |
| 1853 | 1827 | drv_data->led_delay_off[n] = new_off; |
| 1854 | − sony_schedule_work(drv_data); | |
| 1828 | + sony_schedule_work(drv_data, SONY_WORKER_STATE); | |
| 1855 | 1829 | } |
| 1856 | 1830 | |
| 1857 | 1831 | return 0; |
| @@ -1964,6 +1938,7 @@ static int sony_leds_init(struct sony_sc *sc) · 106 unmodified lines | ||
| 1964 | 1938 | led->name = name; |
| 1965 | 1939 | led->brightness = sc->led_state[n]; |
| 1966 | 1940 | led->max_brightness = max_brightness[n]; |
| 1941 | + led->flags = LED_CORE_SUSPENDRESUME; | |
| 1967 | 1942 | led->brightness_get = sony_led_get_brightness; |
| 1968 | 1943 | led->brightness_set = sony_led_set_brightness; |
| 1969 | 1944 | |
| @@ -2052,26 +2027,24 @@ static void dualshock4_send_output_report(struct sony_sc *sc) · 82 unmodified lines | ||
| 2052 | 2027 | int offset; |
| 2053 | 2028 | |
| 2054 | 2029 | /* |
| 2055 | − * NOTE: The buf[1] field of the Bluetooth report controls | |
| 2056 | − * the Dualshock 4 reporting rate. | |
| 2057 | − * | |
| 2058 | − * Known values include: | |
| 2059 | − * | |
| 2060 | − * 0x80 - 1000hz (full speed) | |
| 2061 | − * 0xA0 - 31hz | |
| 2062 | − * 0xB0 - 20hz | |
| 2063 | − * 0xD0 - 66hz | |
| 2030 | + * NOTE: The lower 6 bits of buf[1] field of the Bluetooth report | |
| 2031 | + * control the interval at which Dualshock 4 reports data: | |
| 2032 | + * 0x00 - 1ms | |
| 2033 | + * 0x01 - 1ms | |
| 2034 | + * 0x02 - 2ms | |
| 2035 | + * 0x3E - 62ms | |
| 2036 | + * 0x3F - disabled | |
| 2064 | 2037 | */ |
| 2065 | − if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | |
| 2038 | + if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { | |
| 2066 | 2039 | memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE); |
| 2067 | 2040 | buf[0] = 0x05; |
| 2068 | − buf[1] = 0xFF; | |
| 2041 | + buf[1] = 0x07; /* blink + LEDs + motor */ | |
| 2069 | 2042 | offset = 4; |
| 2070 | 2043 | } else { |
| 2071 | 2044 | memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE); |
| 2072 | 2045 | buf[0] = 0x11; |
| 2073 | − buf[1] = 0xC0; /* HID + CRC */ | |
| 2074 | − buf[3] = 0x0F; | |
| 2046 | + buf[1] = 0xC0 /* HID + CRC */ | sc->ds4_bt_poll_interval; | |
| 2047 | + buf[3] = 0x07; /* blink + LEDs + motor */ | |
| 2075 | 2048 | offset = 6; |
| 2076 | 2049 | } |
| 2077 | 2050 | |
| @@ -2095,7 +2068,7 @@ static void dualshock4_send_output_report(struct sony_sc *sc) · 17 unmodified lines | ||
| 2095 | 2068 | buf[offset++] = sc->led_delay_on[3]; |
| 2096 | 2069 | buf[offset++] = sc->led_delay_off[3]; |
| 2097 | 2070 | |
| 2098 | − if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | |
| 2071 | + if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) | |
| 2099 | 2072 | hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE); |
| 2100 | 2073 | else { |
| 2101 | 2074 | /* CRC generation */ |
| @@ -2152,7 +2125,7 @@ static int sony_allocate_output_report(struct sony_sc *sc) · 50 unmodified lines | ||
| 2152 | 2125 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) |
| 2153 | 2126 | sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE, |
| 2154 | 2127 | GFP_KERNEL); |
| 2155 | − else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | |
| 2128 | + else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) | |
| 2156 | 2129 | sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE, |
| 2157 | 2130 | GFP_KERNEL); |
| 2158 | 2131 | else if (sc->quirks & MOTION_CONTROLLER) |
| @@ -2180,7 +2153,7 @@ static int sony_play_effect(struct input_dev *dev, void *data, · 21 unmodified lines | ||
| 2180 | 2153 | sc->left = effect->u.rumble.strong_magnitude / 256; |
| 2181 | 2154 | sc->right = effect->u.rumble.weak_magnitude / 256; |
| 2182 | 2155 | |
| 2183 | − sony_schedule_work(sc); | |
| 2156 | + sony_schedule_work(sc, SONY_WORKER_STATE); | |
| 2184 | 2157 | return 0; |
| 2185 | 2158 | } |
| 2186 | 2159 | |
| @@ -2397,7 +2370,7 @@ static int sony_check_add(struct sony_sc *sc) · 210 unmodified lines | ||
| 2397 | 2370 | hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n"); |
| 2398 | 2371 | return 0; |
| 2399 | 2372 | } |
| 2400 | − } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | |
| 2373 | + } else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { | |
| 2401 | 2374 | buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL); |
| 2402 | 2375 | if (!buf) |
| 2403 | 2376 | return -ENOMEM; |
| @@ -2451,6 +2424,12 @@ static int sony_check_add(struct sony_sc *sc) · 47 unmodified lines | ||
| 2451 | 2424 | */ |
| 2452 | 2425 | for (n = 0; n < 6; n++) |
| 2453 | 2426 | sc->mac_address[5-n] = buf[4+n]; |
| 2427 | + | |
| 2428 | + snprintf(sc->hdev->uniq, sizeof(sc->hdev->uniq), | |
| 2429 | + "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", | |
| 2430 | + sc->mac_address[5], sc->mac_address[4], | |
| 2431 | + sc->mac_address[3], sc->mac_address[2], | |
| 2432 | + sc->mac_address[1], sc->mac_address[0]); | |
| 2454 | 2433 | } else { |
| 2455 | 2434 | return 0; |
| 2456 | 2435 | } |
| @@ -2501,18 +2480,21 @@ static inline void sony_init_output_report(struct sony_sc *sc, · 44 unmodified lines | ||
| 2501 | 2480 | { |
| 2502 | 2481 | sc->send_output_report = send_output_report; |
| 2503 | 2482 | |
| 2504 | − if (!sc->worker_initialized) | |
| 2483 | + if (!sc->state_worker_initialized) | |
| 2505 | 2484 | INIT_WORK(&sc->state_worker, sony_state_worker); |
| 2506 | 2485 | |
| 2507 | − sc->worker_initialized = 1; | |
| 2486 | + sc->state_worker_initialized = 1; | |
| 2508 | 2487 | } |
| 2509 | 2488 | |
| 2510 | 2489 | static inline void sony_cancel_work_sync(struct sony_sc *sc) |
| 2511 | 2490 | { |
| 2512 | − if (sc->worker_initialized) | |
| 2491 | + if (sc->hotplug_worker_initialized) | |
| 2492 | + cancel_work_sync(&sc->hotplug_worker); | |
| 2493 | + if (sc->state_worker_initialized) | |
| 2513 | 2494 | cancel_work_sync(&sc->state_worker); |
| 2514 | 2495 | } |
| 2515 | 2496 | |
| 2497 | + | |
| 2516 | 2498 | static int sony_input_configured(struct hid_device *hdev, |
| 2517 | 2499 | struct hid_input *hidinput) |
| 2518 | 2500 | { |
| @@ -2526,14 +2508,17 @@ static int sony_input_configured(struct hid_device *hdev, · 7 unmodified lines | ||
| 2526 | 2508 | goto err_stop; |
| 2527 | 2509 | } |
| 2528 | 2510 | |
| 2511 | + ret = append_dev_id = sony_check_add(sc); | |
| 2512 | + if (ret < 0) | |
| 2513 | + goto err_stop; | |
| 2514 | + | |
| 2529 | 2515 | ret = sony_allocate_output_report(sc); |
| 2530 | 2516 | if (ret < 0) { |
| 2531 | 2517 | hid_err(hdev, "failed to allocate the output report buffer\n"); |
| 2532 | 2518 | goto err_stop; |
| 2533 | 2519 | } |
| 2534 | 2520 | |
| 2535 | − if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || | |
| 2536 | − (sc->quirks & NAVIGATION_CONTROLLER_USB)) { | |
| 2521 | + if (sc->quirks & NAVIGATION_CONTROLLER_USB) { | |
| 2537 | 2522 | /* |
| 2538 | 2523 | * The Sony Sixaxis does not handle HID Output Reports on the |
| 2539 | 2524 | * Interrupt EP like it could, so we need to force HID Output |
| @@ -2553,24 +2538,79 @@ static int sony_input_configured(struct hid_device *hdev, · 13 unmodified lines | ||
| 2553 | 2538 | hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; |
| 2554 | 2539 | hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; |
| 2555 | 2540 | sc->defer_initialization = 1; |
| 2541 | + | |
| 2556 | 2542 | ret = sixaxis_set_operational_usb(hdev); |
| 2543 | + if (ret < 0) { | |
| 2544 | + hid_err(hdev, "Failed to set controller into operational mode\n"); | |
| 2545 | + goto err_stop; | |
| 2546 | + } | |
| 2547 | + | |
| 2548 | + sony_init_output_report(sc, sixaxis_send_output_report); | |
| 2549 | + } else if (sc->quirks & NAVIGATION_CONTROLLER_BT) { | |
| 2550 | + /* | |
| 2551 | + * The Navigation controller wants output reports sent on the ctrl | |
| 2552 | + * endpoint when connected via Bluetooth. | |
| 2553 | + */ | |
| 2554 | + hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; | |
| 2555 | + | |
| 2556 | + ret = sixaxis_set_operational_bt(hdev); | |
| 2557 | + if (ret < 0) { | |
| 2558 | + hid_err(hdev, "Failed to set controller into operational mode\n"); | |
| 2559 | + goto err_stop; | |
| 2560 | + } | |
| 2561 | + | |
| 2557 | 2562 | sony_init_output_report(sc, sixaxis_send_output_report); |
| 2558 | − } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) || | |
| 2559 | − (sc->quirks & NAVIGATION_CONTROLLER_BT)) { | |
| 2563 | + } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { | |
| 2564 | + /* | |
| 2565 | + * The Sony Sixaxis does not handle HID Output Reports on the | |
| 2566 | + * Interrupt EP and the device only becomes active when the | |
| 2567 | + * PS button is pressed. See comment for Navigation controller | |
| 2568 | + * above for more details. | |
| 2569 | + */ | |
| 2570 | + hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; | |
| 2571 | + hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; | |
| 2572 | + sc->defer_initialization = 1; | |
| 2573 | + | |
| 2574 | + ret = sixaxis_set_operational_usb(hdev); | |
| 2575 | + if (ret < 0) { | |
| 2576 | + hid_err(hdev, "Failed to set controller into operational mode\n"); | |
| 2577 | + goto err_stop; | |
| 2578 | + } | |
| 2579 | + | |
| 2580 | + ret = sony_register_sensors(sc); | |
| 2581 | + if (ret) { | |
| 2582 | + hid_err(sc->hdev, | |
| 2583 | + "Unable to initialize motion sensors: %d\n", ret); | |
| 2584 | + goto err_stop; | |
| 2585 | + } | |
| 2586 | + | |
| 2587 | + sony_init_output_report(sc, sixaxis_send_output_report); | |
| 2588 | + } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { | |
| 2560 | 2589 | /* |
| 2561 | 2590 | * The Sixaxis wants output reports sent on the ctrl endpoint |
| 2562 | 2591 | * when connected via Bluetooth. |
| 2563 | 2592 | */ |
| 2564 | 2593 | hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; |
| 2594 | + | |
| 2565 | 2595 | ret = sixaxis_set_operational_bt(hdev); |
| 2596 | + if (ret < 0) { | |
| 2597 | + hid_err(hdev, "Failed to set controller into operational mode\n"); | |
| 2598 | + goto err_stop; | |
| 2599 | + } | |
| 2600 | + | |
| 2601 | + ret = sony_register_sensors(sc); | |
| 2602 | + if (ret) { | |
| 2603 | + hid_err(sc->hdev, | |
| 2604 | + "Unable to initialize motion sensors: %d\n", ret); | |
| 2605 | + goto err_stop; | |
| 2606 | + } | |
| 2607 | + | |
| 2566 | 2608 | sony_init_output_report(sc, sixaxis_send_output_report); |
| 2567 | 2609 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { |
| 2568 | − if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { | |
| 2569 | − ret = dualshock4_set_operational_bt(hdev); | |
| 2570 | − if (ret < 0) { | |
| 2571 | − hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); | |
| 2572 | − goto err_stop; | |
| 2573 | − } | |
| 2610 | + ret = dualshock4_get_calibration_data(sc); | |
| 2611 | + if (ret < 0) { | |
| 2612 | + hid_err(hdev, "Failed to get calibration data from Dualshock 4\n"); | |
| 2613 | + goto err_stop; | |
| 2574 | 2614 | } |
| 2575 | 2615 | |
| 2576 | 2616 | /* |
| @@ -2585,6 +2625,28 @@ static int sony_input_configured(struct hid_device *hdev, · 8 unmodified lines | ||
| 2585 | 2625 | goto err_stop; |
| 2586 | 2626 | } |
| 2587 | 2627 | |
| 2628 | + ret = sony_register_sensors(sc); | |
| 2629 | + if (ret) { | |
| 2630 | + hid_err(sc->hdev, | |
| 2631 | + "Unable to initialize motion sensors: %d\n", ret); | |
| 2632 | + goto err_stop; | |
| 2633 | + } | |
| 2634 | + | |
| 2635 | + if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { | |
| 2636 | + sc->ds4_bt_poll_interval = DS4_BT_DEFAULT_POLL_INTERVAL_MS; | |
| 2637 | + ret = device_create_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); | |
| 2638 | + if (ret) | |
| 2639 | + hid_warn(sc->hdev, | |
| 2640 | + "can't create sysfs bt_poll_interval attribute err: %d\n", | |
| 2641 | + ret); | |
| 2642 | + } | |
| 2643 | + | |
| 2644 | + if (sc->quirks & DUALSHOCK4_DONGLE) { | |
| 2645 | + INIT_WORK(&sc->hotplug_worker, dualshock4_calibration_work); | |
| 2646 | + sc->hotplug_worker_initialized = 1; | |
| 2647 | + sc->ds4_dongle_state = DONGLE_DISCONNECTED; | |
| 2648 | + } | |
| 2649 | + | |
| 2588 | 2650 | sony_init_output_report(sc, dualshock4_send_output_report); |
| 2589 | 2651 | } else if (sc->quirks & MOTION_CONTROLLER) { |
| 2590 | 2652 | sony_init_output_report(sc, motion_send_output_report); |
| @@ -2592,13 +2654,6 @@ static int sony_input_configured(struct hid_device *hdev, · 1 unmodified line | ||
| 2592 | 2654 | ret = 0; |
| 2593 | 2655 | } |
| 2594 | 2656 | |
| 2595 | − if (ret < 0) | |
| 2596 | − goto err_stop; | |
| 2597 | − | |
| 2598 | − ret = append_dev_id = sony_check_add(sc); | |
| 2599 | − if (ret < 0) | |
| 2600 | − goto err_stop; | |
| 2601 | − | |
| 2602 | 2657 | if (sc->quirks & SONY_LED_SUPPORT) { |
| 2603 | 2658 | ret = sony_leds_init(sc); |
| 2604 | 2659 | if (ret < 0) |
| @@ -2628,12 +2683,20 @@ static int sony_input_configured(struct hid_device *hdev, · 23 unmodified lines | ||
| 2628 | 2683 | err_close: |
| 2629 | 2684 | hid_hw_close(hdev); |
| 2630 | 2685 | err_stop: |
| 2686 | + /* Piggy back on the default ds4_bt_ poll_interval to determine | |
| 2687 | + * if we need to remove the file as we don't know for sure if we | |
| 2688 | + * executed that logic. | |
| 2689 | + */ | |
| 2690 | + if (sc->ds4_bt_poll_interval) | |
| 2691 | + device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); | |
| 2631 | 2692 | if (sc->quirks & SONY_LED_SUPPORT) |
| 2632 | 2693 | sony_leds_remove(sc); |
| 2633 | 2694 | if (sc->quirks & SONY_BATTERY_SUPPORT) |
| 2634 | 2695 | sony_battery_remove(sc); |
| 2635 | 2696 | if (sc->touchpad) |
| 2636 | 2697 | sony_unregister_touchpad(sc); |
| 2698 | + if (sc->sensor_dev) | |
| 2699 | + sony_unregister_sensors(sc); | |
| 2637 | 2700 | sony_cancel_work_sync(sc); |
| 2638 | 2701 | kfree(sc->output_report_dmabuf); |
| 2639 | 2702 | sony_remove_dev_list(sc); |
| @@ -2675,13 +2738,13 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 35 unmodified lines | ||
| 2675 | 2738 | else if (sc->quirks & SIXAXIS_CONTROLLER) |
| 2676 | 2739 | connect_mask |= HID_CONNECT_HIDDEV_FORCE; |
| 2677 | 2740 | |
| 2678 | − /* Patch the hw version on DS4 compatible devices, so applications can | |
| 2741 | + /* Patch the hw version on DS3/4 compatible devices, so applications can | |
| 2679 | 2742 | * distinguish between the default HID mappings and the mappings defined |
| 2680 | 2743 | * by the Linux game controller spec. This is important for the SDL2 |
| 2681 | 2744 | * library, which has a game controller database, which uses device ids |
| 2682 | 2745 | * in combination with version as a key. |
| 2683 | 2746 | */ |
| 2684 | − if (sc->quirks & DUALSHOCK4_CONTROLLER) | |
| 2747 | + if (sc->quirks & (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)) | |
| 2685 | 2748 | hdev->version |= 0x8000; |
| 2686 | 2749 | |
| 2687 | 2750 | ret = hid_hw_start(hdev, connect_mask); |
| @@ -2721,6 +2784,12 @@ static void sony_remove(struct hid_device *hdev) · 33 unmodified lines | ||
| 2721 | 2784 | if (sc->touchpad) |
| 2722 | 2785 | sony_unregister_touchpad(sc); |
| 2723 | 2786 | |
| 2787 | + if (sc->sensor_dev) | |
| 2788 | + sony_unregister_sensors(sc); | |
| 2789 | + | |
| 2790 | + if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) | |
| 2791 | + device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); | |
| 2792 | + | |
| 2724 | 2793 | sony_cancel_work_sync(sc); |
| 2725 | 2794 | |
| 2726 | 2795 | kfree(sc->output_report_dmabuf); |
| @@ -2736,47 +2805,32 @@ static void sony_remove(struct hid_device *hdev) · 9 unmodified lines | ||
| 2736 | 2805 | |
| 2737 | 2806 | static int sony_suspend(struct hid_device *hdev, pm_message_t message) |
| 2738 | 2807 | { |
| 2739 | − /* | |
| 2740 | − * On suspend save the current LED state, | |
| 2741 | − * stop running force-feedback and blank the LEDS. | |
| 2742 | − */ | |
| 2743 | − if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) { | |
| 2744 | − struct sony_sc *sc = hid_get_drvdata(hdev); | |
| 2745 | − | |
| 2746 | 2808 | #ifdef CONFIG_SONY_FF |
| 2747 | − sc->left = sc->right = 0; | |
| 2748 | −#endif | |
| 2749 | 2809 | |
| 2750 | − memcpy(sc->resume_led_state, sc->led_state, | |
| 2751 | − sizeof(sc->resume_led_state)); | |
| 2752 | − memset(sc->led_state, 0, sizeof(sc->led_state)); | |
| 2810 | + /* On suspend stop any running force-feedback events */ | |
| 2811 | + if (SONY_FF_SUPPORT) { | |
| 2812 | + struct sony_sc *sc = hid_get_drvdata(hdev); | |
| 2753 | 2813 | |
| 2814 | + sc->left = sc->right = 0; | |
| 2754 | 2815 | sony_send_output_report(sc); |
| 2755 | 2816 | } |
| 2756 | 2817 | |
| 2818 | +#endif | |
| 2757 | 2819 | return 0; |
| 2758 | 2820 | } |
| 2759 | 2821 | |
| 2760 | 2822 | static int sony_resume(struct hid_device *hdev) |
| 2761 | 2823 | { |
| 2762 | − /* Restore the state of controller LEDs on resume */ | |
| 2763 | − if (SONY_LED_SUPPORT) { | |
| 2764 | − struct sony_sc *sc = hid_get_drvdata(hdev); | |
| 2765 | − | |
| 2766 | − memcpy(sc->led_state, sc->resume_led_state, | |
| 2767 | − sizeof(sc->led_state)); | |
| 2768 | − | |
| 2769 | − /* | |
| 2770 | − * The Sixaxis and navigation controllers on USB need to be | |
| 2771 | − * reinitialized on resume or they won't behave properly. | |
| 2772 | − */ | |
| 2773 | − if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || | |
| 2774 | − (sc->quirks & NAVIGATION_CONTROLLER_USB)) { | |
| 2775 | − sixaxis_set_operational_usb(sc->hdev); | |
| 2776 | − sc->defer_initialization = 1; | |
| 2777 | − } | |
| 2824 | + struct sony_sc *sc = hid_get_drvdata(hdev); | |
| 2778 | 2825 | |
| 2779 | − sony_set_leds(sc); | |
| 2826 | + /* | |
| 2827 | + * The Sixaxis and navigation controllers on USB need to be | |
| 2828 | + * reinitialized on resume or they won't behave properly. | |
| 2829 | + */ | |
| 2830 | + if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || | |
| 2831 | + (sc->quirks & NAVIGATION_CONTROLLER_USB)) { | |
| 2832 | + sixaxis_set_operational_usb(sc->hdev); | |
| 2833 | + sc->defer_initialization = 1; | |
| 2780 | 2834 | } |
| 2781 | 2835 | |
| 2782 | 2836 | return 0; |
| @@ -2828,7 +2882,7 @@ static const struct hid_device_id sony_devices[] = { · 45 unmodified lines | ||
| 2828 | 2882 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), |
| 2829 | 2883 | .driver_data = DUALSHOCK4_CONTROLLER_BT }, |
| 2830 | 2884 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE), |
| 2831 | − .driver_data = DUALSHOCK4_CONTROLLER_USB }, | |
| 2885 | + .driver_data = DUALSHOCK4_DONGLE }, | |
| 2832 | 2886 | /* Nyko Core Controller for PS3 */ |
| 2833 | 2887 | { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER), |
| 2834 | 2888 | .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER }, |
| @@ -508,66 +508,6 @@ static int i2c_hid_get_report_length(struct hid_report *report) · 507 unmodified lines | ||
| 508 | 508 | report->device->report_enum[report->type].numbered + 2; |
| 509 | 509 | } |
| 510 | 510 | |
| 511 | −static void i2c_hid_init_report(struct hid_report *report, u8 *buffer, | |
| 512 | − size_t bufsize) | |
| 513 | −{ | |
| 514 | − struct hid_device *hid = report->device; | |
| 515 | − struct i2c_client *client = hid->driver_data; | |
| 516 | − struct i2c_hid *ihid = i2c_get_clientdata(client); | |
| 517 | − unsigned int size, ret_size; | |
| 518 | − | |
| 519 | − size = i2c_hid_get_report_length(report); | |
| 520 | − if (i2c_hid_get_report(client, | |
| 521 | − report->type == HID_FEATURE_REPORT ? 0x03 : 0x01, | |
| 522 | − report->id, buffer, size)) | |
| 523 | − return; | |
| 524 | − | |
| 525 | − i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, buffer); | |
| 526 | − | |
| 527 | − ret_size = buffer[0] | (buffer[1] << 8); | |
| 528 | − | |
| 529 | − if (ret_size != size) { | |
| 530 | − dev_err(&client->dev, "error in %s size:%d / ret_size:%d\n", | |
| 531 | − __func__, size, ret_size); | |
| 532 | − return; | |
| 533 | − } | |
| 534 | − | |
| 535 | − /* hid->driver_lock is held as we are in probe function, | |
| 536 | − * we just need to setup the input fields, so using | |
| 537 | − * hid_report_raw_event is safe. */ | |
| 538 | − hid_report_raw_event(hid, report->type, buffer + 2, size - 2, 1); | |
| 539 | −} | |
| 540 | − | |
| 541 | −/* | |
| 542 | − * Initialize all reports | |
| 543 | − */ | |
| 544 | −static void i2c_hid_init_reports(struct hid_device *hid) | |
| 545 | −{ | |
| 546 | − struct hid_report *report; | |
| 547 | − struct i2c_client *client = hid->driver_data; | |
| 548 | − struct i2c_hid *ihid = i2c_get_clientdata(client); | |
| 549 | − u8 *inbuf = kzalloc(ihid->bufsize, GFP_KERNEL); | |
| 550 | − | |
| 551 | − if (!inbuf) { | |
| 552 | − dev_err(&client->dev, "can not retrieve initial reports\n"); | |
| 553 | − return; | |
| 554 | − } | |
| 555 | − | |
| 556 | − /* | |
| 557 | − * The device must be powered on while we fetch initial reports | |
| 558 | − * from it. | |
| 559 | − */ | |
| 560 | − pm_runtime_get_sync(&client->dev); | |
| 561 | − | |
| 562 | − list_for_each_entry(report, | |
| 563 | − &hid->report_enum[HID_FEATURE_REPORT].report_list, list) | |
| 564 | − i2c_hid_init_report(report, inbuf, ihid->bufsize); | |
| 565 | − | |
| 566 | − pm_runtime_put(&client->dev); | |
| 567 | − | |
| 568 | − kfree(inbuf); | |
| 569 | −} | |
| 570 | − | |
| 571 | 511 | /* |
| 572 | 512 | * Traverse the supplied list of reports and find the longest |
| 573 | 513 | */ |
| @@ -789,9 +729,6 @@ static int i2c_hid_start(struct hid_device *hid) · 215 unmodified lines | ||
| 789 | 729 | return ret; |
| 790 | 730 | } |
| 791 | 731 | |
| 792 | − if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS)) | |
| 793 | − i2c_hid_init_reports(hid); | |
| 794 | − | |
| 795 | 732 | return 0; |
| 796 | 733 | } |
| 797 | 734 | |
| @@ -994,6 +931,11 @@ static int i2c_hid_of_probe(struct i2c_client *client, · 196 unmodified lines | ||
| 994 | 931 | } |
| 995 | 932 | pdata->hid_descriptor_address = val; |
| 996 | 933 | |
| 934 | + ret = of_property_read_u32(dev->of_node, "post-power-on-delay-ms", | |
| 935 | + &val); | |
| 936 | + if (!ret) | |
| 937 | + pdata->post_power_delay_ms = val; | |
| 938 | + | |
| 997 | 939 | return 0; |
| 998 | 940 | } |
| 999 | 941 | |
| @@ -1053,6 +995,24 @@ static int i2c_hid_probe(struct i2c_client *client, · 53 unmodified lines | ||
| 1053 | 995 | ihid->pdata = *platform_data; |
| 1054 | 996 | } |
| 1055 | 997 | |
| 998 | + ihid->pdata.supply = devm_regulator_get(&client->dev, "vdd"); | |
| 999 | + if (IS_ERR(ihid->pdata.supply)) { | |
| 1000 | + ret = PTR_ERR(ihid->pdata.supply); | |
| 1001 | + if (ret != -EPROBE_DEFER) | |
| 1002 | + dev_err(&client->dev, "Failed to get regulator: %d\n", | |
| 1003 | + ret); | |
| 1004 | + goto err; | |
| 1005 | + } | |
| 1006 | + | |
| 1007 | + ret = regulator_enable(ihid->pdata.supply); | |
| 1008 | + if (ret < 0) { | |
| 1009 | + dev_err(&client->dev, "Failed to enable regulator: %d\n", | |
| 1010 | + ret); | |
| 1011 | + goto err; | |
| 1012 | + } | |
| 1013 | + if (ihid->pdata.post_power_delay_ms) | |
| 1014 | + msleep(ihid->pdata.post_power_delay_ms); | |
| 1015 | + | |
| 1056 | 1016 | i2c_set_clientdata(client, ihid); |
| 1057 | 1017 | |
| 1058 | 1018 | ihid->client = client; |
| @@ -1068,7 +1028,7 @@ static int i2c_hid_probe(struct i2c_client *client, · 9 unmodified lines | ||
| 1068 | 1028 | * real computation later. */ |
| 1069 | 1029 | ret = i2c_hid_alloc_buffers(ihid, HID_MIN_BUFFER_SIZE); |
| 1070 | 1030 | if (ret < 0) |
| 1071 | − goto err; | |
| 1031 | + goto err_regulator; | |
| 1072 | 1032 | |
| 1073 | 1033 | pm_runtime_get_noresume(&client->dev); |
| 1074 | 1034 | pm_runtime_set_active(&client->dev); |
| @@ -1125,6 +1085,9 @@ err_pm: · 50 unmodified lines | ||
| 1125 | 1085 | pm_runtime_put_noidle(&client->dev); |
| 1126 | 1086 | pm_runtime_disable(&client->dev); |
| 1127 | 1087 | |
| 1088 | +err_regulator: | |
| 1089 | + regulator_disable(ihid->pdata.supply); | |
| 1090 | + | |
| 1128 | 1091 | err: |
| 1129 | 1092 | i2c_hid_free_buffers(ihid); |
| 1130 | 1093 | kfree(ihid); |
| @@ -1149,6 +1112,8 @@ static int i2c_hid_remove(struct i2c_client *client) · 18 unmodified lines | ||
| 1149 | 1112 | if (ihid->bufsize) |
| 1150 | 1113 | i2c_hid_free_buffers(ihid); |
| 1151 | 1114 | |
| 1115 | + regulator_disable(ihid->pdata.supply); | |
| 1116 | + | |
| 1152 | 1117 | kfree(ihid); |
| 1153 | 1118 | |
| 1154 | 1119 | return 0; |
| @@ -1199,6 +1164,10 @@ static int i2c_hid_suspend(struct device *dev) · 44 unmodified lines | ||
| 1199 | 1164 | else |
| 1200 | 1165 | hid_warn(hid, "Failed to enable irq wake: %d\n", |
| 1201 | 1166 | wake_status); |
| 1167 | + } else { | |
| 1168 | + ret = regulator_disable(ihid->pdata.supply); | |
| 1169 | + if (ret < 0) | |
| 1170 | + hid_warn(hid, "Failed to disable supply: %d\n", ret); | |
| 1202 | 1171 | } |
| 1203 | 1172 | |
| 1204 | 1173 | return 0; |
| @@ -1212,7 +1181,13 @@ static int i2c_hid_resume(struct device *dev) · 7 unmodified lines | ||
| 1212 | 1181 | struct hid_device *hid = ihid->hid; |
| 1213 | 1182 | int wake_status; |
| 1214 | 1183 | |
| 1215 | − if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) { | |
| 1184 | + if (!device_may_wakeup(&client->dev)) { | |
| 1185 | + ret = regulator_enable(ihid->pdata.supply); | |
| 1186 | + if (ret < 0) | |
| 1187 | + hid_warn(hid, "Failed to enable supply: %d\n", ret); | |
| 1188 | + if (ihid->pdata.post_power_delay_ms) | |
| 1189 | + msleep(ihid->pdata.post_power_delay_ms); | |
| 1190 | + } else if (ihid->irq_wake_enabled) { | |
| 1216 | 1191 | wake_status = disable_irq_wake(client->irq); |
| 1217 | 1192 | if (!wake_status) |
| 1218 | 1193 | ihid->irq_wake_enabled = false; |
| @@ -52,6 +52,10 @@ static unsigned int hid_mousepoll_interval; · 51 unmodified lines | ||
| 52 | 52 | module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); |
| 53 | 53 | MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); |
| 54 | 54 | |
| 55 | +static unsigned int hid_jspoll_interval; | |
| 56 | +module_param_named(jspoll, hid_jspoll_interval, uint, 0644); | |
| 57 | +MODULE_PARM_DESC(jspoll, "Polling interval of joysticks"); | |
| 58 | + | |
| 55 | 59 | static unsigned int ignoreled; |
| 56 | 60 | module_param_named(ignoreled, ignoreled, uint, 0644); |
| 57 | 61 | MODULE_PARM_DESC(ignoreled, "Autosuspend with active leds"); |
| @@ -753,11 +757,9 @@ void usbhid_init_reports(struct hid_device *hid) · 695 unmodified lines | ||
| 753 | 757 | struct hid_report_enum *report_enum; |
| 754 | 758 | int err, ret; |
| 755 | 759 | |
| 756 | − if (!(hid->quirks & HID_QUIRK_NO_INIT_INPUT_REPORTS)) { | |
| 757 | − report_enum = &hid->report_enum[HID_INPUT_REPORT]; | |
| 758 | − list_for_each_entry(report, &report_enum->report_list, list) | |
| 759 | − usbhid_submit_report(hid, report, USB_DIR_IN); | |
| 760 | − } | |
| 760 | + report_enum = &hid->report_enum[HID_INPUT_REPORT]; | |
| 761 | + list_for_each_entry(report, &report_enum->report_list, list) | |
| 762 | + usbhid_submit_report(hid, report, USB_DIR_IN); | |
| 761 | 763 | |
| 762 | 764 | report_enum = &hid->report_enum[HID_FEATURE_REPORT]; |
| 763 | 765 | list_for_each_entry(report, &report_enum->report_list, list) |
| @@ -1004,10 +1006,9 @@ static int usbhid_parse(struct hid_device *hid) · 240 unmodified lines | ||
| 1004 | 1006 | return -EINVAL; |
| 1005 | 1007 | } |
| 1006 | 1008 | |
| 1007 | − if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) { | |
| 1008 | − dbg_hid("couldn't allocate rdesc memory\n"); | |
| 1009 | + rdesc = kmalloc(rsize, GFP_KERNEL); | |
| 1010 | + if (!rdesc) | |
| 1009 | 1011 | return -ENOMEM; |
| 1010 | − } | |
| 1011 | 1012 | |
| 1012 | 1013 | hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); |
| 1013 | 1014 | |
| @@ -1077,13 +1078,21 @@ static int usbhid_start(struct hid_device *hid) · 63 unmodified lines | ||
| 1077 | 1078 | if (hid->quirks & HID_QUIRK_FULLSPEED_INTERVAL && |
| 1078 | 1079 | dev->speed == USB_SPEED_HIGH) { |
| 1079 | 1080 | interval = fls(endpoint->bInterval*8); |
| 1080 | − printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n", | |
| 1081 | − hid->name, endpoint->bInterval, interval); | |
| 1081 | + pr_info("%s: Fixing fullspeed to highspeed interval: %d -> %d\n", | |
| 1082 | + hid->name, endpoint->bInterval, interval); | |
| 1082 | 1083 | } |
| 1083 | 1084 | |
| 1084 | − /* Change the polling interval of mice. */ | |
| 1085 | − if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) | |
| 1086 | − interval = hid_mousepoll_interval; | |
| 1085 | + /* Change the polling interval of mice and joysticks. */ | |
| 1086 | + switch (hid->collection->usage) { | |
| 1087 | + case HID_GD_MOUSE: | |
| 1088 | + if (hid_mousepoll_interval > 0) | |
| 1089 | + interval = hid_mousepoll_interval; | |
| 1090 | + break; | |
| 1091 | + case HID_GD_JOYSTICK: | |
| 1092 | + if (hid_jspoll_interval > 0) | |
| 1093 | + interval = hid_jspoll_interval; | |
| 1094 | + break; | |
| 1095 | + } | |
| 1087 | 1096 | |
| 1088 | 1097 | ret = -ENOMEM; |
| 1089 | 1098 | if (usb_endpoint_dir_in(endpoint)) { |
| @@ -1120,9 +1129,6 @@ static int usbhid_start(struct hid_device *hid) · 30 unmodified lines | ||
| 1120 | 1129 | usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; |
| 1121 | 1130 | usbhid->urbctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 1122 | 1131 | |
| 1123 | − if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS)) | |
| 1124 | − usbhid_init_reports(hid); | |
| 1125 | − | |
| 1126 | 1132 | set_bit(HID_STARTED, &usbhid->iofl); |
| 1127 | 1133 | |
| 1128 | 1134 | if (hid->quirks & HID_QUIRK_ALWAYS_POLL) { |
| @@ -1456,10 +1462,9 @@ static int hid_post_reset(struct usb_interface *intf) · 327 unmodified lines | ||
| 1456 | 1462 | * the size of the HID report descriptor has not changed. |
| 1457 | 1463 | */ |
| 1458 | 1464 | rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL); |
| 1459 | − if (!rdesc) { | |
| 1460 | − dbg_hid("couldn't allocate rdesc memory (post_reset)\n"); | |
| 1465 | + if (!rdesc) | |
| 1461 | 1466 | return -ENOMEM; |
| 1462 | − } | |
| 1467 | + | |
| 1463 | 1468 | status = hid_get_class_descriptor(dev, |
| 1464 | 1469 | interface->desc.bInterfaceNumber, |
| 1465 | 1470 | HID_DT_REPORT, rdesc, hid->dev_rsize); |
| @@ -1637,7 +1642,7 @@ static int __init hid_init(void) · 171 unmodified lines | ||
| 1637 | 1642 | retval = usb_register(&hid_driver); |
| 1638 | 1643 | if (retval) |
| 1639 | 1644 | goto usb_register_fail; |
| 1640 | − printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); | |
| 1645 | + pr_info(KBUILD_MODNAME ": " DRIVER_DESC "\n"); | |
| 1641 | 1646 | |
| 1642 | 1647 | return 0; |
| 1643 | 1648 | usb_register_fail: |
| @@ -65,6 +65,7 @@ static const struct hid_blacklist { · 64 unmodified lines | ||
| 65 | 65 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, |
| 66 | 66 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET }, |
| 67 | 67 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692, HID_QUIRK_NOGET }, |
| 68 | + { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS1758, HID_QUIRK_NOGET }, | |
| 68 | 69 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET }, |
| 69 | 70 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, |
| 70 | 71 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, |
| @@ -161,10 +162,11 @@ static const struct hid_blacklist { · 90 unmodified lines | ||
| 161 | 162 | { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, |
| 162 | 163 | { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS }, |
| 163 | 164 | { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS }, |
| 164 | − { USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096, HID_QUIRK_NO_INIT_INPUT_REPORTS }, | |
| 165 | + { USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096, HID_QUIRK_NO_INIT_REPORTS }, | |
| 165 | 166 | { USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD, HID_QUIRK_MULTI_INPUT }, |
| 166 | 167 | { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES, HID_QUIRK_MULTI_INPUT }, |
| 167 | 168 | { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES, HID_QUIRK_MULTI_INPUT }, |
| 169 | + { USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI, HID_QUIRK_MULTI_INPUT }, | |
| 168 | 170 | |
| 169 | 171 | { 0, 0 } |
| 170 | 172 | }; |
| @@ -240,10 +242,8 @@ static int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, · 69 unmodified lines | ||
| 240 | 242 | } |
| 241 | 243 | |
| 242 | 244 | q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL); |
| 243 | − if (!q_new) { | |
| 244 | − dbg_hid("Could not allocate quirks_list_struct\n"); | |
| 245 | + if (!q_new) | |
| 245 | 246 | return -ENOMEM; |
| 246 | − } | |
| 247 | 247 | |
| 248 | 248 | q_new->hid_bl_item.idVendor = idVendor; |
| 249 | 249 | q_new->hid_bl_item.idProduct = idProduct; |
| @@ -309,10 +309,9 @@ int usbhid_quirks_init(char **quirks_param) · 59 unmodified lines | ||
| 309 | 309 | &idVendor, &idProduct, &quirks); |
| 310 | 310 | |
| 311 | 311 | if (m != 3 || |
| 312 | − usbhid_modify_dquirk(idVendor, idProduct, quirks) != 0) { | |
| 313 | − printk(KERN_WARNING | |
| 314 | − "Could not parse HID quirk module param %s\n", | |
| 315 | − quirks_param[n]); | |
| 312 | + usbhid_modify_dquirk(idVendor, idProduct, quirks) != 0) { | |
| 313 | + pr_warn("Could not parse HID quirk module param %s\n", | |
| 314 | + quirks_param[n]); | |
| 316 | 315 | } |
| 317 | 316 | } |
| 318 | 317 | |
| @@ -47,16 +47,6 @@ · 46 unmodified lines | ||
| 47 | 47 | #endif |
| 48 | 48 | #define HIDDEV_BUFFER_SIZE 2048 |
| 49 | 49 | |
| 50 | −struct hiddev { | |
| 51 | − int exist; | |
| 52 | − int open; | |
| 53 | − struct mutex existancelock; | |
| 54 | − wait_queue_head_t wait; | |
| 55 | − struct hid_device *hid; | |
| 56 | − struct list_head list; | |
| 57 | − spinlock_t list_lock; | |
| 58 | −}; | |
| 59 | − | |
| 60 | 50 | struct hiddev_list { |
| 61 | 51 | struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE]; |
| 62 | 52 | int head; |
| @@ -690,6 +680,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 627 unmodified lines | ||
| 690 | 680 | |
| 691 | 681 | case HIDIOCINITREPORT: |
| 692 | 682 | usbhid_init_reports(hid); |
| 683 | + hiddev->initialized = true; | |
| 693 | 684 | r = 0; |
| 694 | 685 | break; |
| 695 | 686 | |
| @@ -791,6 +782,10 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 95 unmodified lines | ||
| 791 | 782 | case HIDIOCGUSAGES: |
| 792 | 783 | case HIDIOCSUSAGES: |
| 793 | 784 | case HIDIOCGCOLLECTIONINDEX: |
| 785 | + if (!hiddev->initialized) { | |
| 786 | + usbhid_init_reports(hid); | |
| 787 | + hiddev->initialized = true; | |
| 788 | + } | |
| 794 | 789 | r = hiddev_ioctl_usage(hiddev, cmd, user_arg); |
| 795 | 790 | break; |
| 796 | 791 | |
| @@ -911,6 +906,15 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) · 114 unmodified lines | ||
| 911 | 906 | kfree(hiddev); |
| 912 | 907 | return -1; |
| 913 | 908 | } |
| 909 | + | |
| 910 | + /* | |
| 911 | + * If HID_QUIRK_NO_INIT_REPORTS is set, make sure we don't initialize | |
| 912 | + * the reports. | |
| 913 | + */ | |
| 914 | + hiddev->initialized = hid->quirks & HID_QUIRK_NO_INIT_REPORTS; | |
| 915 | + | |
| 916 | + hiddev->minor = usbhid->intf->minor; | |
| 917 | + | |
| 914 | 918 | return 0; |
| 915 | 919 | } |
| 916 | 920 | |
| @@ -110,6 +110,7 @@ enum wacom_worker { · 109 unmodified lines | ||
| 110 | 110 | WACOM_WORKER_WIRELESS, |
| 111 | 111 | WACOM_WORKER_BATTERY, |
| 112 | 112 | WACOM_WORKER_REMOTE, |
| 113 | + WACOM_WORKER_MODE_CHANGE, | |
| 113 | 114 | }; |
| 114 | 115 | |
| 115 | 116 | struct wacom; |
| @@ -167,6 +168,7 @@ struct wacom { · 51 unmodified lines | ||
| 167 | 168 | struct work_struct remote_work; |
| 168 | 169 | struct delayed_work init_work; |
| 169 | 170 | struct wacom_remote *remote; |
| 171 | + struct work_struct mode_change_work; | |
| 170 | 172 | bool generic_has_leds; |
| 171 | 173 | struct wacom_leds { |
| 172 | 174 | struct wacom_group_leds *groups; |
| @@ -196,6 +198,9 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac, · 23 unmodified lines | ||
| 196 | 198 | case WACOM_WORKER_REMOTE: |
| 197 | 199 | schedule_work(&wacom->remote_work); |
| 198 | 200 | break; |
| 201 | + case WACOM_WORKER_MODE_CHANGE: | |
| 202 | + schedule_work(&wacom->mode_change_work); | |
| 203 | + break; | |
| 199 | 204 | } |
| 200 | 205 | } |
| 201 | 206 | |
| @@ -325,6 +325,13 @@ static void wacom_post_parse_hid(struct hid_device *hdev, · 324 unmodified lines | ||
| 325 | 325 | |
| 326 | 326 | if (features->type == HID_GENERIC) { |
| 327 | 327 | /* Any last-minute generic device setup */ |
| 328 | + if (wacom_wac->has_mode_change) { | |
| 329 | + if (wacom_wac->is_direct_mode) | |
| 330 | + features->device_type |= WACOM_DEVICETYPE_DIRECT; | |
| 331 | + else | |
| 332 | + features->device_type &= ~WACOM_DEVICETYPE_DIRECT; | |
| 333 | + } | |
| 334 | + | |
| 328 | 335 | if (features->touch_max > 1) { |
| 329 | 336 | if (features->device_type & WACOM_DEVICETYPE_DIRECT) |
| 330 | 337 | input_mt_init_slots(wacom_wac->touch_input, |
| @@ -2093,8 +2100,10 @@ static void wacom_set_shared_values(struct wacom_wac *wacom_wac) · 1762 unmodified lines | ||
| 2093 | 2100 | wacom_wac->shared->touch_input = wacom_wac->touch_input; |
| 2094 | 2101 | } |
| 2095 | 2102 | |
| 2096 | − if (wacom_wac->has_mute_touch_switch) | |
| 2103 | + if (wacom_wac->has_mute_touch_switch) { | |
| 2097 | 2104 | wacom_wac->shared->has_mute_touch_switch = true; |
| 2105 | + wacom_wac->shared->is_touch_on = true; | |
| 2106 | + } | |
| 2098 | 2107 | |
| 2099 | 2108 | if (wacom_wac->shared->has_mute_touch_switch && |
| 2100 | 2109 | wacom_wac->shared->touch_input) { |
| @@ -2490,6 +2499,46 @@ static void wacom_remote_work(struct work_struct *work) · 389 unmodified lines | ||
| 2490 | 2499 | } |
| 2491 | 2500 | } |
| 2492 | 2501 | |
| 2502 | +static void wacom_mode_change_work(struct work_struct *work) | |
| 2503 | +{ | |
| 2504 | + struct wacom *wacom = container_of(work, struct wacom, mode_change_work); | |
| 2505 | + struct wacom_shared *shared = wacom->wacom_wac.shared; | |
| 2506 | + struct wacom *wacom1 = NULL; | |
| 2507 | + struct wacom *wacom2 = NULL; | |
| 2508 | + bool is_direct = wacom->wacom_wac.is_direct_mode; | |
| 2509 | + int error = 0; | |
| 2510 | + | |
| 2511 | + if (shared->pen) { | |
| 2512 | + wacom1 = hid_get_drvdata(shared->pen); | |
| 2513 | + wacom_release_resources(wacom1); | |
| 2514 | + hid_hw_stop(wacom1->hdev); | |
| 2515 | + wacom1->wacom_wac.has_mode_change = true; | |
| 2516 | + wacom1->wacom_wac.is_direct_mode = is_direct; | |
| 2517 | + } | |
| 2518 | + | |
| 2519 | + if (shared->touch) { | |
| 2520 | + wacom2 = hid_get_drvdata(shared->touch); | |
| 2521 | + wacom_release_resources(wacom2); | |
| 2522 | + hid_hw_stop(wacom2->hdev); | |
| 2523 | + wacom2->wacom_wac.has_mode_change = true; | |
| 2524 | + wacom2->wacom_wac.is_direct_mode = is_direct; | |
| 2525 | + } | |
| 2526 | + | |
| 2527 | + if (wacom1) { | |
| 2528 | + error = wacom_parse_and_register(wacom1, false); | |
| 2529 | + if (error) | |
| 2530 | + return; | |
| 2531 | + } | |
| 2532 | + | |
| 2533 | + if (wacom2) { | |
| 2534 | + error = wacom_parse_and_register(wacom2, false); | |
| 2535 | + if (error) | |
| 2536 | + return; | |
| 2537 | + } | |
| 2538 | + | |
| 2539 | + return; | |
| 2540 | +} | |
| 2541 | + | |
| 2493 | 2542 | static int wacom_probe(struct hid_device *hdev, |
| 2494 | 2543 | const struct hid_device_id *id) |
| 2495 | 2544 | { |
| @@ -2534,6 +2583,7 @@ static int wacom_probe(struct hid_device *hdev, · 38 unmodified lines | ||
| 2534 | 2583 | INIT_WORK(&wacom->wireless_work, wacom_wireless_work); |
| 2535 | 2584 | INIT_WORK(&wacom->battery_work, wacom_battery_work); |
| 2536 | 2585 | INIT_WORK(&wacom->remote_work, wacom_remote_work); |
| 2586 | + INIT_WORK(&wacom->mode_change_work, wacom_mode_change_work); | |
| 2537 | 2587 | |
| 2538 | 2588 | /* ask for the report descriptor to be loaded by HID */ |
| 2539 | 2589 | error = hid_parse(hdev); |
| @@ -2576,6 +2626,7 @@ static void wacom_remove(struct hid_device *hdev) · 36 unmodified lines | ||
| 2576 | 2626 | cancel_work_sync(&wacom->wireless_work); |
| 2577 | 2627 | cancel_work_sync(&wacom->battery_work); |
| 2578 | 2628 | cancel_work_sync(&wacom->remote_work); |
| 2629 | + cancel_work_sync(&wacom->mode_change_work); | |
| 2579 | 2630 | if (hdev->bus == BUS_BLUETOOTH) |
| 2580 | 2631 | device_remove_file(&hdev->dev, &dev_attr_speed); |
| 2581 | 2632 | |
| @@ -773,131 +773,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) · 772 unmodified lines | ||
| 773 | 773 | return 0; |
| 774 | 774 | } |
| 775 | 775 | |
| 776 | −static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) | |
| 777 | −{ | |
| 778 | − unsigned char *data = wacom_wac->data; | |
| 779 | − struct input_dev *input; | |
| 780 | − struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); | |
| 781 | − struct wacom_remote *remote = wacom->remote; | |
| 782 | − int bat_charging, bat_percent, touch_ring_mode; | |
| 783 | − __u32 serial; | |
| 784 | − int i, index = -1; | |
| 785 | − unsigned long flags; | |
| 786 | − | |
| 787 | − if (data[0] != WACOM_REPORT_REMOTE) { | |
| 788 | − hid_dbg(wacom->hdev, "%s: received unknown report #%d", | |
| 789 | − __func__, data[0]); | |
| 790 | − return 0; | |
| 791 | − } | |
| 792 | − | |
| 793 | − serial = data[3] + (data[4] << 8) + (data[5] << 16); | |
| 794 | − wacom_wac->id[0] = PAD_DEVICE_ID; | |
| 795 | − | |
| 796 | − spin_lock_irqsave(&remote->remote_lock, flags); | |
| 797 | − | |
| 798 | − for (i = 0; i < WACOM_MAX_REMOTES; i++) { | |
| 799 | − if (remote->remotes[i].serial == serial) { | |
| 800 | − index = i; | |
| 801 | − break; | |
| 802 | − } | |
| 803 | − } | |
| 804 | − | |
| 805 | − if (index < 0 || !remote->remotes[index].registered) | |
| 806 | − goto out; | |
| 807 | − | |
| 808 | − input = remote->remotes[index].input; | |
| 809 | − | |
| 810 | − input_report_key(input, BTN_0, (data[9] & 0x01)); | |
| 811 | − input_report_key(input, BTN_1, (data[9] & 0x02)); | |
| 812 | − input_report_key(input, BTN_2, (data[9] & 0x04)); | |
| 813 | − input_report_key(input, BTN_3, (data[9] & 0x08)); | |
| 814 | − input_report_key(input, BTN_4, (data[9] & 0x10)); | |
| 815 | − input_report_key(input, BTN_5, (data[9] & 0x20)); | |
| 816 | − input_report_key(input, BTN_6, (data[9] & 0x40)); | |
| 817 | − input_report_key(input, BTN_7, (data[9] & 0x80)); | |
| 818 | − | |
| 819 | − input_report_key(input, BTN_8, (data[10] & 0x01)); | |
| 820 | − input_report_key(input, BTN_9, (data[10] & 0x02)); | |
| 821 | − input_report_key(input, BTN_A, (data[10] & 0x04)); | |
| 822 | − input_report_key(input, BTN_B, (data[10] & 0x08)); | |
| 823 | − input_report_key(input, BTN_C, (data[10] & 0x10)); | |
| 824 | − input_report_key(input, BTN_X, (data[10] & 0x20)); | |
| 825 | − input_report_key(input, BTN_Y, (data[10] & 0x40)); | |
| 826 | − input_report_key(input, BTN_Z, (data[10] & 0x80)); | |
| 827 | − | |
| 828 | − input_report_key(input, BTN_BASE, (data[11] & 0x01)); | |
| 829 | − input_report_key(input, BTN_BASE2, (data[11] & 0x02)); | |
| 830 | − | |
| 831 | − if (data[12] & 0x80) | |
| 832 | − input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f)); | |
| 833 | − else | |
| 834 | − input_report_abs(input, ABS_WHEEL, 0); | |
| 835 | − | |
| 836 | − bat_percent = data[7] & 0x7f; | |
| 837 | − bat_charging = !!(data[7] & 0x80); | |
| 838 | − | |
| 839 | − if (data[9] | data[10] | (data[11] & 0x03) | data[12]) | |
| 840 | − input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); | |
| 841 | − else | |
| 842 | − input_report_abs(input, ABS_MISC, 0); | |
| 843 | − | |
| 844 | − input_event(input, EV_MSC, MSC_SERIAL, serial); | |
| 845 | − | |
| 846 | − input_sync(input); | |
| 847 | − | |
| 848 | − /*Which mode select (LED light) is currently on?*/ | |
| 849 | − touch_ring_mode = (data[11] & 0xC0) >> 6; | |
| 850 | − | |
| 851 | − for (i = 0; i < WACOM_MAX_REMOTES; i++) { | |
| 852 | − if (remote->remotes[i].serial == serial) | |
| 853 | − wacom->led.groups[i].select = touch_ring_mode; | |
| 854 | − } | |
| 855 | − | |
| 856 | − __wacom_notify_battery(&remote->remotes[index].battery, bat_percent, | |
| 857 | − bat_charging, 1, bat_charging); | |
| 858 | − | |
| 859 | −out: | |
| 860 | − spin_unlock_irqrestore(&remote->remote_lock, flags); | |
| 861 | − return 0; | |
| 862 | −} | |
| 863 | − | |
| 864 | −static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) | |
| 865 | −{ | |
| 866 | − struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); | |
| 867 | − unsigned char *data = wacom_wac->data; | |
| 868 | − struct wacom_remote *remote = wacom->remote; | |
| 869 | − struct wacom_remote_data remote_data; | |
| 870 | − unsigned long flags; | |
| 871 | − int i, ret; | |
| 872 | − | |
| 873 | − if (data[0] != WACOM_REPORT_DEVICE_LIST) | |
| 874 | − return; | |
| 875 | − | |
| 876 | − memset(&remote_data, 0, sizeof(struct wacom_remote_data)); | |
| 877 | − | |
| 878 | − for (i = 0; i < WACOM_MAX_REMOTES; i++) { | |
| 879 | − int j = i * 6; | |
| 880 | − int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4]; | |
| 881 | − bool connected = data[j+2]; | |
| 882 | − | |
| 883 | − remote_data.remote[i].serial = serial; | |
| 884 | − remote_data.remote[i].connected = connected; | |
| 885 | − } | |
| 886 | − | |
| 887 | − spin_lock_irqsave(&remote->remote_lock, flags); | |
| 888 | − | |
| 889 | − ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data)); | |
| 890 | − if (ret != sizeof(remote_data)) { | |
| 891 | − spin_unlock_irqrestore(&remote->remote_lock, flags); | |
| 892 | − hid_err(wacom->hdev, "Can't queue Remote status event.\n"); | |
| 893 | − return; | |
| 894 | − } | |
| 895 | − | |
| 896 | − spin_unlock_irqrestore(&remote->remote_lock, flags); | |
| 897 | − | |
| 898 | − wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE); | |
| 899 | −} | |
| 900 | − | |
| 901 | 776 | static inline bool report_touch_events(struct wacom_wac *wacom) |
| 902 | 777 | { |
| 903 | 778 | return (touch_arbitration ? !wacom->shared->stylus_in_proximity : 1); |
| @@ -1116,6 +991,131 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) · 212 unmodified lines | ||
| 1116 | 991 | return 0; |
| 1117 | 992 | } |
| 1118 | 993 | |
| 994 | +static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) | |
| 995 | +{ | |
| 996 | + unsigned char *data = wacom_wac->data; | |
| 997 | + struct input_dev *input; | |
| 998 | + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); | |
| 999 | + struct wacom_remote *remote = wacom->remote; | |
| 1000 | + int bat_charging, bat_percent, touch_ring_mode; | |
| 1001 | + __u32 serial; | |
| 1002 | + int i, index = -1; | |
| 1003 | + unsigned long flags; | |
| 1004 | + | |
| 1005 | + if (data[0] != WACOM_REPORT_REMOTE) { | |
| 1006 | + hid_dbg(wacom->hdev, "%s: received unknown report #%d", | |
| 1007 | + __func__, data[0]); | |
| 1008 | + return 0; | |
| 1009 | + } | |
| 1010 | + | |
| 1011 | + serial = data[3] + (data[4] << 8) + (data[5] << 16); | |
| 1012 | + wacom_wac->id[0] = PAD_DEVICE_ID; | |
| 1013 | + | |
| 1014 | + spin_lock_irqsave(&remote->remote_lock, flags); | |
| 1015 | + | |
| 1016 | + for (i = 0; i < WACOM_MAX_REMOTES; i++) { | |
| 1017 | + if (remote->remotes[i].serial == serial) { | |
| 1018 | + index = i; | |
| 1019 | + break; | |
| 1020 | + } | |
| 1021 | + } | |
| 1022 | + | |
| 1023 | + if (index < 0 || !remote->remotes[index].registered) | |
| 1024 | + goto out; | |
| 1025 | + | |
| 1026 | + input = remote->remotes[index].input; | |
| 1027 | + | |
| 1028 | + input_report_key(input, BTN_0, (data[9] & 0x01)); | |
| 1029 | + input_report_key(input, BTN_1, (data[9] & 0x02)); | |
| 1030 | + input_report_key(input, BTN_2, (data[9] & 0x04)); | |
| 1031 | + input_report_key(input, BTN_3, (data[9] & 0x08)); | |
| 1032 | + input_report_key(input, BTN_4, (data[9] & 0x10)); | |
| 1033 | + input_report_key(input, BTN_5, (data[9] & 0x20)); | |
| 1034 | + input_report_key(input, BTN_6, (data[9] & 0x40)); | |
| 1035 | + input_report_key(input, BTN_7, (data[9] & 0x80)); | |
| 1036 | + | |
| 1037 | + input_report_key(input, BTN_8, (data[10] & 0x01)); | |
| 1038 | + input_report_key(input, BTN_9, (data[10] & 0x02)); | |
| 1039 | + input_report_key(input, BTN_A, (data[10] & 0x04)); | |
| 1040 | + input_report_key(input, BTN_B, (data[10] & 0x08)); | |
| 1041 | + input_report_key(input, BTN_C, (data[10] & 0x10)); | |
| 1042 | + input_report_key(input, BTN_X, (data[10] & 0x20)); | |
| 1043 | + input_report_key(input, BTN_Y, (data[10] & 0x40)); | |
| 1044 | + input_report_key(input, BTN_Z, (data[10] & 0x80)); | |
| 1045 | + | |
| 1046 | + input_report_key(input, BTN_BASE, (data[11] & 0x01)); | |
| 1047 | + input_report_key(input, BTN_BASE2, (data[11] & 0x02)); | |
| 1048 | + | |
| 1049 | + if (data[12] & 0x80) | |
| 1050 | + input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f)); | |
| 1051 | + else | |
| 1052 | + input_report_abs(input, ABS_WHEEL, 0); | |
| 1053 | + | |
| 1054 | + bat_percent = data[7] & 0x7f; | |
| 1055 | + bat_charging = !!(data[7] & 0x80); | |
| 1056 | + | |
| 1057 | + if (data[9] | data[10] | (data[11] & 0x03) | data[12]) | |
| 1058 | + input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); | |
| 1059 | + else | |
| 1060 | + input_report_abs(input, ABS_MISC, 0); | |
| 1061 | + | |
| 1062 | + input_event(input, EV_MSC, MSC_SERIAL, serial); | |
| 1063 | + | |
| 1064 | + input_sync(input); | |
| 1065 | + | |
| 1066 | + /*Which mode select (LED light) is currently on?*/ | |
| 1067 | + touch_ring_mode = (data[11] & 0xC0) >> 6; | |
| 1068 | + | |
| 1069 | + for (i = 0; i < WACOM_MAX_REMOTES; i++) { | |
| 1070 | + if (remote->remotes[i].serial == serial) | |
| 1071 | + wacom->led.groups[i].select = touch_ring_mode; | |
| 1072 | + } | |
| 1073 | + | |
| 1074 | + __wacom_notify_battery(&remote->remotes[index].battery, bat_percent, | |
| 1075 | + bat_charging, 1, bat_charging); | |
| 1076 | + | |
| 1077 | +out: | |
| 1078 | + spin_unlock_irqrestore(&remote->remote_lock, flags); | |
| 1079 | + return 0; | |
| 1080 | +} | |
| 1081 | + | |
| 1082 | +static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) | |
| 1083 | +{ | |
| 1084 | + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); | |
| 1085 | + unsigned char *data = wacom_wac->data; | |
| 1086 | + struct wacom_remote *remote = wacom->remote; | |
| 1087 | + struct wacom_remote_data remote_data; | |
| 1088 | + unsigned long flags; | |
| 1089 | + int i, ret; | |
| 1090 | + | |
| 1091 | + if (data[0] != WACOM_REPORT_DEVICE_LIST) | |
| 1092 | + return; | |
| 1093 | + | |
| 1094 | + memset(&remote_data, 0, sizeof(struct wacom_remote_data)); | |
| 1095 | + | |
| 1096 | + for (i = 0; i < WACOM_MAX_REMOTES; i++) { | |
| 1097 | + int j = i * 6; | |
| 1098 | + int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4]; | |
| 1099 | + bool connected = data[j+2]; | |
| 1100 | + | |
| 1101 | + remote_data.remote[i].serial = serial; | |
| 1102 | + remote_data.remote[i].connected = connected; | |
| 1103 | + } | |
| 1104 | + | |
| 1105 | + spin_lock_irqsave(&remote->remote_lock, flags); | |
| 1106 | + | |
| 1107 | + ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data)); | |
| 1108 | + if (ret != sizeof(remote_data)) { | |
| 1109 | + spin_unlock_irqrestore(&remote->remote_lock, flags); | |
| 1110 | + hid_err(wacom->hdev, "Can't queue Remote status event.\n"); | |
| 1111 | + return; | |
| 1112 | + } | |
| 1113 | + | |
| 1114 | + spin_unlock_irqrestore(&remote->remote_lock, flags); | |
| 1115 | + | |
| 1116 | + wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE); | |
| 1117 | +} | |
| 1118 | + | |
| 1119 | 1119 | static int int_dist(int x1, int y1, int x2, int y2) |
| 1120 | 1120 | { |
| 1121 | 1121 | int x = x2 - x1; |
| @@ -1739,6 +1739,7 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, · 617 unmodified lines | ||
| 1739 | 1739 | features->device_type |= WACOM_DEVICETYPE_PAD; |
| 1740 | 1740 | break; |
| 1741 | 1741 | case WACOM_HID_WD_TOUCHONOFF: |
| 1742 | + case WACOM_HID_WD_MUTE_DEVICE: | |
| 1742 | 1743 | /* |
| 1743 | 1744 | * This usage, which is used to mute touch events, comes |
| 1744 | 1745 | * from the pad packet, but is reported on the touch |
| @@ -1768,6 +1769,26 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, · 23 unmodified lines | ||
| 1768 | 1769 | wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); |
| 1769 | 1770 | features->device_type |= WACOM_DEVICETYPE_PAD; |
| 1770 | 1771 | break; |
| 1772 | + case WACOM_HID_WD_BUTTONCONFIG: | |
| 1773 | + wacom_map_usage(input, usage, field, EV_KEY, KEY_BUTTONCONFIG, 0); | |
| 1774 | + features->device_type |= WACOM_DEVICETYPE_PAD; | |
| 1775 | + break; | |
| 1776 | + case WACOM_HID_WD_ONSCREEN_KEYBOARD: | |
| 1777 | + wacom_map_usage(input, usage, field, EV_KEY, KEY_ONSCREEN_KEYBOARD, 0); | |
| 1778 | + features->device_type |= WACOM_DEVICETYPE_PAD; | |
| 1779 | + break; | |
| 1780 | + case WACOM_HID_WD_CONTROLPANEL: | |
| 1781 | + wacom_map_usage(input, usage, field, EV_KEY, KEY_CONTROLPANEL, 0); | |
| 1782 | + features->device_type |= WACOM_DEVICETYPE_PAD; | |
| 1783 | + break; | |
| 1784 | + case WACOM_HID_WD_MODE_CHANGE: | |
| 1785 | + /* do not overwrite previous data */ | |
| 1786 | + if (!wacom_wac->has_mode_change) { | |
| 1787 | + wacom_wac->has_mode_change = true; | |
| 1788 | + wacom_wac->is_direct_mode = true; | |
| 1789 | + } | |
| 1790 | + features->device_type |= WACOM_DEVICETYPE_PAD; | |
| 1791 | + break; | |
| 1771 | 1792 | } |
| 1772 | 1793 | |
| 1773 | 1794 | switch (equivalent_usage & 0xfffffff0) { |
| @@ -1811,12 +1832,13 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field · 37 unmodified lines | ||
| 1811 | 1832 | struct wacom_features *features = &wacom_wac->features; |
| 1812 | 1833 | unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); |
| 1813 | 1834 | int i; |
| 1835 | + bool is_touch_on = value; | |
| 1814 | 1836 | |
| 1815 | 1837 | /* |
| 1816 | 1838 | * Avoid reporting this event and setting inrange_state if this usage |
| 1817 | 1839 | * hasn't been mapped. |
| 1818 | 1840 | */ |
| 1819 | − if (!usage->type) | |
| 1841 | + if (!usage->type && equivalent_usage != WACOM_HID_WD_MODE_CHANGE) | |
| 1820 | 1842 | return; |
| 1821 | 1843 | |
| 1822 | 1844 | if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) { |
| @@ -1830,14 +1852,28 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field · 7 unmodified lines | ||
| 1830 | 1852 | input_event(input, usage->type, usage->code, 0); |
| 1831 | 1853 | break; |
| 1832 | 1854 | |
| 1855 | + case WACOM_HID_WD_MUTE_DEVICE: | |
| 1856 | + if (wacom_wac->shared->touch_input && value) { | |
| 1857 | + wacom_wac->shared->is_touch_on = !wacom_wac->shared->is_touch_on; | |
| 1858 | + is_touch_on = wacom_wac->shared->is_touch_on; | |
| 1859 | + } | |
| 1860 | + | |
| 1861 | + /* fall through*/ | |
| 1833 | 1862 | case WACOM_HID_WD_TOUCHONOFF: |
| 1834 | 1863 | if (wacom_wac->shared->touch_input) { |
| 1835 | 1864 | input_report_switch(wacom_wac->shared->touch_input, |
| 1836 | − SW_MUTE_DEVICE, !value); | |
| 1865 | + SW_MUTE_DEVICE, !is_touch_on); | |
| 1837 | 1866 | input_sync(wacom_wac->shared->touch_input); |
| 1838 | 1867 | } |
| 1839 | 1868 | break; |
| 1840 | 1869 | |
| 1870 | + case WACOM_HID_WD_MODE_CHANGE: | |
| 1871 | + if (wacom_wac->is_direct_mode != value) { | |
| 1872 | + wacom_wac->is_direct_mode = value; | |
| 1873 | + wacom_schedule_work(&wacom->wacom_wac, WACOM_WORKER_MODE_CHANGE); | |
| 1874 | + } | |
| 1875 | + break; | |
| 1876 | + | |
| 1841 | 1877 | case WACOM_HID_WD_BUTTONCENTER: |
| 1842 | 1878 | for (i = 0; i < wacom->led.count; i++) |
| 1843 | 1879 | wacom_update_led(wacom, features->numbered_buttons, |
| @@ -1845,6 +1881,8 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field · 1 unmodified line | ||
| 1845 | 1881 | /* fall through*/ |
| 1846 | 1882 | default: |
| 1847 | 1883 | input_event(input, usage->type, usage->code, value); |
| 1884 | + if (value) | |
| 1885 | + wacom_wac->hid_data.pad_input_event_flag = true; | |
| 1848 | 1886 | break; |
| 1849 | 1887 | } |
| 1850 | 1888 | } |
| @@ -1885,9 +1923,12 @@ static void wacom_wac_pad_report(struct hid_device *hdev, · 34 unmodified lines | ||
| 1885 | 1923 | bool active = wacom_wac->hid_data.inrange_state != 0; |
| 1886 | 1924 | |
| 1887 | 1925 | /* report prox for expresskey events */ |
| 1888 | − if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) { | |
| 1926 | + if ((wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) && | |
| 1927 | + wacom_wac->hid_data.pad_input_event_flag) { | |
| 1889 | 1928 | input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0); |
| 1890 | 1929 | input_sync(input); |
| 1930 | + if (!active) | |
| 1931 | + wacom_wac->hid_data.pad_input_event_flag = false; | |
| 1891 | 1932 | } |
| 1892 | 1933 | |
| 1893 | 1934 | } |
| @@ -2197,6 +2238,13 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac, · 303 unmodified lines | ||
| 2197 | 2238 | bool prox = hid_data->tipswitch && |
| 2198 | 2239 | report_touch_events(wacom_wac); |
| 2199 | 2240 | |
| 2241 | + if (wacom_wac->shared->has_mute_touch_switch && | |
| 2242 | + !wacom_wac->shared->is_touch_on) { | |
| 2243 | + if (!wacom_wac->shared->touch_down) | |
| 2244 | + return; | |
| 2245 | + prox = 0; | |
| 2246 | + } | |
| 2247 | + | |
| 2200 | 2248 | wacom_wac->hid_data.num_received++; |
| 2201 | 2249 | if (wacom_wac->hid_data.num_received > wacom_wac->hid_data.num_expected) |
| 2202 | 2250 | return; |
| @@ -4127,7 +4175,7 @@ static const struct wacom_features wacom_features_0x300 = · 1924 unmodified lines | ||
| 4127 | 4175 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 4128 | 4176 | static const struct wacom_features wacom_features_0x301 = |
| 4129 | 4177 | { "Wacom Bamboo One M", 21648, 13530, 1023, 31, |
| 4130 | − BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | |
| 4178 | + BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | |
| 4131 | 4179 | static const struct wacom_features wacom_features_0x302 = |
| 4132 | 4180 | { "Wacom Intuos PT S", 15200, 9500, 1023, 31, |
| 4133 | 4181 | INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, |
| @@ -120,6 +120,11 @@ · 119 unmodified lines | ||
| 120 | 120 | #define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b) |
| 121 | 121 | #define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) |
| 122 | 122 | #define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950) |
| 123 | +#define WACOM_HID_WD_MODE_CHANGE (WACOM_HID_UP_WACOMDIGITIZER | 0x0980) | |
| 124 | +#define WACOM_HID_WD_MUTE_DEVICE (WACOM_HID_UP_WACOMDIGITIZER | 0x0981) | |
| 125 | +#define WACOM_HID_WD_CONTROLPANEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0982) | |
| 126 | +#define WACOM_HID_WD_ONSCREEN_KEYBOARD (WACOM_HID_UP_WACOMDIGITIZER | 0x0983) | |
| 127 | +#define WACOM_HID_WD_BUTTONCONFIG (WACOM_HID_UP_WACOMDIGITIZER | 0x0986) | |
| 123 | 128 | #define WACOM_HID_WD_BUTTONHOME (WACOM_HID_UP_WACOMDIGITIZER | 0x0990) |
| 124 | 129 | #define WACOM_HID_WD_BUTTONUP (WACOM_HID_UP_WACOMDIGITIZER | 0x0991) |
| 125 | 130 | #define WACOM_HID_WD_BUTTONDOWN (WACOM_HID_UP_WACOMDIGITIZER | 0x0992) |
| @@ -270,6 +275,7 @@ struct wacom_shared { · 144 unmodified lines | ||
| 270 | 275 | struct hid_device *pen; |
| 271 | 276 | struct hid_device *touch; |
| 272 | 277 | bool has_mute_touch_switch; |
| 278 | + bool is_touch_on; | |
| 273 | 279 | }; |
| 274 | 280 | |
| 275 | 281 | struct hid_data { |
| @@ -295,6 +301,7 @@ struct hid_data { · 19 unmodified lines | ||
| 295 | 301 | int bat_charging; |
| 296 | 302 | int bat_connected; |
| 297 | 303 | int ps_connected; |
| 304 | + bool pad_input_event_flag; | |
| 298 | 305 | }; |
| 299 | 306 | |
| 300 | 307 | struct wacom_remote_data { |
| @@ -327,6 +334,9 @@ struct wacom_wac { · 26 unmodified lines | ||
| 327 | 334 | int mode_value; |
| 328 | 335 | struct hid_data hid_data; |
| 329 | 336 | bool has_mute_touch_switch; |
| 337 | + bool has_mode_change; | |
| 338 | + bool is_direct_mode; | |
| 339 | + | |
| 330 | 340 | }; |
| 331 | 341 | |
| 332 | 342 | #endif |
| @@ -268,6 +268,8 @@ struct hid_item { · 267 unmodified lines | ||
| 268 | 268 | #define HID_CP_APPLICATIONLAUNCHBUTTONS 0x000c0180 |
| 269 | 269 | #define HID_CP_GENERICGUIAPPLICATIONCONTROLS 0x000c0200 |
| 270 | 270 | |
| 271 | +#define HID_DG_DEVICECONFIG 0x000d000e | |
| 272 | +#define HID_DG_DEVICESETTINGS 0x000d0023 | |
| 271 | 273 | #define HID_DG_CONFIDENCE 0x000d0047 |
| 272 | 274 | #define HID_DG_WIDTH 0x000d0048 |
| 273 | 275 | #define HID_DG_HEIGHT 0x000d0049 |
| @@ -322,7 +324,7 @@ struct hid_item { · 48 unmodified lines | ||
| 322 | 324 | #define HID_QUIRK_MULTI_INPUT 0x00000040 |
| 323 | 325 | #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 |
| 324 | 326 | #define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 |
| 325 | −#define HID_QUIRK_NO_INIT_INPUT_REPORTS 0x00000200 | |
| 327 | +/* 0x00000200 reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */ | |
| 326 | 328 | #define HID_QUIRK_ALWAYS_POLL 0x00000400 |
| 327 | 329 | #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 |
| 328 | 330 | #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID 0x00020000 |
| @@ -541,7 +543,6 @@ struct hid_device { /* device report descriptor */ · 212 unmodified lines | ||
| 541 | 543 | struct list_head inputs; /* The list of inputs */ |
| 542 | 544 | void *hiddev; /* The hiddev structure */ |
| 543 | 545 | void *hidraw; |
| 544 | − int minor; /* Hiddev minor number */ | |
| 545 | 546 | |
| 546 | 547 | int open; /* is the device open by anyone? */ |
| 547 | 548 | char name[128]; /* Device name */ |
| @@ -32,6 +32,18 @@ · 31 unmodified lines | ||
| 32 | 32 | * In-kernel definitions. |
| 33 | 33 | */ |
| 34 | 34 | |
| 35 | +struct hiddev { | |
| 36 | + int minor; | |
| 37 | + int exist; | |
| 38 | + int open; | |
| 39 | + struct mutex existancelock; | |
| 40 | + wait_queue_head_t wait; | |
| 41 | + struct hid_device *hid; | |
| 42 | + struct list_head list; | |
| 43 | + spinlock_t list_lock; | |
| 44 | + bool initialized; | |
| 45 | +}; | |
| 46 | + | |
| 35 | 47 | struct hid_device; |
| 36 | 48 | struct hid_usage; |
| 37 | 49 | struct hid_field; |
| @@ -14,9 +14,13 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #include <linux/types.h> |
| 16 | 16 | |
| 17 | +struct regulator; | |
| 18 | + | |
| 17 | 19 | /** |
| 18 | 20 | * struct i2chid_platform_data - used by hid over i2c implementation. |
| 19 | 21 | * @hid_descriptor_address: i2c register where the HID descriptor is stored. |
| 22 | + * @supply: regulator for powering on the device. | |
| 23 | + * @post_power_delay_ms: delay after powering on before device is usable. | |
| 20 | 24 | * |
| 21 | 25 | * Note that it is the responsibility of the platform driver (or the acpi 5.0 |
| 22 | 26 | * driver, or the flattened device tree) to setup the irq related to the gpio in |
| @@ -31,6 +35,8 @@ · 8 unmodified lines | ||
| 31 | 35 | */ |
| 32 | 36 | struct i2c_hid_platform_data { |
| 33 | 37 | u16 hid_descriptor_address; |
| 38 | + struct regulator *supply; | |
| 39 | + int post_power_delay_ms; | |
| 34 | 40 | }; |
| 35 | 41 | |
| 36 | 42 | #endif /* __LINUX_I2C_HID_H */ |
| @@ -641,6 +641,7 @@ · 640 unmodified lines | ||
| 641 | 641 | * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.) |
| 642 | 642 | */ |
| 643 | 643 | #define KEY_DATA 0x277 |
| 644 | +#define KEY_ONSCREEN_KEYBOARD 0x278 | |
| 644 | 645 | |
| 645 | 646 | #define BTN_TRIGGER_HAPPY 0x2c0 |
| 646 | 647 | #define BTN_TRIGGER_HAPPY1 0x2c0 |
| @@ -61,9 +61,14 @@ struct input_id { · 60 unmodified lines | ||
| 61 | 61 | * Note that input core does not clamp reported values to the |
| 62 | 62 | * [minimum, maximum] limits, such task is left to userspace. |
| 63 | 63 | * |
| 64 | − * Resolution for main axes (ABS_X, ABS_Y, ABS_Z) is reported in | |
| 65 | − * units per millimeter (units/mm), resolution for rotational axes | |
| 66 | − * (ABS_RX, ABS_RY, ABS_RZ) is reported in units per radian. | |
| 64 | + * The default resolution for main axes (ABS_X, ABS_Y, ABS_Z) | |
| 65 | + * is reported in units per millimeter (units/mm), resolution | |
| 66 | + * for rotational axes (ABS_RX, ABS_RY, ABS_RZ) is reported | |
| 67 | + * in units per radian. | |
| 68 | + * When INPUT_PROP_ACCELEROMETER is set the resolution changes. | |
| 69 | + * The main axes (ABS_X, ABS_Y, ABS_Z) are then reported in | |
| 70 | + * in units per g (units/g) and in units per degree per second | |
| 71 | + * (units/deg/s) for rotational axes (ABS_RX, ABS_RY, ABS_RZ). | |
| 67 | 72 | */ |
| 68 | 73 | struct input_absinfo { |
| 69 | 74 | __s32 value; |