Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID updates from Jiri Kosina:

- Surface Aggregator Module support from Maximilian Luz

- Apple Magic Mouse 2 support from John Chen

- Support for newer Quad/BT 2.0 Logitech receivers in HID proxy mode
from Hans de Goede

- Thinkpad X1 Tablet keyboard support from Hans de Goede

- Support for FTDI FT260 I2C host adapter from Michael Zaidman

- other various small device-specific quirks, fixes and cleanups

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (46 commits)
HID: wacom: Setup pen input capabilities to the targeted tools
HID: hid-sensor-hub: Move 'hsdev' description to correct struct definition
HID: hid-sensor-hub: Remove unused struct member 'quirks'
HID: wacom_sys: Demote kernel-doc abuse
HID: hid-sensor-custom: Remove unused variable 'ret'
HID: hid-uclogic-params: Ensure function names are present and correct in kernel-doc headers
HID: hid-uclogic-rdesc: Kernel-doc is for functions and structs
HID: hid-logitech-hidpp: Fix conformant kernel-doc header and demote abuses
HID: hid-picolcd_core: Remove unused variable 'ret'
HID: hid-kye: Fix incorrect function name for kye_tablet_enable()
HID: hid-core: Fix incorrect function name in header
HID: hid-alps: Correct struct misnaming
HID: usbhid: hid-pidff: Demote a couple kernel-doc abuses
HID: usbhid: Repair a formatting issue in a struct description
HID: hid-thrustmaster: Demote a bunch of kernel-doc abuses
HID: input: map battery capacity (00850065)
HID: magicmouse: fix reconnection of Magic Mouse 2
HID: magicmouse: fix 3 button emulation of Mouse 2
HID: magicmouse: add Apple Magic Mouse 2 support
HID: lenovo: Add support for Thinkpad X1 Tablet Thin keyboard
...

+2955 -229
+14
MAINTAINERS
··· 7432 7432 F: include/linux/fsverity.h 7433 7433 F: include/uapi/linux/fsverity.h 7434 7434 7435 + FT260 FTDI USB-HID TO I2C BRIDGE DRIVER 7436 + M: Michael Zaidman <michael.zaidman@gmail.com> 7437 + L: linux-i2c@vger.kernel.org 7438 + L: linux-input@vger.kernel.org 7439 + S: Maintained 7440 + F: drivers/hid/hid-ft260.c 7441 + 7435 7442 FUJITSU LAPTOP EXTRAS 7436 7443 M: Jonathan Woithe <jwoithe@just42.net> 7437 7444 L: platform-driver-x86@vger.kernel.org ··· 12085 12078 S: Maintained 12086 12079 T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git 12087 12080 F: drivers/platform/surface/ 12081 + 12082 + MICROSOFT SURFACE HID TRANSPORT DRIVER 12083 + M: Maximilian Luz <luzmaximilian@gmail.com> 12084 + L: linux-input@vger.kernel.org 12085 + L: platform-driver-x86@vger.kernel.org 12086 + S: Maintained 12087 + F: drivers/hid/surface-hid/ 12088 12088 12089 12089 MICROSOFT SURFACE HOT-PLUG DRIVER 12090 12090 M: Maximilian Luz <luzmaximilian@gmail.com>
+17 -3
drivers/hid/Kconfig
··· 351 351 help 352 352 Support for Ezkey BTC 8193 keyboard. 353 353 354 + config HID_FT260 355 + tristate "FTDI FT260 USB HID to I2C host support" 356 + depends on USB_HID && HIDRAW && I2C 357 + help 358 + Provides I2C host adapter functionality over USB-HID through FT260 359 + device. The customizable USB descriptor fields are exposed as sysfs 360 + attributes. 361 + 362 + To compile this driver as a module, choose M here: the module 363 + will be called hid-ft260. 364 + 354 365 config HID_GEMBIRD 355 366 tristate "Gembird Joypad" 356 367 depends on HID ··· 1053 1042 1054 1043 config HID_THRUSTMASTER 1055 1044 tristate "ThrustMaster devices support" 1056 - depends on HID 1045 + depends on USB_HID 1057 1046 help 1058 - Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or 1059 - a THRUSTMASTER Ferrari GT Rumble Wheel. 1047 + Say Y here if you have a THRUSTMASTER FireStore Dual Power 2, 1048 + a THRUSTMASTER Ferrari GT Rumble Wheel or Thrustmaster FFB 1049 + Wheel (T150RS, T300RS, T300 Ferrari Alcantara Edition, T500RS). 1060 1050 1061 1051 config THRUSTMASTER_FF 1062 1052 bool "ThrustMaster devices force feedback support" ··· 1217 1205 source "drivers/hid/intel-ish-hid/Kconfig" 1218 1206 1219 1207 source "drivers/hid/amd-sfh-hid/Kconfig" 1208 + 1209 + source "drivers/hid/surface-hid/Kconfig" 1220 1210 1221 1211 endmenu
+5 -1
drivers/hid/Makefile
··· 46 46 obj-$(CONFIG_HID_ELECOM) += hid-elecom.o 47 47 obj-$(CONFIG_HID_ELO) += hid-elo.o 48 48 obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o 49 + obj-$(CONFIG_HID_FT260) += hid-ft260.o 49 50 obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o 50 51 obj-$(CONFIG_HID_GFRM) += hid-gfrm.o 51 52 obj-$(CONFIG_HID_GLORIOUS) += hid-glorious.o ··· 113 112 obj-$(CONFIG_HID_STEELSERIES) += hid-steelseries.o 114 113 obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o 115 114 obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o 116 - obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o 115 + obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o hid-thrustmaster.o 116 + obj-$(CONFIG_HID_TMINIT) += hid-tminit.o 117 117 obj-$(CONFIG_HID_TIVO) += hid-tivo.o 118 118 obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o 119 119 obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o ··· 147 145 obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/ 148 146 149 147 obj-$(CONFIG_AMD_SFH_HID) += amd-sfh-hid/ 148 + 149 + obj-$(CONFIG_SURFACE_HID_CORE) += surface-hid/
+1 -1
drivers/hid/hid-alps.c
··· 74 74 UNKNOWN, 75 75 }; 76 76 /** 77 - * struct u1_data 77 + * struct alps_dev 78 78 * 79 79 * @input: pointer to the kernel input device 80 80 * @input2: pointer to the kernel input2 device
+1 -1
drivers/hid/hid-core.c
··· 2129 2129 }; 2130 2130 2131 2131 /** 2132 - * store_new_id - add a new HID device ID to this driver and re-probe devices 2132 + * new_id_store - add a new HID device ID to this driver and re-probe devices 2133 2133 * @drv: target device driver 2134 2134 * @buf: buffer for scanning device ID data 2135 2135 * @count: input size
+1
drivers/hid/hid-debug.c
··· 417 417 { 0x85, 0x44, "Charging" }, 418 418 { 0x85, 0x45, "Discharging" }, 419 419 { 0x85, 0x4b, "NeedReplacement" }, 420 + { 0x85, 0x65, "AbsoluteStateOfCharge" }, 420 421 { 0x85, 0x66, "RemainingCapacity" }, 421 422 { 0x85, 0x68, "RunTimeToEmpty" }, 422 423 { 0x85, 0x6a, "AverageTimeToFull" },
+5 -12
drivers/hid/hid-elan.c
··· 410 410 return 0; 411 411 } 412 412 413 - static enum led_brightness elan_mute_led_get_brigtness(struct led_classdev *led_cdev) 414 - { 415 - struct device *dev = led_cdev->dev->parent; 416 - struct hid_device *hdev = to_hid_device(dev); 417 - struct elan_drvdata *drvdata = hid_get_drvdata(hdev); 418 - 419 - return drvdata->mute_led_state; 420 - } 421 - 422 413 static int elan_mute_led_set_brigtness(struct led_classdev *led_cdev, 423 414 enum led_brightness value) 424 415 { ··· 436 445 kfree(dmabuf); 437 446 438 447 if (ret != ELAN_LED_REPORT_SIZE) { 439 - hid_err(hdev, "Failed to set mute led brightness: %d\n", ret); 440 - return ret; 448 + if (ret != -ENODEV) 449 + hid_err(hdev, "Failed to set mute led brightness: %d\n", ret); 450 + return ret < 0 ? ret : -EIO; 441 451 } 442 452 443 453 drvdata->mute_led_state = led_state; ··· 451 459 struct led_classdev *mute_led = &drvdata->mute_led; 452 460 453 461 mute_led->name = "elan:red:mute"; 454 - mute_led->brightness_get = elan_mute_led_get_brigtness; 462 + mute_led->default_trigger = "audio-mute"; 455 463 mute_led->brightness_set_blocking = elan_mute_led_set_brigtness; 456 464 mute_led->max_brightness = LED_ON; 465 + mute_led->flags = LED_HW_PLUGGABLE; 457 466 mute_led->dev = &hdev->dev; 458 467 459 468 return devm_led_classdev_register(&hdev->dev, mute_led);
+1054
drivers/hid/hid-ft260.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * hid-ft260.c - FTDI FT260 USB HID to I2C host bridge 4 + * 5 + * Copyright (c) 2021, Michael Zaidman <michaelz@xsightlabs.com> 6 + * 7 + * Data Sheet: 8 + * https://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT260.pdf 9 + */ 10 + 11 + #include "hid-ids.h" 12 + #include <linux/hidraw.h> 13 + #include <linux/i2c.h> 14 + #include <linux/module.h> 15 + #include <linux/usb.h> 16 + 17 + #ifdef DEBUG 18 + static int ft260_debug = 1; 19 + #else 20 + static int ft260_debug; 21 + #endif 22 + module_param_named(debug, ft260_debug, int, 0600); 23 + MODULE_PARM_DESC(debug, "Toggle FT260 debugging messages"); 24 + 25 + #define ft260_dbg(format, arg...) \ 26 + do { \ 27 + if (ft260_debug) \ 28 + pr_info("%s: " format, __func__, ##arg); \ 29 + } while (0) 30 + 31 + #define FT260_REPORT_MAX_LENGTH (64) 32 + #define FT260_I2C_DATA_REPORT_ID(len) (FT260_I2C_REPORT_MIN + (len - 1) / 4) 33 + /* 34 + * The input report format assigns 62 bytes for the data payload, but ft260 35 + * returns 60 and 2 in two separate transactions. To minimize transfer time 36 + * in reading chunks mode, set the maximum read payload length to 60 bytes. 37 + */ 38 + #define FT260_RD_DATA_MAX (60) 39 + #define FT260_WR_DATA_MAX (60) 40 + 41 + /* 42 + * Device interface configuration. 43 + * The FT260 has 2 interfaces that are controlled by DCNF0 and DCNF1 pins. 44 + * First implementes USB HID to I2C bridge function and 45 + * second - USB HID to UART bridge function. 46 + */ 47 + enum { 48 + FT260_MODE_ALL = 0x00, 49 + FT260_MODE_I2C = 0x01, 50 + FT260_MODE_UART = 0x02, 51 + FT260_MODE_BOTH = 0x03, 52 + }; 53 + 54 + /* Control pipe */ 55 + enum { 56 + FT260_GET_RQST_TYPE = 0xA1, 57 + FT260_GET_REPORT = 0x01, 58 + FT260_SET_RQST_TYPE = 0x21, 59 + FT260_SET_REPORT = 0x09, 60 + FT260_FEATURE = 0x03, 61 + }; 62 + 63 + /* Report IDs / Feature In */ 64 + enum { 65 + FT260_CHIP_VERSION = 0xA0, 66 + FT260_SYSTEM_SETTINGS = 0xA1, 67 + FT260_I2C_STATUS = 0xC0, 68 + FT260_I2C_READ_REQ = 0xC2, 69 + FT260_I2C_REPORT_MIN = 0xD0, 70 + FT260_I2C_REPORT_MAX = 0xDE, 71 + FT260_GPIO = 0xB0, 72 + FT260_UART_INTERRUPT_STATUS = 0xB1, 73 + FT260_UART_STATUS = 0xE0, 74 + FT260_UART_RI_DCD_STATUS = 0xE1, 75 + FT260_UART_REPORT = 0xF0, 76 + }; 77 + 78 + /* Feature Out */ 79 + enum { 80 + FT260_SET_CLOCK = 0x01, 81 + FT260_SET_I2C_MODE = 0x02, 82 + FT260_SET_UART_MODE = 0x03, 83 + FT260_ENABLE_INTERRUPT = 0x05, 84 + FT260_SELECT_GPIO2_FUNC = 0x06, 85 + FT260_ENABLE_UART_DCD_RI = 0x07, 86 + FT260_SELECT_GPIOA_FUNC = 0x08, 87 + FT260_SELECT_GPIOG_FUNC = 0x09, 88 + FT260_SET_INTERRUPT_TRIGGER = 0x0A, 89 + FT260_SET_SUSPEND_OUT_POLAR = 0x0B, 90 + FT260_ENABLE_UART_RI_WAKEUP = 0x0C, 91 + FT260_SET_UART_RI_WAKEUP_CFG = 0x0D, 92 + FT260_SET_I2C_RESET = 0x20, 93 + FT260_SET_I2C_CLOCK_SPEED = 0x22, 94 + FT260_SET_UART_RESET = 0x40, 95 + FT260_SET_UART_CONFIG = 0x41, 96 + FT260_SET_UART_BAUD_RATE = 0x42, 97 + FT260_SET_UART_DATA_BIT = 0x43, 98 + FT260_SET_UART_PARITY = 0x44, 99 + FT260_SET_UART_STOP_BIT = 0x45, 100 + FT260_SET_UART_BREAKING = 0x46, 101 + FT260_SET_UART_XON_XOFF = 0x49, 102 + }; 103 + 104 + /* Response codes in I2C status report */ 105 + enum { 106 + FT260_I2C_STATUS_SUCCESS = 0x00, 107 + FT260_I2C_STATUS_CTRL_BUSY = 0x01, 108 + FT260_I2C_STATUS_ERROR = 0x02, 109 + FT260_I2C_STATUS_ADDR_NO_ACK = 0x04, 110 + FT260_I2C_STATUS_DATA_NO_ACK = 0x08, 111 + FT260_I2C_STATUS_ARBITR_LOST = 0x10, 112 + FT260_I2C_STATUS_CTRL_IDLE = 0x20, 113 + FT260_I2C_STATUS_BUS_BUSY = 0x40, 114 + }; 115 + 116 + /* I2C Conditions flags */ 117 + enum { 118 + FT260_FLAG_NONE = 0x00, 119 + FT260_FLAG_START = 0x02, 120 + FT260_FLAG_START_REPEATED = 0x03, 121 + FT260_FLAG_STOP = 0x04, 122 + FT260_FLAG_START_STOP = 0x06, 123 + FT260_FLAG_START_STOP_REPEATED = 0x07, 124 + }; 125 + 126 + #define FT260_SET_REQUEST_VALUE(report_id) ((FT260_FEATURE << 8) | report_id) 127 + 128 + /* Feature In reports */ 129 + 130 + struct ft260_get_chip_version_report { 131 + u8 report; /* FT260_CHIP_VERSION */ 132 + u8 chip_code[4]; /* FTDI chip identification code */ 133 + u8 reserved[8]; 134 + } __packed; 135 + 136 + struct ft260_get_system_status_report { 137 + u8 report; /* FT260_SYSTEM_SETTINGS */ 138 + u8 chip_mode; /* DCNF0 and DCNF1 status, bits 0-1 */ 139 + u8 clock_ctl; /* 0 - 12MHz, 1 - 24MHz, 2 - 48MHz */ 140 + u8 suspend_status; /* 0 - not suspended, 1 - suspended */ 141 + u8 pwren_status; /* 0 - FT260 is not ready, 1 - ready */ 142 + u8 i2c_enable; /* 0 - disabled, 1 - enabled */ 143 + u8 uart_mode; /* 0 - OFF; 1 - RTS_CTS, 2 - DTR_DSR, */ 144 + /* 3 - XON_XOFF, 4 - No flow control */ 145 + u8 hid_over_i2c_en; /* 0 - disabled, 1 - enabled */ 146 + u8 gpio2_function; /* 0 - GPIO, 1 - SUSPOUT, */ 147 + /* 2 - PWREN, 4 - TX_LED */ 148 + u8 gpioA_function; /* 0 - GPIO, 3 - TX_ACTIVE, 4 - TX_LED */ 149 + u8 gpioG_function; /* 0 - GPIO, 2 - PWREN, */ 150 + /* 5 - RX_LED, 6 - BCD_DET */ 151 + u8 suspend_out_pol; /* 0 - active-high, 1 - active-low */ 152 + u8 enable_wakeup_int; /* 0 - disabled, 1 - enabled */ 153 + u8 intr_cond; /* Interrupt trigger conditions */ 154 + u8 power_saving_en; /* 0 - disabled, 1 - enabled */ 155 + u8 reserved[10]; 156 + } __packed; 157 + 158 + struct ft260_get_i2c_status_report { 159 + u8 report; /* FT260_I2C_STATUS */ 160 + u8 bus_status; /* I2C bus status */ 161 + __le16 clock; /* I2C bus clock in range 60-3400 KHz */ 162 + u8 reserved; 163 + } __packed; 164 + 165 + /* Feature Out reports */ 166 + 167 + struct ft260_set_system_clock_report { 168 + u8 report; /* FT260_SYSTEM_SETTINGS */ 169 + u8 request; /* FT260_SET_CLOCK */ 170 + u8 clock_ctl; /* 0 - 12MHz, 1 - 24MHz, 2 - 48MHz */ 171 + } __packed; 172 + 173 + struct ft260_set_i2c_mode_report { 174 + u8 report; /* FT260_SYSTEM_SETTINGS */ 175 + u8 request; /* FT260_SET_I2C_MODE */ 176 + u8 i2c_enable; /* 0 - disabled, 1 - enabled */ 177 + } __packed; 178 + 179 + struct ft260_set_uart_mode_report { 180 + u8 report; /* FT260_SYSTEM_SETTINGS */ 181 + u8 request; /* FT260_SET_UART_MODE */ 182 + u8 uart_mode; /* 0 - OFF; 1 - RTS_CTS, 2 - DTR_DSR, */ 183 + /* 3 - XON_XOFF, 4 - No flow control */ 184 + } __packed; 185 + 186 + struct ft260_set_i2c_reset_report { 187 + u8 report; /* FT260_SYSTEM_SETTINGS */ 188 + u8 request; /* FT260_SET_I2C_RESET */ 189 + } __packed; 190 + 191 + struct ft260_set_i2c_speed_report { 192 + u8 report; /* FT260_SYSTEM_SETTINGS */ 193 + u8 request; /* FT260_SET_I2C_CLOCK_SPEED */ 194 + __le16 clock; /* I2C bus clock in range 60-3400 KHz */ 195 + } __packed; 196 + 197 + /* Data transfer reports */ 198 + 199 + struct ft260_i2c_write_request_report { 200 + u8 report; /* FT260_I2C_REPORT */ 201 + u8 address; /* 7-bit I2C address */ 202 + u8 flag; /* I2C transaction condition */ 203 + u8 length; /* data payload length */ 204 + u8 data[60]; /* data payload */ 205 + } __packed; 206 + 207 + struct ft260_i2c_read_request_report { 208 + u8 report; /* FT260_I2C_READ_REQ */ 209 + u8 address; /* 7-bit I2C address */ 210 + u8 flag; /* I2C transaction condition */ 211 + __le16 length; /* data payload length */ 212 + } __packed; 213 + 214 + struct ft260_i2c_input_report { 215 + u8 report; /* FT260_I2C_REPORT */ 216 + u8 length; /* data payload length */ 217 + u8 data[2]; /* data payload */ 218 + } __packed; 219 + 220 + static const struct hid_device_id ft260_devices[] = { 221 + { HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, 222 + USB_DEVICE_ID_FT260) }, 223 + { /* END OF LIST */ } 224 + }; 225 + MODULE_DEVICE_TABLE(hid, ft260_devices); 226 + 227 + struct ft260_device { 228 + struct i2c_adapter adap; 229 + struct hid_device *hdev; 230 + struct completion wait; 231 + struct mutex lock; 232 + u8 write_buf[FT260_REPORT_MAX_LENGTH]; 233 + u8 *read_buf; 234 + u16 read_idx; 235 + u16 read_len; 236 + u16 clock; 237 + }; 238 + 239 + static int ft260_hid_feature_report_get(struct hid_device *hdev, 240 + unsigned char report_id, u8 *data, 241 + size_t len) 242 + { 243 + u8 *buf; 244 + int ret; 245 + 246 + buf = kmalloc(len, GFP_KERNEL); 247 + if (!buf) 248 + return -ENOMEM; 249 + 250 + ret = hid_hw_raw_request(hdev, report_id, buf, len, HID_FEATURE_REPORT, 251 + HID_REQ_GET_REPORT); 252 + memcpy(data, buf, len); 253 + kfree(buf); 254 + return ret; 255 + } 256 + 257 + static int ft260_hid_feature_report_set(struct hid_device *hdev, u8 *data, 258 + size_t len) 259 + { 260 + u8 *buf; 261 + int ret; 262 + 263 + buf = kmemdup(data, len, GFP_KERNEL); 264 + if (!buf) 265 + return -ENOMEM; 266 + 267 + buf[0] = FT260_SYSTEM_SETTINGS; 268 + 269 + ret = hid_hw_raw_request(hdev, buf[0], buf, len, HID_FEATURE_REPORT, 270 + HID_REQ_SET_REPORT); 271 + 272 + kfree(buf); 273 + return ret; 274 + } 275 + 276 + static int ft260_i2c_reset(struct hid_device *hdev) 277 + { 278 + struct ft260_set_i2c_reset_report report; 279 + int ret; 280 + 281 + report.request = FT260_SET_I2C_RESET; 282 + 283 + ret = ft260_hid_feature_report_set(hdev, (u8 *)&report, sizeof(report)); 284 + if (ret < 0) { 285 + hid_err(hdev, "failed to reset I2C controller: %d\n", ret); 286 + return ret; 287 + } 288 + 289 + ft260_dbg("done\n"); 290 + return ret; 291 + } 292 + 293 + static int ft260_xfer_status(struct ft260_device *dev) 294 + { 295 + struct hid_device *hdev = dev->hdev; 296 + struct ft260_get_i2c_status_report report; 297 + int ret; 298 + 299 + ret = ft260_hid_feature_report_get(hdev, FT260_I2C_STATUS, 300 + (u8 *)&report, sizeof(report)); 301 + if (ret < 0) { 302 + hid_err(hdev, "failed to retrieve status: %d\n", ret); 303 + return ret; 304 + } 305 + 306 + dev->clock = le16_to_cpu(report.clock); 307 + ft260_dbg("bus_status %#02x, clock %u\n", report.bus_status, 308 + dev->clock); 309 + 310 + if (report.bus_status & FT260_I2C_STATUS_CTRL_BUSY) 311 + return -EAGAIN; 312 + 313 + if (report.bus_status & FT260_I2C_STATUS_BUS_BUSY) 314 + return -EBUSY; 315 + 316 + if (report.bus_status & FT260_I2C_STATUS_ERROR) 317 + return -EIO; 318 + 319 + ret = -EIO; 320 + 321 + if (report.bus_status & FT260_I2C_STATUS_ADDR_NO_ACK) 322 + ft260_dbg("unacknowledged address\n"); 323 + 324 + if (report.bus_status & FT260_I2C_STATUS_DATA_NO_ACK) 325 + ft260_dbg("unacknowledged data\n"); 326 + 327 + if (report.bus_status & FT260_I2C_STATUS_ARBITR_LOST) 328 + ft260_dbg("arbitration loss\n"); 329 + 330 + if (report.bus_status & FT260_I2C_STATUS_CTRL_IDLE) 331 + ret = 0; 332 + 333 + return ret; 334 + } 335 + 336 + static int ft260_hid_output_report(struct hid_device *hdev, u8 *data, 337 + size_t len) 338 + { 339 + u8 *buf; 340 + int ret; 341 + 342 + buf = kmemdup(data, len, GFP_KERNEL); 343 + if (!buf) 344 + return -ENOMEM; 345 + 346 + ret = hid_hw_output_report(hdev, buf, len); 347 + 348 + kfree(buf); 349 + return ret; 350 + } 351 + 352 + static int ft260_hid_output_report_check_status(struct ft260_device *dev, 353 + u8 *data, int len) 354 + { 355 + int ret, usec, try = 3; 356 + struct hid_device *hdev = dev->hdev; 357 + 358 + ret = ft260_hid_output_report(hdev, data, len); 359 + if (ret < 0) { 360 + hid_err(hdev, "%s: failed to start transfer, ret %d\n", 361 + __func__, ret); 362 + ft260_i2c_reset(hdev); 363 + return ret; 364 + } 365 + 366 + /* transfer time = 1 / clock(KHz) * 10 bits * bytes */ 367 + usec = 10000 / dev->clock * len; 368 + usleep_range(usec, usec + 100); 369 + ft260_dbg("wait %d usec, len %d\n", usec, len); 370 + do { 371 + ret = ft260_xfer_status(dev); 372 + if (ret != -EAGAIN) 373 + break; 374 + } while (--try); 375 + 376 + if (ret == 0 || ret == -EBUSY) 377 + return 0; 378 + 379 + ft260_i2c_reset(hdev); 380 + return -EIO; 381 + } 382 + 383 + static int ft260_i2c_write(struct ft260_device *dev, u8 addr, u8 *data, 384 + int data_len, u8 flag) 385 + { 386 + int len, ret, idx = 0; 387 + struct hid_device *hdev = dev->hdev; 388 + struct ft260_i2c_write_request_report *rep = 389 + (struct ft260_i2c_write_request_report *)dev->write_buf; 390 + 391 + do { 392 + if (data_len <= FT260_WR_DATA_MAX) 393 + len = data_len; 394 + else 395 + len = FT260_WR_DATA_MAX; 396 + 397 + rep->report = FT260_I2C_DATA_REPORT_ID(len); 398 + rep->address = addr; 399 + rep->length = len; 400 + rep->flag = flag; 401 + 402 + memcpy(rep->data, &data[idx], len); 403 + 404 + ft260_dbg("rep %#02x addr %#02x off %d len %d d[0] %#02x\n", 405 + rep->report, addr, idx, len, data[0]); 406 + 407 + ret = ft260_hid_output_report_check_status(dev, (u8 *)rep, 408 + len + 4); 409 + if (ret < 0) { 410 + hid_err(hdev, "%s: failed to start transfer, ret %d\n", 411 + __func__, ret); 412 + return ret; 413 + } 414 + 415 + data_len -= len; 416 + idx += len; 417 + 418 + } while (data_len > 0); 419 + 420 + return 0; 421 + } 422 + 423 + static int ft260_smbus_write(struct ft260_device *dev, u8 addr, u8 cmd, 424 + u8 *data, u8 data_len, u8 flag) 425 + { 426 + int ret = 0; 427 + int len = 4; 428 + 429 + struct ft260_i2c_write_request_report *rep = 430 + (struct ft260_i2c_write_request_report *)dev->write_buf; 431 + 432 + rep->address = addr; 433 + rep->data[0] = cmd; 434 + rep->length = data_len + 1; 435 + rep->flag = flag; 436 + len += rep->length; 437 + 438 + rep->report = FT260_I2C_DATA_REPORT_ID(len); 439 + 440 + if (data_len > 0) 441 + memcpy(&rep->data[1], data, data_len); 442 + 443 + ft260_dbg("rep %#02x addr %#02x cmd %#02x datlen %d replen %d\n", 444 + rep->report, addr, cmd, rep->length, len); 445 + 446 + ret = ft260_hid_output_report_check_status(dev, (u8 *)rep, len); 447 + 448 + return ret; 449 + } 450 + 451 + static int ft260_i2c_read(struct ft260_device *dev, u8 addr, u8 *data, 452 + u16 len, u8 flag) 453 + { 454 + struct ft260_i2c_read_request_report rep; 455 + struct hid_device *hdev = dev->hdev; 456 + int timeout; 457 + int ret; 458 + 459 + if (len > FT260_RD_DATA_MAX) { 460 + hid_err(hdev, "%s: unsupported rd len: %d\n", __func__, len); 461 + return -EINVAL; 462 + } 463 + 464 + dev->read_idx = 0; 465 + dev->read_buf = data; 466 + dev->read_len = len; 467 + 468 + rep.report = FT260_I2C_READ_REQ; 469 + rep.length = cpu_to_le16(len); 470 + rep.address = addr; 471 + rep.flag = flag; 472 + 473 + ft260_dbg("rep %#02x addr %#02x len %d\n", rep.report, rep.address, 474 + rep.length); 475 + 476 + reinit_completion(&dev->wait); 477 + 478 + ret = ft260_hid_output_report(hdev, (u8 *)&rep, sizeof(rep)); 479 + if (ret < 0) { 480 + hid_err(hdev, "%s: failed to start transaction, ret %d\n", 481 + __func__, ret); 482 + return ret; 483 + } 484 + 485 + timeout = msecs_to_jiffies(5000); 486 + if (!wait_for_completion_timeout(&dev->wait, timeout)) { 487 + ft260_i2c_reset(hdev); 488 + return -ETIMEDOUT; 489 + } 490 + 491 + ret = ft260_xfer_status(dev); 492 + if (ret == 0) 493 + return 0; 494 + 495 + ft260_i2c_reset(hdev); 496 + return -EIO; 497 + } 498 + 499 + /* 500 + * A random read operation is implemented as a dummy write operation, followed 501 + * by a current address read operation. The dummy write operation is used to 502 + * load the target byte address into the current byte address counter, from 503 + * which the subsequent current address read operation then reads. 504 + */ 505 + static int ft260_i2c_write_read(struct ft260_device *dev, struct i2c_msg *msgs) 506 + { 507 + int len, ret; 508 + u16 left_len = msgs[1].len; 509 + u8 *read_buf = msgs[1].buf; 510 + u8 addr = msgs[0].addr; 511 + u16 read_off = 0; 512 + struct hid_device *hdev = dev->hdev; 513 + 514 + if (msgs[0].len > 2) { 515 + hid_err(hdev, "%s: unsupported wr len: %d\n", __func__, 516 + msgs[0].len); 517 + return -EOPNOTSUPP; 518 + } 519 + 520 + memcpy(&read_off, msgs[0].buf, msgs[0].len); 521 + 522 + do { 523 + if (left_len <= FT260_RD_DATA_MAX) 524 + len = left_len; 525 + else 526 + len = FT260_RD_DATA_MAX; 527 + 528 + ft260_dbg("read_off %#x left_len %d len %d\n", read_off, 529 + left_len, len); 530 + 531 + ret = ft260_i2c_write(dev, addr, (u8 *)&read_off, msgs[0].len, 532 + FT260_FLAG_START); 533 + if (ret < 0) 534 + return ret; 535 + 536 + ret = ft260_i2c_read(dev, addr, read_buf, len, 537 + FT260_FLAG_START_STOP); 538 + if (ret < 0) 539 + return ret; 540 + 541 + left_len -= len; 542 + read_buf += len; 543 + read_off += len; 544 + 545 + } while (left_len > 0); 546 + 547 + return 0; 548 + } 549 + 550 + static int ft260_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, 551 + int num) 552 + { 553 + int ret; 554 + struct ft260_device *dev = i2c_get_adapdata(adapter); 555 + struct hid_device *hdev = dev->hdev; 556 + 557 + mutex_lock(&dev->lock); 558 + 559 + ret = hid_hw_power(hdev, PM_HINT_FULLON); 560 + if (ret < 0) { 561 + hid_err(hdev, "failed to enter FULLON power mode: %d\n", ret); 562 + mutex_unlock(&dev->lock); 563 + return ret; 564 + } 565 + 566 + if (num == 1) { 567 + if (msgs->flags & I2C_M_RD) 568 + ret = ft260_i2c_read(dev, msgs->addr, msgs->buf, 569 + msgs->len, FT260_FLAG_START_STOP); 570 + else 571 + ret = ft260_i2c_write(dev, msgs->addr, msgs->buf, 572 + msgs->len, FT260_FLAG_START_STOP); 573 + if (ret < 0) 574 + goto i2c_exit; 575 + 576 + } else { 577 + /* Combined write then read message */ 578 + ret = ft260_i2c_write_read(dev, msgs); 579 + if (ret < 0) 580 + goto i2c_exit; 581 + } 582 + 583 + ret = num; 584 + i2c_exit: 585 + hid_hw_power(hdev, PM_HINT_NORMAL); 586 + mutex_unlock(&dev->lock); 587 + return ret; 588 + } 589 + 590 + static int ft260_smbus_xfer(struct i2c_adapter *adapter, u16 addr, u16 flags, 591 + char read_write, u8 cmd, int size, 592 + union i2c_smbus_data *data) 593 + { 594 + int ret; 595 + struct ft260_device *dev = i2c_get_adapdata(adapter); 596 + struct hid_device *hdev = dev->hdev; 597 + 598 + ft260_dbg("smbus size %d\n", size); 599 + 600 + mutex_lock(&dev->lock); 601 + 602 + ret = hid_hw_power(hdev, PM_HINT_FULLON); 603 + if (ret < 0) { 604 + hid_err(hdev, "power management error: %d\n", ret); 605 + mutex_unlock(&dev->lock); 606 + return ret; 607 + } 608 + 609 + switch (size) { 610 + case I2C_SMBUS_QUICK: 611 + if (read_write == I2C_SMBUS_READ) 612 + ret = ft260_i2c_read(dev, addr, &data->byte, 0, 613 + FT260_FLAG_START_STOP); 614 + else 615 + ret = ft260_smbus_write(dev, addr, cmd, NULL, 0, 616 + FT260_FLAG_START_STOP); 617 + break; 618 + case I2C_SMBUS_BYTE: 619 + if (read_write == I2C_SMBUS_READ) 620 + ret = ft260_i2c_read(dev, addr, &data->byte, 1, 621 + FT260_FLAG_START_STOP); 622 + else 623 + ret = ft260_smbus_write(dev, addr, cmd, NULL, 0, 624 + FT260_FLAG_START_STOP); 625 + break; 626 + case I2C_SMBUS_BYTE_DATA: 627 + if (read_write == I2C_SMBUS_READ) { 628 + ret = ft260_smbus_write(dev, addr, cmd, NULL, 0, 629 + FT260_FLAG_START); 630 + if (ret) 631 + goto smbus_exit; 632 + 633 + ret = ft260_i2c_read(dev, addr, &data->byte, 1, 634 + FT260_FLAG_START_STOP_REPEATED); 635 + } else { 636 + ret = ft260_smbus_write(dev, addr, cmd, &data->byte, 1, 637 + FT260_FLAG_START_STOP); 638 + } 639 + break; 640 + case I2C_SMBUS_WORD_DATA: 641 + if (read_write == I2C_SMBUS_READ) { 642 + ret = ft260_smbus_write(dev, addr, cmd, NULL, 0, 643 + FT260_FLAG_START); 644 + if (ret) 645 + goto smbus_exit; 646 + 647 + ret = ft260_i2c_read(dev, addr, (u8 *)&data->word, 2, 648 + FT260_FLAG_START_STOP_REPEATED); 649 + } else { 650 + ret = ft260_smbus_write(dev, addr, cmd, 651 + (u8 *)&data->word, 2, 652 + FT260_FLAG_START_STOP); 653 + } 654 + break; 655 + case I2C_SMBUS_BLOCK_DATA: 656 + if (read_write == I2C_SMBUS_READ) { 657 + ret = ft260_smbus_write(dev, addr, cmd, NULL, 0, 658 + FT260_FLAG_START); 659 + if (ret) 660 + goto smbus_exit; 661 + 662 + ret = ft260_i2c_read(dev, addr, data->block, 663 + data->block[0] + 1, 664 + FT260_FLAG_START_STOP_REPEATED); 665 + } else { 666 + ret = ft260_smbus_write(dev, addr, cmd, data->block, 667 + data->block[0] + 1, 668 + FT260_FLAG_START_STOP); 669 + } 670 + break; 671 + case I2C_SMBUS_I2C_BLOCK_DATA: 672 + if (read_write == I2C_SMBUS_READ) { 673 + ret = ft260_smbus_write(dev, addr, cmd, NULL, 0, 674 + FT260_FLAG_START); 675 + if (ret) 676 + goto smbus_exit; 677 + 678 + ret = ft260_i2c_read(dev, addr, data->block + 1, 679 + data->block[0], 680 + FT260_FLAG_START_STOP_REPEATED); 681 + } else { 682 + ret = ft260_smbus_write(dev, addr, cmd, data->block + 1, 683 + data->block[0], 684 + FT260_FLAG_START_STOP); 685 + } 686 + break; 687 + default: 688 + hid_err(hdev, "unsupported smbus transaction size %d\n", size); 689 + ret = -EOPNOTSUPP; 690 + } 691 + 692 + smbus_exit: 693 + hid_hw_power(hdev, PM_HINT_NORMAL); 694 + mutex_unlock(&dev->lock); 695 + return ret; 696 + } 697 + 698 + static u32 ft260_functionality(struct i2c_adapter *adap) 699 + { 700 + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_QUICK | 701 + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 702 + I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK; 703 + } 704 + 705 + static const struct i2c_adapter_quirks ft260_i2c_quirks = { 706 + .flags = I2C_AQ_COMB_WRITE_THEN_READ, 707 + .max_comb_1st_msg_len = 2, 708 + }; 709 + 710 + static const struct i2c_algorithm ft260_i2c_algo = { 711 + .master_xfer = ft260_i2c_xfer, 712 + .smbus_xfer = ft260_smbus_xfer, 713 + .functionality = ft260_functionality, 714 + }; 715 + 716 + static int ft260_get_system_config(struct hid_device *hdev, 717 + struct ft260_get_system_status_report *cfg) 718 + { 719 + int ret; 720 + int len = sizeof(struct ft260_get_system_status_report); 721 + 722 + ret = ft260_hid_feature_report_get(hdev, FT260_SYSTEM_SETTINGS, 723 + (u8 *)cfg, len); 724 + if (ret != len) { 725 + hid_err(hdev, "failed to retrieve system status\n"); 726 + if (ret >= 0) 727 + return -EIO; 728 + } 729 + return 0; 730 + } 731 + 732 + static int ft260_is_interface_enabled(struct hid_device *hdev) 733 + { 734 + struct ft260_get_system_status_report cfg; 735 + struct usb_interface *usbif = to_usb_interface(hdev->dev.parent); 736 + int interface = usbif->cur_altsetting->desc.bInterfaceNumber; 737 + int ret; 738 + 739 + ret = ft260_get_system_config(hdev, &cfg); 740 + if (ret) 741 + return ret; 742 + 743 + ft260_dbg("interface: 0x%02x\n", interface); 744 + ft260_dbg("chip mode: 0x%02x\n", cfg.chip_mode); 745 + ft260_dbg("clock_ctl: 0x%02x\n", cfg.clock_ctl); 746 + ft260_dbg("i2c_enable: 0x%02x\n", cfg.i2c_enable); 747 + ft260_dbg("uart_mode: 0x%02x\n", cfg.uart_mode); 748 + 749 + switch (cfg.chip_mode) { 750 + case FT260_MODE_ALL: 751 + case FT260_MODE_BOTH: 752 + if (interface == 1) { 753 + hid_info(hdev, "uart interface is not supported\n"); 754 + return 0; 755 + } 756 + ret = 1; 757 + break; 758 + case FT260_MODE_UART: 759 + if (interface == 0) { 760 + hid_info(hdev, "uart is unsupported on interface 0\n"); 761 + ret = 0; 762 + } 763 + break; 764 + case FT260_MODE_I2C: 765 + if (interface == 1) { 766 + hid_info(hdev, "i2c is unsupported on interface 1\n"); 767 + ret = 0; 768 + } 769 + break; 770 + } 771 + return ret; 772 + } 773 + 774 + static int ft260_byte_show(struct hid_device *hdev, int id, u8 *cfg, int len, 775 + u8 *field, u8 *buf) 776 + { 777 + int ret; 778 + 779 + ret = ft260_hid_feature_report_get(hdev, id, cfg, len); 780 + if (ret != len && ret >= 0) 781 + return -EIO; 782 + 783 + return scnprintf(buf, PAGE_SIZE, "%hi\n", *field); 784 + } 785 + 786 + static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len, 787 + u16 *field, u8 *buf) 788 + { 789 + int ret; 790 + 791 + ret = ft260_hid_feature_report_get(hdev, id, cfg, len); 792 + if (ret != len && ret >= 0) 793 + return -EIO; 794 + 795 + return scnprintf(buf, PAGE_SIZE, "%hi\n", le16_to_cpu(*field)); 796 + } 797 + 798 + #define FT260_ATTR_SHOW(name, reptype, id, type, func) \ 799 + static ssize_t name##_show(struct device *kdev, \ 800 + struct device_attribute *attr, char *buf) \ 801 + { \ 802 + struct reptype rep; \ 803 + struct hid_device *hdev = to_hid_device(kdev); \ 804 + type *field = &rep.name; \ 805 + int len = sizeof(rep); \ 806 + \ 807 + return func(hdev, id, (u8 *)&rep, len, field, buf); \ 808 + } 809 + 810 + #define FT260_SSTAT_ATTR_SHOW(name) \ 811 + FT260_ATTR_SHOW(name, ft260_get_system_status_report, \ 812 + FT260_SYSTEM_SETTINGS, u8, ft260_byte_show) 813 + 814 + #define FT260_I2CST_ATTR_SHOW(name) \ 815 + FT260_ATTR_SHOW(name, ft260_get_i2c_status_report, \ 816 + FT260_I2C_STATUS, u16, ft260_word_show) 817 + 818 + #define FT260_ATTR_STORE(name, reptype, id, req, type, func) \ 819 + static ssize_t name##_store(struct device *kdev, \ 820 + struct device_attribute *attr, \ 821 + const char *buf, size_t count) \ 822 + { \ 823 + struct reptype rep; \ 824 + struct hid_device *hdev = to_hid_device(kdev); \ 825 + type name; \ 826 + int ret; \ 827 + \ 828 + if (!func(buf, 10, &name)) { \ 829 + rep.name = name; \ 830 + rep.report = id; \ 831 + rep.request = req; \ 832 + ret = ft260_hid_feature_report_set(hdev, (u8 *)&rep, \ 833 + sizeof(rep)); \ 834 + if (!ret) \ 835 + ret = count; \ 836 + } else { \ 837 + ret = -EINVAL; \ 838 + } \ 839 + return ret; \ 840 + } 841 + 842 + #define FT260_BYTE_ATTR_STORE(name, reptype, req) \ 843 + FT260_ATTR_STORE(name, reptype, FT260_SYSTEM_SETTINGS, req, \ 844 + u8, kstrtou8) 845 + 846 + #define FT260_WORD_ATTR_STORE(name, reptype, req) \ 847 + FT260_ATTR_STORE(name, reptype, FT260_SYSTEM_SETTINGS, req, \ 848 + u16, kstrtou16) 849 + 850 + FT260_SSTAT_ATTR_SHOW(chip_mode); 851 + static DEVICE_ATTR_RO(chip_mode); 852 + 853 + FT260_SSTAT_ATTR_SHOW(pwren_status); 854 + static DEVICE_ATTR_RO(pwren_status); 855 + 856 + FT260_SSTAT_ATTR_SHOW(suspend_status); 857 + static DEVICE_ATTR_RO(suspend_status); 858 + 859 + FT260_SSTAT_ATTR_SHOW(hid_over_i2c_en); 860 + static DEVICE_ATTR_RO(hid_over_i2c_en); 861 + 862 + FT260_SSTAT_ATTR_SHOW(power_saving_en); 863 + static DEVICE_ATTR_RO(power_saving_en); 864 + 865 + FT260_SSTAT_ATTR_SHOW(i2c_enable); 866 + FT260_BYTE_ATTR_STORE(i2c_enable, ft260_set_i2c_mode_report, 867 + FT260_SET_I2C_MODE); 868 + static DEVICE_ATTR_RW(i2c_enable); 869 + 870 + FT260_SSTAT_ATTR_SHOW(uart_mode); 871 + FT260_BYTE_ATTR_STORE(uart_mode, ft260_set_uart_mode_report, 872 + FT260_SET_UART_MODE); 873 + static DEVICE_ATTR_RW(uart_mode); 874 + 875 + FT260_SSTAT_ATTR_SHOW(clock_ctl); 876 + FT260_BYTE_ATTR_STORE(clock_ctl, ft260_set_system_clock_report, 877 + FT260_SET_CLOCK); 878 + static DEVICE_ATTR_RW(clock_ctl); 879 + 880 + FT260_I2CST_ATTR_SHOW(clock); 881 + FT260_WORD_ATTR_STORE(clock, ft260_set_i2c_speed_report, 882 + FT260_SET_I2C_CLOCK_SPEED); 883 + static DEVICE_ATTR_RW(clock); 884 + 885 + static ssize_t i2c_reset_store(struct device *kdev, 886 + struct device_attribute *attr, const char *buf, 887 + size_t count) 888 + { 889 + struct hid_device *hdev = to_hid_device(kdev); 890 + int ret = ft260_i2c_reset(hdev); 891 + 892 + if (ret) 893 + return ret; 894 + return count; 895 + } 896 + static DEVICE_ATTR_WO(i2c_reset); 897 + 898 + static const struct attribute_group ft260_attr_group = { 899 + .attrs = (struct attribute *[]) { 900 + &dev_attr_chip_mode.attr, 901 + &dev_attr_pwren_status.attr, 902 + &dev_attr_suspend_status.attr, 903 + &dev_attr_hid_over_i2c_en.attr, 904 + &dev_attr_power_saving_en.attr, 905 + &dev_attr_i2c_enable.attr, 906 + &dev_attr_uart_mode.attr, 907 + &dev_attr_clock_ctl.attr, 908 + &dev_attr_i2c_reset.attr, 909 + &dev_attr_clock.attr, 910 + NULL 911 + } 912 + }; 913 + 914 + static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id) 915 + { 916 + struct ft260_device *dev; 917 + struct ft260_get_chip_version_report version; 918 + int ret; 919 + 920 + dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); 921 + if (!dev) 922 + return -ENOMEM; 923 + 924 + ret = hid_parse(hdev); 925 + if (ret) { 926 + hid_err(hdev, "failed to parse HID\n"); 927 + return ret; 928 + } 929 + 930 + ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); 931 + if (ret) { 932 + hid_err(hdev, "failed to start HID HW\n"); 933 + return ret; 934 + } 935 + 936 + ret = hid_hw_open(hdev); 937 + if (ret) { 938 + hid_err(hdev, "failed to open HID HW\n"); 939 + goto err_hid_stop; 940 + } 941 + 942 + ret = ft260_hid_feature_report_get(hdev, FT260_CHIP_VERSION, 943 + (u8 *)&version, sizeof(version)); 944 + if (ret != sizeof(version)) { 945 + hid_err(hdev, "failed to retrieve chip version\n"); 946 + if (ret >= 0) 947 + ret = -EIO; 948 + goto err_hid_close; 949 + } 950 + 951 + hid_info(hdev, "chip code: %02x%02x %02x%02x\n", 952 + version.chip_code[0], version.chip_code[1], 953 + version.chip_code[2], version.chip_code[3]); 954 + 955 + ret = ft260_is_interface_enabled(hdev); 956 + if (ret <= 0) 957 + goto err_hid_close; 958 + 959 + hid_set_drvdata(hdev, dev); 960 + dev->hdev = hdev; 961 + dev->adap.owner = THIS_MODULE; 962 + dev->adap.class = I2C_CLASS_HWMON; 963 + dev->adap.algo = &ft260_i2c_algo; 964 + dev->adap.quirks = &ft260_i2c_quirks; 965 + dev->adap.dev.parent = &hdev->dev; 966 + snprintf(dev->adap.name, sizeof(dev->adap.name), 967 + "FT260 usb-i2c bridge on hidraw%d", 968 + ((struct hidraw *)hdev->hidraw)->minor); 969 + 970 + mutex_init(&dev->lock); 971 + init_completion(&dev->wait); 972 + 973 + ret = i2c_add_adapter(&dev->adap); 974 + if (ret) { 975 + hid_err(hdev, "failed to add i2c adapter\n"); 976 + goto err_hid_close; 977 + } 978 + 979 + i2c_set_adapdata(&dev->adap, dev); 980 + 981 + ret = sysfs_create_group(&hdev->dev.kobj, &ft260_attr_group); 982 + if (ret < 0) { 983 + hid_err(hdev, "failed to create sysfs attrs\n"); 984 + goto err_i2c_free; 985 + } 986 + 987 + ret = ft260_xfer_status(dev); 988 + if (ret) 989 + ft260_i2c_reset(hdev); 990 + 991 + return 0; 992 + 993 + err_i2c_free: 994 + i2c_del_adapter(&dev->adap); 995 + err_hid_close: 996 + hid_hw_close(hdev); 997 + err_hid_stop: 998 + hid_hw_stop(hdev); 999 + return ret; 1000 + } 1001 + 1002 + static void ft260_remove(struct hid_device *hdev) 1003 + { 1004 + int ret; 1005 + struct ft260_device *dev = hid_get_drvdata(hdev); 1006 + 1007 + ret = ft260_is_interface_enabled(hdev); 1008 + if (ret <= 0) 1009 + return; 1010 + 1011 + sysfs_remove_group(&hdev->dev.kobj, &ft260_attr_group); 1012 + i2c_del_adapter(&dev->adap); 1013 + 1014 + hid_hw_close(hdev); 1015 + hid_hw_stop(hdev); 1016 + } 1017 + 1018 + static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report, 1019 + u8 *data, int size) 1020 + { 1021 + struct ft260_device *dev = hid_get_drvdata(hdev); 1022 + struct ft260_i2c_input_report *xfer = (void *)data; 1023 + 1024 + if (xfer->report >= FT260_I2C_REPORT_MIN && 1025 + xfer->report <= FT260_I2C_REPORT_MAX) { 1026 + ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report, 1027 + xfer->length); 1028 + 1029 + memcpy(&dev->read_buf[dev->read_idx], &xfer->data, 1030 + xfer->length); 1031 + dev->read_idx += xfer->length; 1032 + 1033 + if (dev->read_idx == dev->read_len) 1034 + complete(&dev->wait); 1035 + 1036 + } else { 1037 + hid_err(hdev, "unknown report: %#02x\n", xfer->report); 1038 + return 0; 1039 + } 1040 + return 1; 1041 + } 1042 + 1043 + static struct hid_driver ft260_driver = { 1044 + .name = "ft260", 1045 + .id_table = ft260_devices, 1046 + .probe = ft260_probe, 1047 + .remove = ft260_remove, 1048 + .raw_event = ft260_raw_event, 1049 + }; 1050 + 1051 + module_hid_driver(ft260_driver); 1052 + MODULE_DESCRIPTION("FTDI FT260 USB HID to I2C host bridge"); 1053 + MODULE_AUTHOR("Michael Zaidman <michael.zaidman@gmail.com>"); 1054 + MODULE_LICENSE("GPL v2");
+12 -2
drivers/hid/hid-ids.h
··· 93 93 #define BT_VENDOR_ID_APPLE 0x004c 94 94 #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 95 95 #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d 96 + #define USB_DEVICE_ID_APPLE_MAGICMOUSE2 0x0269 96 97 #define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e 97 98 #define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 0x0265 98 99 #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e ··· 432 431 433 432 #define USB_VENDOR_ID_FUTURE_TECHNOLOGY 0x0403 434 433 #define USB_DEVICE_ID_RETRODE2 0x97c1 434 + #define USB_DEVICE_ID_FT260 0x6030 435 435 436 436 #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f 437 437 #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 ··· 810 808 #define USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER 0xc51b 811 809 #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER 0xc52b 812 810 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER 0xc52f 811 + #define USB_DEVICE_ID_LOGITECH_G700_RECEIVER 0xc531 813 812 #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532 814 813 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534 815 814 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1 0xc539 ··· 819 816 #define USB_DEVICE_ID_SPACETRAVELLER 0xc623 820 817 #define USB_DEVICE_ID_SPACENAVIGATOR 0xc626 821 818 #define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704 822 - #define USB_DEVICE_ID_DINOVO_EDGE 0xc714 823 - #define USB_DEVICE_ID_DINOVO_MINI 0xc71f 819 + #define USB_DEVICE_ID_MX5000_RECEIVER_MOUSE_DEV 0xc70a 820 + #define USB_DEVICE_ID_MX5000_RECEIVER_KBD_DEV 0xc70e 821 + #define USB_DEVICE_ID_DINOVO_EDGE_RECEIVER_KBD_DEV 0xc713 822 + #define USB_DEVICE_ID_DINOVO_EDGE_RECEIVER_MOUSE_DEV 0xc714 823 + #define USB_DEVICE_ID_MX5500_RECEIVER_KBD_DEV 0xc71b 824 + #define USB_DEVICE_ID_MX5500_RECEIVER_MOUSE_DEV 0xc71c 825 + #define USB_DEVICE_ID_DINOVO_MINI_RECEIVER_KBD_DEV 0xc71e 826 + #define USB_DEVICE_ID_DINOVO_MINI_RECEIVER_MOUSE_DEV 0xc71f 824 827 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03 825 828 #define USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL 0xca04 826 829 ··· 955 946 #define USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S 0x8003 956 947 957 948 #define USB_VENDOR_ID_PLANTRONICS 0x047f 949 + #define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES 0xc056 958 950 959 951 #define USB_VENDOR_ID_PANASONIC 0x04da 960 952 #define USB_DEVICE_ID_PANABOARD_UBT780 0x1044
+16 -6
drivers/hid/hid-input.c
··· 435 435 return ret; 436 436 } 437 437 438 - static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field) 438 + static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, 439 + struct hid_field *field, bool is_percentage) 439 440 { 440 441 struct power_supply_desc *psy_desc; 441 442 struct power_supply_config psy_cfg = { .drv_data = dev, }; ··· 476 475 min = field->logical_minimum; 477 476 max = field->logical_maximum; 478 477 479 - if (quirks & HID_BATTERY_QUIRK_PERCENT) { 478 + if (is_percentage || (quirks & HID_BATTERY_QUIRK_PERCENT)) { 480 479 min = 0; 481 480 max = 100; 482 481 } ··· 553 552 } 554 553 #else /* !CONFIG_HID_BATTERY_STRENGTH */ 555 554 static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, 556 - struct hid_field *field) 555 + struct hid_field *field, bool is_percentage) 557 556 { 558 557 return 0; 559 558 } ··· 807 806 break; 808 807 809 808 case 0x3b: /* Battery Strength */ 810 - hidinput_setup_battery(device, HID_INPUT_REPORT, field); 809 + hidinput_setup_battery(device, HID_INPUT_REPORT, field, false); 811 810 usage->type = EV_PWR; 812 811 return; 813 812 ··· 1069 1068 case HID_UP_GENDEVCTRLS: 1070 1069 switch (usage->hid) { 1071 1070 case HID_DC_BATTERYSTRENGTH: 1072 - hidinput_setup_battery(device, HID_INPUT_REPORT, field); 1071 + hidinput_setup_battery(device, HID_INPUT_REPORT, field, false); 1072 + usage->type = EV_PWR; 1073 + return; 1074 + } 1075 + goto unknown; 1076 + 1077 + case HID_UP_BATTERY: 1078 + switch (usage->hid) { 1079 + case HID_BAT_ABSOLUTESTATEOFCHARGE: 1080 + hidinput_setup_battery(device, HID_INPUT_REPORT, field, true); 1073 1081 usage->type = EV_PWR; 1074 1082 return; 1075 1083 } ··· 1682 1672 /* Verify if Battery Strength feature is available */ 1683 1673 if (usage->hid == HID_DC_BATTERYSTRENGTH) 1684 1674 hidinput_setup_battery(hid, HID_FEATURE_REPORT, 1685 - rep->field[i]); 1675 + rep->field[i], false); 1686 1676 1687 1677 if (drv->feature_mapping) 1688 1678 drv->feature_mapping(hid, rep->field[i], usage);
+1 -1
drivers/hid/hid-kye.c
··· 655 655 } 656 656 657 657 /** 658 - * Enable fully-functional tablet mode by setting a special feature report. 658 + * kye_tablet_enable() - Enable fully-functional tablet mode by setting a special feature report. 659 659 * 660 660 * @hdev: HID device 661 661 *
+114 -33
drivers/hid/hid-lenovo.c
··· 33 33 34 34 #include "hid-ids.h" 35 35 36 + /* Userspace expects F20 for mic-mute KEY_MICMUTE does not work */ 37 + #define LENOVO_KEY_MICMUTE KEY_F20 38 + 36 39 struct lenovo_drvdata { 37 40 u8 led_report[3]; /* Must be first for proper alignment */ 38 41 int led_state; ··· 65 62 #define TP10UBKBD_LED_OFF 1 66 63 #define TP10UBKBD_LED_ON 2 67 64 68 - static void lenovo_led_set_tp10ubkbd(struct hid_device *hdev, u8 led_code, 69 - enum led_brightness value) 65 + static int lenovo_led_set_tp10ubkbd(struct hid_device *hdev, u8 led_code, 66 + enum led_brightness value) 70 67 { 71 68 struct lenovo_drvdata *data = hid_get_drvdata(hdev); 72 69 int ret; ··· 78 75 data->led_report[2] = value ? TP10UBKBD_LED_ON : TP10UBKBD_LED_OFF; 79 76 ret = hid_hw_raw_request(hdev, data->led_report[0], data->led_report, 3, 80 77 HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 81 - if (ret) 82 - hid_err(hdev, "Set LED output report error: %d\n", ret); 78 + if (ret != 3) { 79 + if (ret != -ENODEV) 80 + hid_err(hdev, "Set LED output report error: %d\n", ret); 81 + 82 + ret = ret < 0 ? ret : -EIO; 83 + } else { 84 + ret = 0; 85 + } 83 86 84 87 mutex_unlock(&data->led_report_mutex); 88 + 89 + return ret; 85 90 } 86 91 87 92 static void lenovo_tp10ubkbd_sync_fn_lock(struct work_struct *work) ··· 137 126 if (usage->hid == (HID_UP_BUTTON | 0x0010)) { 138 127 /* This sub-device contains trackpoint, mark it */ 139 128 hid_set_drvdata(hdev, (void *)1); 140 - map_key_clear(KEY_MICMUTE); 129 + map_key_clear(LENOVO_KEY_MICMUTE); 141 130 return 1; 142 131 } 143 132 return 0; ··· 152 141 (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) { 153 142 switch (usage->hid & HID_USAGE) { 154 143 case 0x00f1: /* Fn-F4: Mic mute */ 155 - map_key_clear(KEY_MICMUTE); 144 + map_key_clear(LENOVO_KEY_MICMUTE); 156 145 return 1; 157 146 case 0x00f2: /* Fn-F5: Brightness down */ 158 147 map_key_clear(KEY_BRIGHTNESSDOWN); ··· 242 231 map_key_clear(KEY_FN_ESC); 243 232 return 1; 244 233 case 9: /* Fn-F4: Mic mute */ 245 - map_key_clear(KEY_MICMUTE); 234 + map_key_clear(LENOVO_KEY_MICMUTE); 246 235 return 1; 247 236 case 10: /* Fn-F7: Control panel */ 248 237 map_key_clear(KEY_CONFIG); ··· 262 251 */ 263 252 if (usage->hid == 0x00070072) 264 253 return -1; 254 + 255 + return 0; 256 + } 257 + 258 + static int lenovo_input_mapping_x1_tab_kbd(struct hid_device *hdev, 259 + struct hid_input *hi, struct hid_field *field, 260 + struct hid_usage *usage, unsigned long **bit, int *max) 261 + { 262 + /* 263 + * The ThinkPad X1 Tablet Thin Keyboard uses 0x000c0001 usage for 264 + * a bunch of keys which have no standard consumer page code. 265 + */ 266 + if (usage->hid == 0x000c0001) { 267 + switch (usage->usage_index) { 268 + case 0: /* Fn-F10: Enable/disable bluetooth */ 269 + map_key_clear(KEY_BLUETOOTH); 270 + return 1; 271 + case 1: /* Fn-F11: Keyboard settings */ 272 + map_key_clear(KEY_KEYBOARD); 273 + return 1; 274 + case 2: /* Fn-F12: User function / Cortana */ 275 + map_key_clear(KEY_MACRO1); 276 + return 1; 277 + case 3: /* Fn-PrtSc: Snipping tool */ 278 + map_key_clear(KEY_SELECTIVE_SCREENSHOT); 279 + return 1; 280 + case 8: /* Fn-Esc: Fn-lock toggle */ 281 + map_key_clear(KEY_FN_ESC); 282 + return 1; 283 + case 9: /* Fn-F4: Mute/unmute microphone */ 284 + map_key_clear(KEY_MICMUTE); 285 + return 1; 286 + case 10: /* Fn-F9: Settings */ 287 + map_key_clear(KEY_CONFIG); 288 + return 1; 289 + case 13: /* Fn-F7: Manage external displays */ 290 + map_key_clear(KEY_SWITCHVIDEOMODE); 291 + return 1; 292 + case 14: /* Fn-F8: Enable/disable wifi */ 293 + map_key_clear(KEY_WLAN); 294 + return 1; 295 + } 296 + } 297 + 298 + if (usage->hid == (HID_UP_KEYBOARD | 0x009a)) { 299 + map_key_clear(KEY_SYSRQ); 300 + return 1; 301 + } 265 302 266 303 return 0; 267 304 } ··· 337 278 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 338 279 return lenovo_input_mapping_tp10_ultrabook_kbd(hdev, hi, field, 339 280 usage, bit, max); 281 + case USB_DEVICE_ID_LENOVO_X1_TAB: 282 + return lenovo_input_mapping_x1_tab_kbd(hdev, hi, field, usage, bit, max); 340 283 default: 341 284 return 0; 342 285 } ··· 410 349 { 411 350 struct hid_device *hdev = to_hid_device(dev); 412 351 struct lenovo_drvdata *data = hid_get_drvdata(hdev); 413 - int value; 352 + int value, ret; 414 353 415 354 if (kstrtoint(buf, 10, &value)) 416 355 return -EINVAL; ··· 425 364 lenovo_features_set_cptkbd(hdev); 426 365 break; 427 366 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 428 - lenovo_led_set_tp10ubkbd(hdev, TP10UBKBD_FN_LOCK_LED, value); 367 + case USB_DEVICE_ID_LENOVO_X1_TAB: 368 + ret = lenovo_led_set_tp10ubkbd(hdev, TP10UBKBD_FN_LOCK_LED, value); 369 + if (ret) 370 + return ret; 429 371 break; 430 372 } 431 373 ··· 562 498 static int lenovo_event(struct hid_device *hdev, struct hid_field *field, 563 499 struct hid_usage *usage, __s32 value) 564 500 { 501 + if (!hid_get_drvdata(hdev)) 502 + return 0; 503 + 565 504 switch (hdev->product) { 566 505 case USB_DEVICE_ID_LENOVO_CUSBKBD: 567 506 case USB_DEVICE_ID_LENOVO_CBTKBD: 568 507 return lenovo_event_cptkbd(hdev, field, usage, value); 569 508 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 509 + case USB_DEVICE_ID_LENOVO_X1_TAB: 570 510 return lenovo_event_tp10ubkbd(hdev, field, usage, value); 571 511 default: 572 512 return 0; ··· 829 761 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 830 762 } 831 763 832 - static enum led_brightness lenovo_led_brightness_get( 833 - struct led_classdev *led_cdev) 834 - { 835 - struct device *dev = led_cdev->dev->parent; 836 - struct hid_device *hdev = to_hid_device(dev); 837 - struct lenovo_drvdata *data_pointer = hid_get_drvdata(hdev); 838 - int led_nr = 0; 839 - 840 - if (led_cdev == &data_pointer->led_micmute) 841 - led_nr = 1; 842 - 843 - return data_pointer->led_state & (1 << led_nr) 844 - ? LED_FULL 845 - : LED_OFF; 846 - } 847 - 848 - static void lenovo_led_brightness_set(struct led_classdev *led_cdev, 764 + static int lenovo_led_brightness_set(struct led_classdev *led_cdev, 849 765 enum led_brightness value) 850 766 { 851 767 struct device *dev = led_cdev->dev->parent; ··· 837 785 struct lenovo_drvdata *data_pointer = hid_get_drvdata(hdev); 838 786 u8 tp10ubkbd_led[] = { TP10UBKBD_MUTE_LED, TP10UBKBD_MICMUTE_LED }; 839 787 int led_nr = 0; 788 + int ret = 0; 840 789 841 790 if (led_cdev == &data_pointer->led_micmute) 842 791 led_nr = 1; ··· 852 799 lenovo_led_set_tpkbd(hdev); 853 800 break; 854 801 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 855 - lenovo_led_set_tp10ubkbd(hdev, tp10ubkbd_led[led_nr], value); 802 + case USB_DEVICE_ID_LENOVO_X1_TAB: 803 + ret = lenovo_led_set_tp10ubkbd(hdev, tp10ubkbd_led[led_nr], value); 856 804 break; 857 805 } 806 + 807 + return ret; 858 808 } 859 809 860 810 static int lenovo_register_leds(struct hid_device *hdev) ··· 877 821 snprintf(name_micm, name_sz, "%s:amber:micmute", dev_name(&hdev->dev)); 878 822 879 823 data->led_mute.name = name_mute; 880 - data->led_mute.brightness_get = lenovo_led_brightness_get; 881 - data->led_mute.brightness_set = lenovo_led_brightness_set; 824 + data->led_mute.default_trigger = "audio-mute"; 825 + data->led_mute.brightness_set_blocking = lenovo_led_brightness_set; 826 + data->led_mute.max_brightness = 1; 827 + data->led_mute.flags = LED_HW_PLUGGABLE; 882 828 data->led_mute.dev = &hdev->dev; 883 829 ret = led_classdev_register(&hdev->dev, &data->led_mute); 884 830 if (ret < 0) 885 831 return ret; 886 832 887 833 data->led_micmute.name = name_micm; 888 - data->led_micmute.brightness_get = lenovo_led_brightness_get; 889 - data->led_micmute.brightness_set = lenovo_led_brightness_set; 834 + data->led_micmute.default_trigger = "audio-micmute"; 835 + data->led_micmute.brightness_set_blocking = lenovo_led_brightness_set; 836 + data->led_micmute.max_brightness = 1; 837 + data->led_micmute.flags = LED_HW_PLUGGABLE; 890 838 data->led_micmute.dev = &hdev->dev; 891 839 ret = led_classdev_register(&hdev->dev, &data->led_micmute); 892 840 if (ret < 0) { ··· 1012 952 1013 953 static int lenovo_probe_tp10ubkbd(struct hid_device *hdev) 1014 954 { 955 + struct hid_report_enum *rep_enum; 1015 956 struct lenovo_drvdata *data; 957 + struct hid_report *rep; 958 + bool found; 1016 959 int ret; 1017 960 1018 - /* All the custom action happens on the USBMOUSE device for USB */ 1019 - if (hdev->type != HID_TYPE_USBMOUSE) 961 + /* 962 + * The LEDs and the Fn-lock functionality use output report 9, 963 + * with an application of 0xffa0001, add the LEDs on the interface 964 + * with this output report. 965 + */ 966 + found = false; 967 + rep_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; 968 + list_for_each_entry(rep, &rep_enum->report_list, list) { 969 + if (rep->application == 0xffa00001) 970 + found = true; 971 + } 972 + if (!found) 1020 973 return 0; 1021 974 1022 975 data = devm_kzalloc(&hdev->dev, sizeof(*data), GFP_KERNEL); ··· 1091 1018 ret = lenovo_probe_cptkbd(hdev); 1092 1019 break; 1093 1020 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 1021 + case USB_DEVICE_ID_LENOVO_X1_TAB: 1094 1022 ret = lenovo_probe_tp10ubkbd(hdev); 1095 1023 break; 1096 1024 default: ··· 1157 1083 lenovo_remove_cptkbd(hdev); 1158 1084 break; 1159 1085 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 1086 + case USB_DEVICE_ID_LENOVO_X1_TAB: 1160 1087 lenovo_remove_tp10ubkbd(hdev); 1161 1088 break; 1162 1089 } ··· 1197 1122 { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO) }, 1198 1123 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL) }, 1199 1124 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TP10UBKBD) }, 1125 + /* 1126 + * Note bind to the HID_GROUP_GENERIC group, so that we only bind to the keyboard 1127 + * part, while letting hid-multitouch.c handle the touchpad and trackpoint. 1128 + */ 1129 + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, 1130 + USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB) }, 1200 1131 { } 1201 1132 }; 1202 1133
-24
drivers/hid/hid-lg.c
··· 568 568 return 1; 569 569 } 570 570 571 - static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage, 572 - unsigned long **bit, int *max) 573 - { 574 - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) 575 - return 0; 576 - 577 - switch (usage->hid & HID_USAGE) { 578 - 579 - case 0x00d: lg_map_key_clear(KEY_MEDIA); break; 580 - default: 581 - return 0; 582 - 583 - } 584 - return 1; 585 - } 586 - 587 571 static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage, 588 572 unsigned long **bit, int *max) 589 573 { ··· 650 666 651 667 if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER && 652 668 lg_ultrax_remote_mapping(hi, usage, bit, max)) 653 - return 1; 654 - 655 - if (hdev->product == USB_DEVICE_ID_DINOVO_MINI && 656 - lg_dinovo_mapping(hi, usage, bit, max)) 657 669 return 1; 658 670 659 671 if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max)) ··· 858 878 .driver_data = LG_BAD_RELATIVE_KEYS }, 859 879 860 880 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP), 861 - .driver_data = LG_DUPLICATE_USAGES }, 862 - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE), 863 - .driver_data = LG_DUPLICATE_USAGES }, 864 - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI), 865 881 .driver_data = LG_DUPLICATE_USAGES }, 866 882 867 883 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
+114 -23
drivers/hid/hid-logitech-dj.c
··· 84 84 #define STD_MOUSE BIT(2) 85 85 #define MULTIMEDIA BIT(3) 86 86 #define POWER_KEYS BIT(4) 87 + #define KBD_MOUSE BIT(5) 87 88 #define MEDIA_CENTER BIT(8) 88 89 #define KBD_LEDS BIT(14) 89 90 /* Fake (bitnr > NUMBER_OF_HID_REPORTS) bit to track HID++ capability */ ··· 118 117 recvr_type_mouse_only, 119 118 recvr_type_27mhz, 120 119 recvr_type_bluetooth, 120 + recvr_type_dinovo, 121 121 }; 122 122 123 123 struct dj_report { ··· 335 333 0xC0, /* END_COLLECTION */ 336 334 }; 337 335 336 + /* Mouse descriptor (5) for Bluetooth receiver, normal-res hwheel, 8 buttons */ 337 + static const char mse5_bluetooth_descriptor[] = { 338 + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ 339 + 0x09, 0x02, /* Usage (Mouse) */ 340 + 0xa1, 0x01, /* Collection (Application) */ 341 + 0x85, 0x05, /* Report ID (5) */ 342 + 0x09, 0x01, /* Usage (Pointer) */ 343 + 0xa1, 0x00, /* Collection (Physical) */ 344 + 0x05, 0x09, /* Usage Page (Button) */ 345 + 0x19, 0x01, /* Usage Minimum (1) */ 346 + 0x29, 0x08, /* Usage Maximum (8) */ 347 + 0x15, 0x00, /* Logical Minimum (0) */ 348 + 0x25, 0x01, /* Logical Maximum (1) */ 349 + 0x95, 0x08, /* Report Count (8) */ 350 + 0x75, 0x01, /* Report Size (1) */ 351 + 0x81, 0x02, /* Input (Data,Var,Abs) */ 352 + 0x05, 0x01, /* Usage Page (Generic Desktop) */ 353 + 0x16, 0x01, 0xf8, /* Logical Minimum (-2047) */ 354 + 0x26, 0xff, 0x07, /* Logical Maximum (2047) */ 355 + 0x75, 0x0c, /* Report Size (12) */ 356 + 0x95, 0x02, /* Report Count (2) */ 357 + 0x09, 0x30, /* Usage (X) */ 358 + 0x09, 0x31, /* Usage (Y) */ 359 + 0x81, 0x06, /* Input (Data,Var,Rel) */ 360 + 0x15, 0x81, /* Logical Minimum (-127) */ 361 + 0x25, 0x7f, /* Logical Maximum (127) */ 362 + 0x75, 0x08, /* Report Size (8) */ 363 + 0x95, 0x01, /* Report Count (1) */ 364 + 0x09, 0x38, /* Usage (Wheel) */ 365 + 0x81, 0x06, /* Input (Data,Var,Rel) */ 366 + 0x05, 0x0c, /* Usage Page (Consumer Devices) */ 367 + 0x0a, 0x38, 0x02, /* Usage (AC Pan) */ 368 + 0x15, 0x81, /* Logical Minimum (-127) */ 369 + 0x25, 0x7f, /* Logical Maximum (127) */ 370 + 0x75, 0x08, /* Report Size (8) */ 371 + 0x95, 0x01, /* Report Count (1) */ 372 + 0x81, 0x06, /* Input (Data,Var,Rel) */ 373 + 0xc0, /* End Collection */ 374 + 0xc0, /* End Collection */ 375 + }; 376 + 338 377 /* Gaming Mouse descriptor (2) */ 339 378 static const char mse_high_res_descriptor[] = { 340 379 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ ··· 523 480 #define MAX_RDESC_SIZE \ 524 481 (sizeof(kbd_descriptor) + \ 525 482 sizeof(mse_bluetooth_descriptor) + \ 483 + sizeof(mse5_bluetooth_descriptor) + \ 526 484 sizeof(consumer_descriptor) + \ 527 485 sizeof(syscontrol_descriptor) + \ 528 486 sizeof(media_descriptor) + \ ··· 561 517 static LIST_HEAD(dj_hdev_list); 562 518 static DEFINE_MUTEX(dj_hdev_list_lock); 563 519 520 + static bool recvr_type_is_bluetooth(enum recvr_type type) 521 + { 522 + return type == recvr_type_bluetooth || type == recvr_type_dinovo; 523 + } 524 + 564 525 /* 565 526 * dj/HID++ receivers are really a single logical entity, but for BIOS/Windows 566 527 * compatibility they have multiple USB interfaces. On HID++ receivers we need ··· 583 534 * The bluetooth receiver contains a built-in hub and has separate 584 535 * USB-devices for the keyboard and mouse interfaces. 585 536 */ 586 - sep = (type == recvr_type_bluetooth) ? '.' : '/'; 537 + sep = recvr_type_is_bluetooth(type) ? '.' : '/'; 587 538 588 539 /* Try to find an already-probed interface from the same device */ 589 540 list_for_each_entry(djrcv_dev, &dj_hdev_list, list) { ··· 921 872 * touchpad to work we must also forward mouse input reports to the dj_hiddev 922 873 * created for the keyboard (instead of forwarding them to a second paired 923 874 * device with a device_type of REPORT_TYPE_MOUSE as we normally would). 875 + * 876 + * On Dinovo receivers the keyboard's touchpad and an optional paired actual 877 + * mouse send separate input reports, INPUT(2) aka STD_MOUSE for the mouse 878 + * and INPUT(5) aka KBD_MOUSE for the keyboard's touchpad. 879 + * 880 + * On MX5x00 receivers (which can also be paired with a Dinovo keyboard) 881 + * INPUT(2) is used for both an optional paired actual mouse and for the 882 + * keyboard's touchpad. 924 883 */ 925 884 static const u16 kbd_builtin_touchpad_ids[] = { 926 885 0xb309, /* Dinovo Edge */ ··· 955 898 id = (workitem->quad_id_msb << 8) | workitem->quad_id_lsb; 956 899 for (i = 0; i < ARRAY_SIZE(kbd_builtin_touchpad_ids); i++) { 957 900 if (id == kbd_builtin_touchpad_ids[i]) { 958 - workitem->reports_supported |= STD_MOUSE; 901 + if (djrcv_dev->type == recvr_type_dinovo) 902 + workitem->reports_supported |= KBD_MOUSE; 903 + else 904 + workitem->reports_supported |= STD_MOUSE; 959 905 break; 960 906 } 961 907 } ··· 1427 1367 else if (djdev->dj_receiver_dev->type == recvr_type_27mhz) 1428 1368 rdcat(rdesc, &rsize, mse_27mhz_descriptor, 1429 1369 sizeof(mse_27mhz_descriptor)); 1430 - else if (djdev->dj_receiver_dev->type == recvr_type_bluetooth) 1370 + else if (recvr_type_is_bluetooth(djdev->dj_receiver_dev->type)) 1431 1371 rdcat(rdesc, &rsize, mse_bluetooth_descriptor, 1432 1372 sizeof(mse_bluetooth_descriptor)); 1433 1373 else 1434 1374 rdcat(rdesc, &rsize, mse_descriptor, 1435 1375 sizeof(mse_descriptor)); 1376 + } 1377 + 1378 + if (djdev->reports_supported & KBD_MOUSE) { 1379 + dbg_hid("%s: sending a kbd-mouse descriptor, reports_supported: %llx\n", 1380 + __func__, djdev->reports_supported); 1381 + rdcat(rdesc, &rsize, mse5_bluetooth_descriptor, 1382 + sizeof(mse5_bluetooth_descriptor)); 1436 1383 } 1437 1384 1438 1385 if (djdev->reports_supported & MULTIMEDIA) { ··· 1759 1692 case recvr_type_mouse_only: no_dj_interfaces = 2; break; 1760 1693 case recvr_type_27mhz: no_dj_interfaces = 2; break; 1761 1694 case recvr_type_bluetooth: no_dj_interfaces = 2; break; 1695 + case recvr_type_dinovo: no_dj_interfaces = 2; break; 1762 1696 } 1763 1697 if (hid_is_using_ll_driver(hdev, &usb_hid_driver)) { 1764 1698 intf = to_usb_interface(hdev->dev.parent); ··· 1925 1857 } 1926 1858 1927 1859 static const struct hid_device_id logi_dj_receivers[] = { 1928 - {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1860 + { /* Logitech unifying receiver (0xc52b) */ 1861 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1929 1862 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER), 1930 1863 .driver_data = recvr_type_dj}, 1931 - {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1864 + { /* Logitech unifying receiver (0xc532) */ 1865 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1932 1866 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2), 1933 1867 .driver_data = recvr_type_dj}, 1934 - { /* Logitech Nano mouse only receiver */ 1868 + 1869 + { /* Logitech Nano mouse only receiver (0xc52f) */ 1935 1870 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1936 1871 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER), 1937 1872 .driver_data = recvr_type_mouse_only}, 1938 - { /* Logitech Nano (non DJ) receiver */ 1873 + { /* Logitech Nano (non DJ) receiver (0xc534) */ 1939 1874 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1940 1875 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2), 1941 1876 .driver_data = recvr_type_hidpp}, 1877 + 1942 1878 { /* Logitech G700(s) receiver (0xc531) */ 1943 1879 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1944 - 0xc531), 1880 + USB_DEVICE_ID_LOGITECH_G700_RECEIVER), 1945 1881 .driver_data = recvr_type_gaming_hidpp}, 1946 1882 { /* Logitech G602 receiver (0xc537) */ 1947 1883 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, ··· 1955 1883 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1956 1884 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1), 1957 1885 .driver_data = recvr_type_gaming_hidpp}, 1958 - { /* Logitech lightspeed receiver (0xc53f) */ 1959 - HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1960 - USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1), 1961 - .driver_data = recvr_type_gaming_hidpp}, 1962 - { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */ 1963 - HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), 1964 - .driver_data = recvr_type_27mhz}, 1965 1886 { /* Logitech powerplay receiver (0xc53a) */ 1966 1887 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1967 1888 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY), 1968 1889 .driver_data = recvr_type_gaming_hidpp}, 1890 + { /* Logitech lightspeed receiver (0xc53f) */ 1891 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1892 + USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1), 1893 + .driver_data = recvr_type_gaming_hidpp}, 1894 + 1895 + { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */ 1896 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), 1897 + .driver_data = recvr_type_27mhz}, 1969 1898 { /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */ 1970 1899 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1971 1900 USB_DEVICE_ID_S510_RECEIVER_2), ··· 1975 1902 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1976 1903 USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER), 1977 1904 .driver_data = recvr_type_27mhz}, 1978 - { /* Logitech MX5000 HID++ / bluetooth receiver keyboard intf. */ 1905 + 1906 + { /* Logitech MX5000 HID++ / bluetooth receiver keyboard intf. (0xc70e) */ 1979 1907 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1980 - 0xc70e), 1908 + USB_DEVICE_ID_MX5000_RECEIVER_KBD_DEV), 1981 1909 .driver_data = recvr_type_bluetooth}, 1982 - { /* Logitech MX5000 HID++ / bluetooth receiver mouse intf. */ 1910 + { /* Logitech MX5000 HID++ / bluetooth receiver mouse intf. (0xc70a) */ 1983 1911 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1984 - 0xc70a), 1912 + USB_DEVICE_ID_MX5000_RECEIVER_MOUSE_DEV), 1985 1913 .driver_data = recvr_type_bluetooth}, 1986 - { /* Logitech MX5500 HID++ / bluetooth receiver keyboard intf. */ 1914 + { /* Logitech MX5500 HID++ / bluetooth receiver keyboard intf. (0xc71b) */ 1987 1915 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1988 - 0xc71b), 1916 + USB_DEVICE_ID_MX5500_RECEIVER_KBD_DEV), 1989 1917 .driver_data = recvr_type_bluetooth}, 1990 - { /* Logitech MX5500 HID++ / bluetooth receiver mouse intf. */ 1918 + { /* Logitech MX5500 HID++ / bluetooth receiver mouse intf. (0xc71c) */ 1991 1919 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1992 - 0xc71c), 1920 + USB_DEVICE_ID_MX5500_RECEIVER_MOUSE_DEV), 1993 1921 .driver_data = recvr_type_bluetooth}, 1922 + 1923 + { /* Logitech Dinovo Edge HID++ / bluetooth receiver keyboard intf. (0xc713) */ 1924 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1925 + USB_DEVICE_ID_DINOVO_EDGE_RECEIVER_KBD_DEV), 1926 + .driver_data = recvr_type_dinovo}, 1927 + { /* Logitech Dinovo Edge HID++ / bluetooth receiver mouse intf. (0xc714) */ 1928 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1929 + USB_DEVICE_ID_DINOVO_EDGE_RECEIVER_MOUSE_DEV), 1930 + .driver_data = recvr_type_dinovo}, 1931 + { /* Logitech DiNovo Mini HID++ / bluetooth receiver mouse intf. (0xc71e) */ 1932 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1933 + USB_DEVICE_ID_DINOVO_MINI_RECEIVER_KBD_DEV), 1934 + .driver_data = recvr_type_dinovo}, 1935 + { /* Logitech DiNovo Mini HID++ / bluetooth receiver keyboard intf. (0xc71f) */ 1936 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1937 + USB_DEVICE_ID_DINOVO_MINI_RECEIVER_MOUSE_DEV), 1938 + .driver_data = recvr_type_dinovo}, 1994 1939 {} 1995 1940 }; 1996 1941
+4 -3
drivers/hid/hid-logitech-hidpp.c
··· 261 261 return ret == fields_count ? 0 : -1; 262 262 } 263 263 264 - /** 264 + /* 265 265 * hidpp_send_message_sync() returns 0 in case of success, and something else 266 266 * in case of a failure. 267 267 * - If ' something else' is positive, that means that an error has been raised ··· 423 423 (report->rap.sub_id == 0x41)); 424 424 } 425 425 426 - /** 426 + /* 427 427 * hidpp_prefix_name() prefixes the current given name with "Logitech ". 428 428 */ 429 429 static void hidpp_prefix_name(char **name, int name_length) ··· 454 454 * hidpp_scroll_counter_handle_scroll() - Send high- and low-resolution scroll 455 455 * events given a high-resolution wheel 456 456 * movement. 457 + * @input_dev: Pointer to the input device 457 458 * @counter: a hid_scroll_counter struct describing the wheel. 458 459 * @hi_res_value: the movement of the wheel, in the mouse's high-resolution 459 460 * units. ··· 1885 1884 uint8_t persistent; 1886 1885 }; 1887 1886 1888 - /** 1887 + /* 1889 1888 * send a set state command to the device by reading the current items->state 1890 1889 * field. items is then filled with the current state. 1891 1890 */
+128 -34
drivers/hid/hid-magicmouse.c
··· 16 16 #include <linux/input/mt.h> 17 17 #include <linux/module.h> 18 18 #include <linux/slab.h> 19 + #include <linux/workqueue.h> 19 20 20 21 #include "hid-ids.h" 21 22 ··· 55 54 #define TRACKPAD2_USB_REPORT_ID 0x02 56 55 #define TRACKPAD2_BT_REPORT_ID 0x31 57 56 #define MOUSE_REPORT_ID 0x29 57 + #define MOUSE2_REPORT_ID 0x12 58 58 #define DOUBLE_REPORT_ID 0xf7 59 59 /* These definitions are not precise, but they're close enough. (Bits 60 60 * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem ··· 129 127 u8 size; 130 128 } touches[16]; 131 129 int tracking_ids[16]; 130 + 131 + struct hid_device *hdev; 132 + struct delayed_work work; 132 133 }; 133 134 134 135 static int magicmouse_firm_touch(struct magicmouse_sc *msc) ··· 200 195 int id, x, y, size, orientation, touch_major, touch_minor, state, down; 201 196 int pressure = 0; 202 197 203 - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { 198 + if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE || 199 + input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) { 204 200 id = (tdata[6] << 2 | tdata[5] >> 6) & 0xf; 205 201 x = (tdata[1] << 28 | tdata[0] << 20) >> 20; 206 202 y = -((tdata[2] << 24 | tdata[1] << 16) >> 20); ··· 302 296 input_report_abs(input, ABS_MT_PRESSURE, pressure); 303 297 304 298 if (report_undeciphered) { 305 - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) 299 + if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE || 300 + input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) 306 301 input_event(input, EV_MSC, MSC_RAW, tdata[7]); 307 302 else if (input->id.product != 308 303 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) ··· 387 380 * ts = data[3] >> 6 | data[4] << 2 | data[5] << 10; 388 381 */ 389 382 break; 383 + case MOUSE2_REPORT_ID: 384 + /* Size is either 8 or (14 + 8 * N) */ 385 + if (size != 8 && (size < 14 || (size - 14) % 8 != 0)) 386 + return 0; 387 + npoints = (size - 14) / 8; 388 + if (npoints > 15) { 389 + hid_warn(hdev, "invalid size value (%d) for MOUSE2_REPORT_ID\n", 390 + size); 391 + return 0; 392 + } 393 + msc->ntouches = 0; 394 + for (ii = 0; ii < npoints; ii++) 395 + magicmouse_emit_touch(msc, ii, data + ii * 8 + 14); 396 + 397 + /* When emulating three-button mode, it is important 398 + * to have the current touch information before 399 + * generating a click event. 400 + */ 401 + x = (int)((data[3] << 24) | (data[2] << 16)) >> 16; 402 + y = (int)((data[5] << 24) | (data[4] << 16)) >> 16; 403 + clicks = data[1]; 404 + 405 + /* The following bits provide a device specific timestamp. They 406 + * are unused here. 407 + * 408 + * ts = data[11] >> 6 | data[12] << 2 | data[13] << 10; 409 + */ 410 + break; 390 411 case DOUBLE_REPORT_ID: 391 412 /* Sometimes the trackpad sends two touch reports in one 392 413 * packet. ··· 427 392 return 0; 428 393 } 429 394 430 - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { 395 + if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE || 396 + input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) { 431 397 magicmouse_emit_buttons(msc, clicks & 3); 432 398 input_report_rel(input, REL_X, x); 433 399 input_report_rel(input, REL_Y, y); ··· 444 408 return 1; 445 409 } 446 410 411 + static int magicmouse_event(struct hid_device *hdev, struct hid_field *field, 412 + struct hid_usage *usage, __s32 value) 413 + { 414 + struct magicmouse_sc *msc = hid_get_drvdata(hdev); 415 + if (msc->input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 && 416 + field->report->id == MOUSE2_REPORT_ID) { 417 + /* 418 + * magic_mouse_raw_event has done all the work. Skip hidinput. 419 + * 420 + * Specifically, hidinput may modify BTN_LEFT and BTN_RIGHT, 421 + * breaking emulate_3button. 422 + */ 423 + return 1; 424 + } 425 + return 0; 426 + } 427 + 447 428 static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) 448 429 { 449 430 int error; ··· 468 415 469 416 __set_bit(EV_KEY, input->evbit); 470 417 471 - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { 418 + if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE || 419 + input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) { 472 420 __set_bit(BTN_LEFT, input->keybit); 473 421 __set_bit(BTN_RIGHT, input->keybit); 474 422 if (emulate_3button) ··· 534 480 * the origin at the same position, and just uses the additive 535 481 * inverse of the reported Y. 536 482 */ 537 - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { 483 + if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE || 484 + input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) { 538 485 input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0); 539 486 input_set_abs_params(input, ABS_MT_POSITION_X, 540 487 MOUSE_MIN_X, MOUSE_MAX_X, 4, 0); ··· 635 580 return 0; 636 581 } 637 582 583 + static int magicmouse_enable_multitouch(struct hid_device *hdev) 584 + { 585 + const u8 *feature; 586 + const u8 feature_mt[] = { 0xD7, 0x01 }; 587 + const u8 feature_mt_mouse2[] = { 0xF1, 0x02, 0x01 }; 588 + const u8 feature_mt_trackpad2_usb[] = { 0x02, 0x01 }; 589 + const u8 feature_mt_trackpad2_bt[] = { 0xF1, 0x02, 0x01 }; 590 + u8 *buf; 591 + int ret; 592 + int feature_size; 593 + 594 + if (hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) { 595 + if (hdev->vendor == BT_VENDOR_ID_APPLE) { 596 + feature_size = sizeof(feature_mt_trackpad2_bt); 597 + feature = feature_mt_trackpad2_bt; 598 + } else { /* USB_VENDOR_ID_APPLE */ 599 + feature_size = sizeof(feature_mt_trackpad2_usb); 600 + feature = feature_mt_trackpad2_usb; 601 + } 602 + } else if (hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) { 603 + feature_size = sizeof(feature_mt_mouse2); 604 + feature = feature_mt_mouse2; 605 + } else { 606 + feature_size = sizeof(feature_mt); 607 + feature = feature_mt; 608 + } 609 + 610 + buf = kmemdup(feature, feature_size, GFP_KERNEL); 611 + if (!buf) 612 + return -ENOMEM; 613 + 614 + ret = hid_hw_raw_request(hdev, buf[0], buf, feature_size, 615 + HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 616 + kfree(buf); 617 + return ret; 618 + } 619 + 620 + static void magicmouse_enable_mt_work(struct work_struct *work) 621 + { 622 + struct magicmouse_sc *msc = 623 + container_of(work, struct magicmouse_sc, work.work); 624 + int ret; 625 + 626 + ret = magicmouse_enable_multitouch(msc->hdev); 627 + if (ret < 0) 628 + hid_err(msc->hdev, "unable to request touch data (%d)\n", ret); 629 + } 638 630 639 631 static int magicmouse_probe(struct hid_device *hdev, 640 632 const struct hid_device_id *id) 641 633 { 642 - const u8 *feature; 643 - const u8 feature_mt[] = { 0xD7, 0x01 }; 644 - const u8 feature_mt_trackpad2_usb[] = { 0x02, 0x01 }; 645 - const u8 feature_mt_trackpad2_bt[] = { 0xF1, 0x02, 0x01 }; 646 - u8 *buf; 647 634 struct magicmouse_sc *msc; 648 635 struct hid_report *report; 649 636 int ret; 650 - int feature_size; 651 637 652 638 if (id->vendor == USB_VENDOR_ID_APPLE && 653 639 id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && ··· 702 606 } 703 607 704 608 msc->scroll_accel = SCROLL_ACCEL_DEFAULT; 609 + msc->hdev = hdev; 610 + INIT_DEFERRABLE_WORK(&msc->work, magicmouse_enable_mt_work); 705 611 706 612 msc->quirks = id->driver_data; 707 613 hid_set_drvdata(hdev, msc); ··· 729 631 if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) 730 632 report = hid_register_report(hdev, HID_INPUT_REPORT, 731 633 MOUSE_REPORT_ID, 0); 634 + else if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) 635 + report = hid_register_report(hdev, HID_INPUT_REPORT, 636 + MOUSE2_REPORT_ID, 0); 732 637 else if (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) { 733 638 if (id->vendor == BT_VENDOR_ID_APPLE) 734 639 report = hid_register_report(hdev, HID_INPUT_REPORT, ··· 753 652 } 754 653 report->size = 6; 755 654 756 - if (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) { 757 - if (id->vendor == BT_VENDOR_ID_APPLE) { 758 - feature_size = sizeof(feature_mt_trackpad2_bt); 759 - feature = feature_mt_trackpad2_bt; 760 - } else { /* USB_VENDOR_ID_APPLE */ 761 - feature_size = sizeof(feature_mt_trackpad2_usb); 762 - feature = feature_mt_trackpad2_usb; 763 - } 764 - } else { 765 - feature_size = sizeof(feature_mt); 766 - feature = feature_mt; 767 - } 768 - 769 - buf = kmemdup(feature, feature_size, GFP_KERNEL); 770 - if (!buf) { 771 - ret = -ENOMEM; 772 - goto err_stop_hw; 773 - } 774 - 775 655 /* 776 656 * Some devices repond with 'invalid report id' when feature 777 657 * report switching it into multitouch mode is sent to it. ··· 761 679 * but there seems to be no other way of switching the mode. 762 680 * Thus the super-ugly hacky success check below. 763 681 */ 764 - ret = hid_hw_raw_request(hdev, buf[0], buf, feature_size, 765 - HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 766 - kfree(buf); 767 - if (ret != -EIO && ret != feature_size) { 682 + ret = magicmouse_enable_multitouch(hdev); 683 + if (ret != -EIO && ret < 0) { 768 684 hid_err(hdev, "unable to request touch data (%d)\n", ret); 769 685 goto err_stop_hw; 686 + } 687 + if (ret == -EIO && id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) { 688 + schedule_delayed_work(&msc->work, msecs_to_jiffies(500)); 770 689 } 771 690 772 691 return 0; ··· 776 693 return ret; 777 694 } 778 695 696 + static void magicmouse_remove(struct hid_device *hdev) 697 + { 698 + struct magicmouse_sc *msc = hid_get_drvdata(hdev); 699 + cancel_delayed_work_sync(&msc->work); 700 + hid_hw_stop(hdev); 701 + } 702 + 779 703 static const struct hid_device_id magic_mice[] = { 780 704 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 781 705 USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 }, 706 + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, 707 + USB_DEVICE_ID_APPLE_MAGICMOUSE2), .driver_data = 0 }, 782 708 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 783 709 USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 }, 784 710 { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, ··· 802 710 .name = "magicmouse", 803 711 .id_table = magic_mice, 804 712 .probe = magicmouse_probe, 713 + .remove = magicmouse_remove, 805 714 .raw_event = magicmouse_raw_event, 715 + .event = magicmouse_event, 806 716 .input_mapping = magicmouse_input_mapping, 807 717 .input_configured = magicmouse_input_configured, 808 718 };
+2 -3
drivers/hid/hid-picolcd_core.c
··· 329 329 { 330 330 struct picolcd_data *data = hid_get_drvdata(hdev); 331 331 unsigned long flags; 332 - int ret = 0; 333 332 334 333 if (!data) 335 334 return 1; ··· 341 342 342 343 if (report->id == REPORT_KEY_STATE) { 343 344 if (data->input_keys) 344 - ret = picolcd_raw_keypad(data, report, raw_data+1, size-1); 345 + picolcd_raw_keypad(data, report, raw_data+1, size-1); 345 346 } else if (report->id == REPORT_IR_DATA) { 346 - ret = picolcd_raw_cir(data, report, raw_data+1, size-1); 347 + picolcd_raw_cir(data, report, raw_data+1, size-1); 347 348 } else { 348 349 spin_lock_irqsave(&data->lock, flags); 349 350 /*
+58 -2
drivers/hid/hid-plantronics.c
··· 13 13 14 14 #include <linux/hid.h> 15 15 #include <linux/module.h> 16 + #include <linux/jiffies.h> 16 17 17 18 #define PLT_HID_1_0_PAGE 0xffa00000 18 19 #define PLT_HID_2_0_PAGE 0xffa20000 ··· 37 36 #define PLT_ALLOW_CONSUMER (field->application == HID_CP_CONSUMERCONTROL && \ 38 37 (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) 39 38 39 + #define PLT_QUIRK_DOUBLE_VOLUME_KEYS BIT(0) 40 + 41 + #define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */ 42 + 43 + struct plt_drv_data { 44 + unsigned long device_type; 45 + unsigned long last_volume_key_ts; 46 + u32 quirks; 47 + }; 48 + 40 49 static int plantronics_input_mapping(struct hid_device *hdev, 41 50 struct hid_input *hi, 42 51 struct hid_field *field, ··· 54 43 unsigned long **bit, int *max) 55 44 { 56 45 unsigned short mapped_key; 57 - unsigned long plt_type = (unsigned long)hid_get_drvdata(hdev); 46 + struct plt_drv_data *drv_data = hid_get_drvdata(hdev); 47 + unsigned long plt_type = drv_data->device_type; 58 48 59 49 /* special case for PTT products */ 60 50 if (field->application == HID_GD_JOYSTICK) ··· 117 105 return 1; 118 106 } 119 107 108 + static int plantronics_event(struct hid_device *hdev, struct hid_field *field, 109 + struct hid_usage *usage, __s32 value) 110 + { 111 + struct plt_drv_data *drv_data = hid_get_drvdata(hdev); 112 + 113 + if (drv_data->quirks & PLT_QUIRK_DOUBLE_VOLUME_KEYS) { 114 + unsigned long prev_ts, cur_ts; 115 + 116 + /* Usages are filtered in plantronics_usages. */ 117 + 118 + if (!value) /* Handle key presses only. */ 119 + return 0; 120 + 121 + prev_ts = drv_data->last_volume_key_ts; 122 + cur_ts = jiffies; 123 + if (jiffies_to_msecs(cur_ts - prev_ts) <= PLT_DOUBLE_KEY_TIMEOUT) 124 + return 1; /* Ignore the repeated key. */ 125 + 126 + drv_data->last_volume_key_ts = cur_ts; 127 + } 128 + 129 + return 0; 130 + } 131 + 120 132 static unsigned long plantronics_device_type(struct hid_device *hdev) 121 133 { 122 134 unsigned i, col_page; ··· 169 133 static int plantronics_probe(struct hid_device *hdev, 170 134 const struct hid_device_id *id) 171 135 { 136 + struct plt_drv_data *drv_data; 172 137 int ret; 138 + 139 + drv_data = devm_kzalloc(&hdev->dev, sizeof(*drv_data), GFP_KERNEL); 140 + if (!drv_data) 141 + return -ENOMEM; 173 142 174 143 ret = hid_parse(hdev); 175 144 if (ret) { ··· 182 141 goto err; 183 142 } 184 143 185 - hid_set_drvdata(hdev, (void *)plantronics_device_type(hdev)); 144 + drv_data->device_type = plantronics_device_type(hdev); 145 + drv_data->quirks = id->driver_data; 146 + drv_data->last_volume_key_ts = jiffies - msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT); 147 + 148 + hid_set_drvdata(hdev, drv_data); 186 149 187 150 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | 188 151 HID_CONNECT_HIDINPUT_FORCE | HID_CONNECT_HIDDEV_FORCE); ··· 198 153 } 199 154 200 155 static const struct hid_device_id plantronics_devices[] = { 156 + { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, 157 + USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES), 158 + .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, 201 159 { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, 202 160 { } 203 161 }; 204 162 MODULE_DEVICE_TABLE(hid, plantronics_devices); 205 163 164 + static const struct hid_usage_id plantronics_usages[] = { 165 + { HID_CP_VOLUMEUP, EV_KEY, HID_ANY_ID }, 166 + { HID_CP_VOLUMEDOWN, EV_KEY, HID_ANY_ID }, 167 + { HID_TERMINATOR, HID_TERMINATOR, HID_TERMINATOR } 168 + }; 169 + 206 170 static struct hid_driver plantronics_driver = { 207 171 .name = "plantronics", 208 172 .id_table = plantronics_devices, 173 + .usage_table = plantronics_usages, 209 174 .input_mapping = plantronics_input_mapping, 175 + .event = plantronics_event, 210 176 .probe = plantronics_probe, 211 177 }; 212 178 module_hid_driver(plantronics_driver);
+3 -2
drivers/hid/hid-quirks.c
··· 445 445 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, 446 446 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, 447 447 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, 448 - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, 449 - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, 450 448 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, 451 449 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, 452 450 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, ··· 658 660 { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) }, 659 661 { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, 660 662 { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) }, 663 + #endif 664 + #if IS_ENABLED(CONFIG_HID_TMINIT) 665 + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65d) }, 661 666 #endif 662 667 #if IS_ENABLED(CONFIG_HID_TIVO) 663 668 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
+2 -3
drivers/hid/hid-sensor-custom.c
··· 397 397 398 398 if (!strncmp(name, "value", strlen("value"))) { 399 399 u32 report_id; 400 - int ret; 401 400 402 401 if (kstrtoint(buf, 0, &value) != 0) 403 402 return -EINVAL; 404 403 405 404 report_id = sensor_inst->fields[field_index].attribute. 406 405 report_id; 407 - ret = sensor_hub_set_feature(sensor_inst->hsdev, report_id, 408 - index, sizeof(value), &value); 406 + sensor_hub_set_feature(sensor_inst->hsdev, report_id, 407 + index, sizeof(value), &value); 409 408 } else 410 409 return -EINVAL; 411 410
+1 -3
drivers/hid/hid-sensor-hub.c
··· 18 18 19 19 /** 20 20 * struct sensor_hub_data - Hold a instance data for a HID hub device 21 - * @hsdev: Stored hid instance for current hub device. 22 21 * @mutex: Mutex to serialize synchronous request. 23 22 * @lock: Spin lock to protect pending request structure. 24 23 * @dyn_callback_list: Holds callback function ··· 33 34 spinlock_t dyn_callback_lock; 34 35 struct mfd_cell *hid_sensor_hub_client_devs; 35 36 int hid_sensor_client_cnt; 36 - unsigned long quirks; 37 37 int ref_cnt; 38 38 }; 39 39 ··· 40 42 * struct hid_sensor_hub_callbacks_list - Stores callback list 41 43 * @list: list head. 42 44 * @usage_id: usage id for a physical device. 45 + * @hsdev: Stored hid instance for current hub device. 43 46 * @usage_callback: Stores registered callback functions. 44 47 * @priv: Private data for a physical device. 45 48 */ ··· 614 615 } 615 616 616 617 hid_set_drvdata(hdev, sd); 617 - sd->quirks = id->driver_data; 618 618 619 619 spin_lock_init(&sd->lock); 620 620 spin_lock_init(&sd->dyn_callback_lock);
+371
drivers/hid/hid-thrustmaster.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * When connected to the machine, the Thrustmaster wheels appear as 4 + * a «generic» hid gamepad called "Thrustmaster FFB Wheel". 5 + * 6 + * When in this mode not every functionality of the wheel, like the force feedback, 7 + * are available. To enable all functionalities of a Thrustmaster wheel we have to send 8 + * to it a specific USB CONTROL request with a code different for each wheel. 9 + * 10 + * This driver tries to understand which model of Thrustmaster wheel the generic 11 + * "Thrustmaster FFB Wheel" really is and then sends the appropriate control code. 12 + * 13 + * Copyright (c) 2020-2021 Dario Pagani <dario.pagani.146+linuxk@gmail.com> 14 + * Copyright (c) 2020-2021 Kim Kuparinen <kimi.h.kuparinen@gmail.com> 15 + */ 16 + #include <linux/hid.h> 17 + #include <linux/usb.h> 18 + #include <linux/input.h> 19 + #include <linux/slab.h> 20 + #include <linux/module.h> 21 + 22 + /* 23 + * These interrupts are used to prevent a nasty crash when initializing the 24 + * T300RS. Used in thrustmaster_interrupts(). 25 + */ 26 + static const u8 setup_0[] = { 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 27 + static const u8 setup_1[] = { 0x0a, 0x04, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00 }; 28 + static const u8 setup_2[] = { 0x0a, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00 }; 29 + static const u8 setup_3[] = { 0x0a, 0x04, 0x12, 0x10, 0x00, 0x00, 0x00, 0x00 }; 30 + static const u8 setup_4[] = { 0x0a, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 }; 31 + static const u8 *const setup_arr[] = { setup_0, setup_1, setup_2, setup_3, setup_4 }; 32 + static const unsigned int setup_arr_sizes[] = { 33 + ARRAY_SIZE(setup_0), 34 + ARRAY_SIZE(setup_1), 35 + ARRAY_SIZE(setup_2), 36 + ARRAY_SIZE(setup_3), 37 + ARRAY_SIZE(setup_4) 38 + }; 39 + /* 40 + * This struct contains for each type of 41 + * Thrustmaster wheel 42 + * 43 + * Note: The values are stored in the CPU 44 + * endianness, the USB protocols always use 45 + * little endian; the macro cpu_to_le[BIT]() 46 + * must be used when preparing USB packets 47 + * and vice-versa 48 + */ 49 + struct tm_wheel_info { 50 + uint16_t wheel_type; 51 + 52 + /* 53 + * See when the USB control out packet is prepared... 54 + * @TODO The TMX seems to require multiple control codes to switch. 55 + */ 56 + uint16_t switch_value; 57 + 58 + char const *const wheel_name; 59 + }; 60 + 61 + /* 62 + * Known wheels. 63 + * Note: TMX does not work as it requires 2 control packets 64 + */ 65 + static const struct tm_wheel_info tm_wheels_infos[] = { 66 + {0x0306, 0x0006, "Thrustmaster T150RS"}, 67 + {0x0206, 0x0005, "Thrustmaster T300RS"}, 68 + {0x0204, 0x0005, "Thrustmaster T300 Ferrari Alcantara Edition"}, 69 + {0x0002, 0x0002, "Thrustmaster T500RS"} 70 + //{0x0407, 0x0001, "Thrustmaster TMX"} 71 + }; 72 + 73 + static const uint8_t tm_wheels_infos_length = 4; 74 + 75 + /* 76 + * This structs contains (in little endian) the response data 77 + * of the wheel to the request 73 78 + * 79 + * A sufficient research to understand what each field does is not 80 + * beign conducted yet. The position and meaning of fields are a 81 + * just a very optimistic guess based on instinct.... 82 + */ 83 + struct __packed tm_wheel_response 84 + { 85 + /* 86 + * Seems to be the type of packet 87 + * - 0x0049 if is data.a (15 bytes) 88 + * - 0x0047 if is data.b (7 bytes) 89 + */ 90 + uint16_t type; 91 + 92 + union { 93 + struct __packed { 94 + uint16_t field0; 95 + uint16_t field1; 96 + /* 97 + * Seems to be the model code of the wheel 98 + * Read table thrustmaster_wheels to values 99 + */ 100 + uint16_t model; 101 + 102 + uint16_t field2; 103 + uint16_t field3; 104 + uint16_t field4; 105 + uint16_t field5; 106 + } a; 107 + struct __packed { 108 + uint16_t field0; 109 + uint16_t field1; 110 + uint16_t model; 111 + } b; 112 + } data; 113 + }; 114 + 115 + struct tm_wheel { 116 + struct usb_device *usb_dev; 117 + struct urb *urb; 118 + 119 + struct usb_ctrlrequest *model_request; 120 + struct tm_wheel_response *response; 121 + 122 + struct usb_ctrlrequest *change_request; 123 + }; 124 + 125 + /* The control packet to send to wheel */ 126 + static const struct usb_ctrlrequest model_request = { 127 + .bRequestType = 0xc1, 128 + .bRequest = 73, 129 + .wValue = 0, 130 + .wIndex = 0, 131 + .wLength = cpu_to_le16(0x0010) 132 + }; 133 + 134 + static const struct usb_ctrlrequest change_request = { 135 + .bRequestType = 0x41, 136 + .bRequest = 83, 137 + .wValue = 0, // Will be filled by the driver 138 + .wIndex = 0, 139 + .wLength = 0 140 + }; 141 + 142 + /* 143 + * On some setups initializing the T300RS crashes the kernel, 144 + * these interrupts fix that particular issue. So far they haven't caused any 145 + * adverse effects in other wheels. 146 + */ 147 + static void thrustmaster_interrupts(struct hid_device *hdev) 148 + { 149 + int ret, trans, i, b_ep; 150 + u8 *send_buf = kmalloc(256, GFP_KERNEL); 151 + struct usb_host_endpoint *ep; 152 + struct device *dev = &hdev->dev; 153 + struct usb_interface *usbif = to_usb_interface(dev->parent); 154 + struct usb_device *usbdev = interface_to_usbdev(usbif); 155 + 156 + if (!send_buf) { 157 + hid_err(hdev, "failed allocating send buffer\n"); 158 + return; 159 + } 160 + 161 + ep = &usbif->cur_altsetting->endpoint[1]; 162 + b_ep = ep->desc.bEndpointAddress; 163 + 164 + for (i = 0; i < ARRAY_SIZE(setup_arr); ++i) { 165 + memcpy(send_buf, setup_arr[i], setup_arr_sizes[i]); 166 + 167 + ret = usb_interrupt_msg(usbdev, 168 + usb_sndintpipe(usbdev, b_ep), 169 + send_buf, 170 + setup_arr_sizes[i], 171 + &trans, 172 + USB_CTRL_SET_TIMEOUT); 173 + 174 + if (ret) { 175 + hid_err(hdev, "setup data couldn't be sent\n"); 176 + return; 177 + } 178 + } 179 + 180 + kfree(send_buf); 181 + } 182 + 183 + static void thrustmaster_change_handler(struct urb *urb) 184 + { 185 + struct hid_device *hdev = urb->context; 186 + 187 + // The wheel seems to kill himself before answering the host and therefore is violating the USB protocol... 188 + if (urb->status == 0 || urb->status == -EPROTO || urb->status == -EPIPE) 189 + hid_info(hdev, "Success?! The wheel should have been initialized!\n"); 190 + else 191 + hid_warn(hdev, "URB to change wheel mode seems to have failed with error %d\n", urb->status); 192 + } 193 + 194 + /* 195 + * Called by the USB subsystem when the wheel responses to our request 196 + * to get [what it seems to be] the wheel's model. 197 + * 198 + * If the model id is recognized then we send an opportune USB CONTROL REQUEST 199 + * to switch the wheel to its full capabilities 200 + */ 201 + static void thrustmaster_model_handler(struct urb *urb) 202 + { 203 + struct hid_device *hdev = urb->context; 204 + struct tm_wheel *tm_wheel = hid_get_drvdata(hdev); 205 + uint16_t model = 0; 206 + int i, ret; 207 + const struct tm_wheel_info *twi = 0; 208 + 209 + if (urb->status) { 210 + hid_err(hdev, "URB to get model id failed with error %d\n", urb->status); 211 + return; 212 + } 213 + 214 + if (tm_wheel->response->type == cpu_to_le16(0x49)) 215 + model = le16_to_cpu(tm_wheel->response->data.a.model); 216 + else if (tm_wheel->response->type == cpu_to_le16(0x47)) 217 + model = le16_to_cpu(tm_wheel->response->data.b.model); 218 + else { 219 + hid_err(hdev, "Unknown packet type 0x%x, unable to proceed further with wheel init\n", tm_wheel->response->type); 220 + return; 221 + } 222 + 223 + for (i = 0; i < tm_wheels_infos_length && !twi; i++) 224 + if (tm_wheels_infos[i].wheel_type == model) 225 + twi = tm_wheels_infos + i; 226 + 227 + if (twi) 228 + hid_info(hdev, "Wheel with model id 0x%x is a %s\n", model, twi->wheel_name); 229 + else { 230 + hid_err(hdev, "Unknown wheel's model id 0x%x, unable to proceed further with wheel init\n", model); 231 + return; 232 + } 233 + 234 + tm_wheel->change_request->wValue = cpu_to_le16(twi->switch_value); 235 + usb_fill_control_urb( 236 + tm_wheel->urb, 237 + tm_wheel->usb_dev, 238 + usb_sndctrlpipe(tm_wheel->usb_dev, 0), 239 + (char *)tm_wheel->change_request, 240 + 0, 0, // We do not expect any response from the wheel 241 + thrustmaster_change_handler, 242 + hdev 243 + ); 244 + 245 + ret = usb_submit_urb(tm_wheel->urb, GFP_ATOMIC); 246 + if (ret) 247 + hid_err(hdev, "Error %d while submitting the change URB. I am unable to initialize this wheel...\n", ret); 248 + } 249 + 250 + static void thrustmaster_remove(struct hid_device *hdev) 251 + { 252 + struct tm_wheel *tm_wheel = hid_get_drvdata(hdev); 253 + 254 + usb_kill_urb(tm_wheel->urb); 255 + 256 + kfree(tm_wheel->response); 257 + kfree(tm_wheel->model_request); 258 + usb_free_urb(tm_wheel->urb); 259 + kfree(tm_wheel); 260 + 261 + hid_hw_stop(hdev); 262 + } 263 + 264 + /* 265 + * Function called by HID when a hid Thrustmaster FFB wheel is connected to the host. 266 + * This function starts the hid dev, tries to allocate the tm_wheel data structure and 267 + * finally send an USB CONTROL REQUEST to the wheel to get [what it seems to be] its 268 + * model type. 269 + */ 270 + static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_id *id) 271 + { 272 + int ret = 0; 273 + struct tm_wheel *tm_wheel = 0; 274 + 275 + ret = hid_parse(hdev); 276 + if (ret) { 277 + hid_err(hdev, "parse failed with error %d\n", ret); 278 + goto error0; 279 + } 280 + 281 + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); 282 + if (ret) { 283 + hid_err(hdev, "hw start failed with error %d\n", ret); 284 + goto error0; 285 + } 286 + 287 + // Now we allocate the tm_wheel 288 + tm_wheel = kzalloc(sizeof(struct tm_wheel), GFP_KERNEL); 289 + if (!tm_wheel) { 290 + ret = -ENOMEM; 291 + goto error1; 292 + } 293 + 294 + tm_wheel->urb = usb_alloc_urb(0, GFP_ATOMIC); 295 + if (!tm_wheel->urb) { 296 + ret = -ENOMEM; 297 + goto error2; 298 + } 299 + 300 + tm_wheel->model_request = kmemdup(&model_request, 301 + sizeof(struct usb_ctrlrequest), 302 + GFP_KERNEL); 303 + if (!tm_wheel->model_request) { 304 + ret = -ENOMEM; 305 + goto error3; 306 + } 307 + 308 + tm_wheel->response = kzalloc(sizeof(struct tm_wheel_response), GFP_KERNEL); 309 + if (!tm_wheel->response) { 310 + ret = -ENOMEM; 311 + goto error4; 312 + } 313 + 314 + tm_wheel->change_request = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); 315 + if (!tm_wheel->model_request) { 316 + ret = -ENOMEM; 317 + goto error5; 318 + } 319 + memcpy(tm_wheel->change_request, &change_request, sizeof(struct usb_ctrlrequest)); 320 + 321 + tm_wheel->usb_dev = interface_to_usbdev(to_usb_interface(hdev->dev.parent)); 322 + hid_set_drvdata(hdev, tm_wheel); 323 + 324 + thrustmaster_interrupts(hdev); 325 + 326 + usb_fill_control_urb( 327 + tm_wheel->urb, 328 + tm_wheel->usb_dev, 329 + usb_rcvctrlpipe(tm_wheel->usb_dev, 0), 330 + (char *)tm_wheel->model_request, 331 + tm_wheel->response, 332 + sizeof(struct tm_wheel_response), 333 + thrustmaster_model_handler, 334 + hdev 335 + ); 336 + 337 + ret = usb_submit_urb(tm_wheel->urb, GFP_ATOMIC); 338 + if (ret) 339 + hid_err(hdev, "Error %d while submitting the URB. I am unable to initialize this wheel...\n", ret); 340 + 341 + return ret; 342 + 343 + error5: kfree(tm_wheel->response); 344 + error4: kfree(tm_wheel->model_request); 345 + error3: usb_free_urb(tm_wheel->urb); 346 + error2: kfree(tm_wheel); 347 + error1: hid_hw_stop(hdev); 348 + error0: 349 + return ret; 350 + } 351 + 352 + static const struct hid_device_id thrustmaster_devices[] = { 353 + { HID_USB_DEVICE(0x044f, 0xb65d)}, 354 + {} 355 + }; 356 + 357 + MODULE_DEVICE_TABLE(hid, thrustmaster_devices); 358 + 359 + static struct hid_driver thrustmaster_driver = { 360 + .name = "hid-thrustmaster", 361 + .id_table = thrustmaster_devices, 362 + .probe = thrustmaster_probe, 363 + .remove = thrustmaster_remove, 364 + }; 365 + 366 + module_hid_driver(thrustmaster_driver); 367 + 368 + MODULE_AUTHOR("Dario Pagani <dario.pagani.146+linuxk@gmail.com>"); 369 + MODULE_LICENSE("GPL"); 370 + MODULE_DESCRIPTION("Driver to initialize some steering wheel joysticks from Thrustmaster"); 371 +
+5 -3
drivers/hid/hid-uclogic-params.c
··· 21 21 #include <asm/unaligned.h> 22 22 23 23 /** 24 - * Convert a pen in-range reporting type to a string. 24 + * uclogic_params_pen_inrange_to_str() - Convert a pen in-range reporting type 25 + * to a string. 25 26 * 26 27 * @inrange: The in-range reporting type to convert. 27 28 * ··· 517 516 } 518 517 519 518 /** 520 - * Get a replacement report descriptor for a tablet's interface. 519 + * uclogic_params_get_desc() - Get a replacement report descriptor for a 520 + * tablet's interface. 521 521 * 522 522 * @params: The parameters of a tablet interface to get report 523 523 * descriptor for. Cannot be NULL. ··· 691 689 } 692 690 693 691 /** 694 - * uclogic_params_init() - initialize a Huion tablet interface and discover 692 + * uclogic_params_huion_init() - initialize a Huion tablet interface and discover 695 693 * its parameters. 696 694 * 697 695 * @params: Parameters to fill in (to be cleaned with
+1 -1
drivers/hid/hid-uclogic-rdesc.c
··· 641 641 const size_t uclogic_rdesc_pen_v2_template_size = 642 642 sizeof(uclogic_rdesc_pen_v2_template_arr); 643 643 644 - /** 644 + /* 645 645 * Expand to the contents of a generic buttonpad report descriptor. 646 646 * 647 647 * @_padding: Padding from the end of button bits at bit 44, until
+27 -29
drivers/hid/i2c-hid/i2c-hid-acpi.c
··· 25 25 #include <linux/kernel.h> 26 26 #include <linux/module.h> 27 27 #include <linux/pm.h> 28 + #include <linux/uuid.h> 28 29 29 30 #include "i2c-hid.h" 30 31 31 32 struct i2c_hid_acpi { 32 33 struct i2chid_ops ops; 33 - struct i2c_client *client; 34 + struct acpi_device *adev; 34 35 }; 35 36 36 37 static const struct acpi_device_id i2c_hid_acpi_blacklist[] = { ··· 43 42 { }, 44 43 }; 45 44 46 - static int i2c_hid_acpi_get_descriptor(struct i2c_client *client) 47 - { 48 - static guid_t i2c_hid_guid = 49 - GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555, 50 - 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE); 51 - union acpi_object *obj; 52 - struct acpi_device *adev; 53 - acpi_handle handle; 54 - u16 hid_descriptor_address; 45 + /* HID I²C Device: 3cdff6f7-4267-4555-ad05-b30a3d8938de */ 46 + static guid_t i2c_hid_guid = 47 + GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555, 48 + 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE); 55 49 56 - handle = ACPI_HANDLE(&client->dev); 57 - if (!handle || acpi_bus_get_device(handle, &adev)) { 58 - dev_err(&client->dev, "Error could not get ACPI device\n"); 59 - return -ENODEV; 60 - } 50 + static int i2c_hid_acpi_get_descriptor(struct acpi_device *adev) 51 + { 52 + acpi_handle handle = acpi_device_handle(adev); 53 + union acpi_object *obj; 54 + u16 hid_descriptor_address; 61 55 62 56 if (acpi_match_device_ids(adev, i2c_hid_acpi_blacklist) == 0) 63 57 return -ENODEV; ··· 60 64 obj = acpi_evaluate_dsm_typed(handle, &i2c_hid_guid, 1, 1, NULL, 61 65 ACPI_TYPE_INTEGER); 62 66 if (!obj) { 63 - dev_err(&client->dev, "Error _DSM call to get HID descriptor address failed\n"); 67 + acpi_handle_err(handle, "Error _DSM call to get HID descriptor address failed\n"); 64 68 return -ENODEV; 65 69 } 66 70 ··· 72 76 73 77 static void i2c_hid_acpi_shutdown_tail(struct i2chid_ops *ops) 74 78 { 75 - struct i2c_hid_acpi *ihid_acpi = 76 - container_of(ops, struct i2c_hid_acpi, ops); 77 - struct device *dev = &ihid_acpi->client->dev; 78 - acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D3_COLD); 79 + struct i2c_hid_acpi *ihid_acpi = container_of(ops, struct i2c_hid_acpi, ops); 80 + 81 + acpi_device_set_power(ihid_acpi->adev, ACPI_STATE_D3_COLD); 79 82 } 80 83 81 - static int i2c_hid_acpi_probe(struct i2c_client *client, 82 - const struct i2c_device_id *dev_id) 84 + static int i2c_hid_acpi_probe(struct i2c_client *client) 83 85 { 84 86 struct device *dev = &client->dev; 85 87 struct i2c_hid_acpi *ihid_acpi; ··· 85 91 u16 hid_descriptor_address; 86 92 int ret; 87 93 94 + adev = ACPI_COMPANION(dev); 95 + if (!adev) { 96 + dev_err(&client->dev, "Error could not get ACPI device\n"); 97 + return -ENODEV; 98 + } 99 + 88 100 ihid_acpi = devm_kzalloc(&client->dev, sizeof(*ihid_acpi), GFP_KERNEL); 89 101 if (!ihid_acpi) 90 102 return -ENOMEM; 91 103 92 - ihid_acpi->client = client; 104 + ihid_acpi->adev = adev; 93 105 ihid_acpi->ops.shutdown_tail = i2c_hid_acpi_shutdown_tail; 94 106 95 - ret = i2c_hid_acpi_get_descriptor(client); 107 + ret = i2c_hid_acpi_get_descriptor(adev); 96 108 if (ret < 0) 97 109 return ret; 98 110 hid_descriptor_address = ret; 99 111 100 - adev = ACPI_COMPANION(dev); 101 - if (adev) 102 - acpi_device_fix_up_power(adev); 112 + acpi_device_fix_up_power(adev); 103 113 104 114 if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { 105 115 device_set_wakeup_capable(dev, true); ··· 126 128 .name = "i2c_hid_acpi", 127 129 .pm = &i2c_hid_core_pm, 128 130 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 129 - .acpi_match_table = ACPI_PTR(i2c_hid_acpi_match), 131 + .acpi_match_table = i2c_hid_acpi_match, 130 132 }, 131 133 132 - .probe = i2c_hid_acpi_probe, 134 + .probe_new = i2c_hid_acpi_probe, 133 135 .remove = i2c_hid_core_remove, 134 136 .shutdown = i2c_hid_core_shutdown, 135 137 };
+42
drivers/hid/surface-hid/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0+ 2 + menu "Surface System Aggregator Module HID support" 3 + depends on SURFACE_AGGREGATOR 4 + depends on INPUT 5 + 6 + config SURFACE_HID 7 + tristate "HID transport driver for Surface System Aggregator Module" 8 + depends on SURFACE_AGGREGATOR_REGISTRY 9 + select SURFACE_HID_CORE 10 + help 11 + Driver to support integrated HID devices on newer Microsoft Surface 12 + models. 13 + 14 + This driver provides support for the HID transport protocol provided 15 + by the Surface Aggregator Module (i.e. the embedded controller) on 16 + 7th-generation Microsoft Surface devices, i.e. Surface Book 3 and 17 + Surface Laptop 3. On those models, it is mainly used to connect the 18 + integrated touchpad and keyboard. 19 + 20 + Say M or Y here, if you want support for integrated HID devices, i.e. 21 + integrated touchpad and keyboard, on 7th generation Microsoft Surface 22 + models. 23 + 24 + config SURFACE_KBD 25 + tristate "HID keyboard transport driver for Surface System Aggregator Module" 26 + select SURFACE_HID_CORE 27 + help 28 + Driver to support HID keyboards on Surface Laptop 1 and 2 devices. 29 + 30 + This driver provides support for the HID transport protocol provided 31 + by the Surface Aggregator Module (i.e. the embedded controller) on 32 + Microsoft Surface Laptops 1 and 2. It is used to connect the 33 + integrated keyboard on those devices. 34 + 35 + Say M or Y here, if you want support for the integrated keyboard on 36 + Microsoft Surface Laptops 1 and 2. 37 + 38 + endmenu 39 + 40 + config SURFACE_HID_CORE 41 + tristate 42 + select HID
+7
drivers/hid/surface-hid/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0+ 2 + # 3 + # Makefile - Surface System Aggregator Module (SSAM) HID transport driver. 4 + # 5 + obj-$(CONFIG_SURFACE_HID_CORE) += surface_hid_core.o 6 + obj-$(CONFIG_SURFACE_HID) += surface_hid.o 7 + obj-$(CONFIG_SURFACE_KBD) += surface_kbd.o
+253
drivers/hid/surface-hid/surface_hid.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Surface System Aggregator Module (SSAM) HID transport driver for the 4 + * generic HID interface (HID/TC=0x15 subsystem). Provides support for 5 + * integrated HID devices on Surface Laptop 3, Book 3, and later. 6 + * 7 + * Copyright (C) 2019-2021 Blaž Hrastnik <blaz@mxxn.io>, 8 + * Maximilian Luz <luzmaximilian@gmail.com> 9 + */ 10 + 11 + #include <asm/unaligned.h> 12 + #include <linux/hid.h> 13 + #include <linux/kernel.h> 14 + #include <linux/module.h> 15 + #include <linux/types.h> 16 + 17 + #include <linux/surface_aggregator/controller.h> 18 + #include <linux/surface_aggregator/device.h> 19 + 20 + #include "surface_hid_core.h" 21 + 22 + 23 + /* -- SAM interface. -------------------------------------------------------- */ 24 + 25 + struct surface_hid_buffer_slice { 26 + __u8 entry; 27 + __le32 offset; 28 + __le32 length; 29 + __u8 end; 30 + __u8 data[]; 31 + } __packed; 32 + 33 + static_assert(sizeof(struct surface_hid_buffer_slice) == 10); 34 + 35 + enum surface_hid_cid { 36 + SURFACE_HID_CID_OUTPUT_REPORT = 0x01, 37 + SURFACE_HID_CID_GET_FEATURE_REPORT = 0x02, 38 + SURFACE_HID_CID_SET_FEATURE_REPORT = 0x03, 39 + SURFACE_HID_CID_GET_DESCRIPTOR = 0x04, 40 + }; 41 + 42 + static int ssam_hid_get_descriptor(struct surface_hid_device *shid, u8 entry, u8 *buf, size_t len) 43 + { 44 + u8 buffer[sizeof(struct surface_hid_buffer_slice) + 0x76]; 45 + struct surface_hid_buffer_slice *slice; 46 + struct ssam_request rqst; 47 + struct ssam_response rsp; 48 + u32 buffer_len, offset, length; 49 + int status; 50 + 51 + /* 52 + * Note: The 0x76 above has been chosen because that's what's used by 53 + * the Windows driver. Together with the header, this leads to a 128 54 + * byte payload in total. 55 + */ 56 + 57 + buffer_len = ARRAY_SIZE(buffer) - sizeof(struct surface_hid_buffer_slice); 58 + 59 + rqst.target_category = shid->uid.category; 60 + rqst.target_id = shid->uid.target; 61 + rqst.command_id = SURFACE_HID_CID_GET_DESCRIPTOR; 62 + rqst.instance_id = shid->uid.instance; 63 + rqst.flags = SSAM_REQUEST_HAS_RESPONSE; 64 + rqst.length = sizeof(struct surface_hid_buffer_slice); 65 + rqst.payload = buffer; 66 + 67 + rsp.capacity = ARRAY_SIZE(buffer); 68 + rsp.pointer = buffer; 69 + 70 + slice = (struct surface_hid_buffer_slice *)buffer; 71 + slice->entry = entry; 72 + slice->end = 0; 73 + 74 + offset = 0; 75 + length = buffer_len; 76 + 77 + while (!slice->end && offset < len) { 78 + put_unaligned_le32(offset, &slice->offset); 79 + put_unaligned_le32(length, &slice->length); 80 + 81 + rsp.length = 0; 82 + 83 + status = ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp, 84 + sizeof(*slice)); 85 + if (status) 86 + return status; 87 + 88 + offset = get_unaligned_le32(&slice->offset); 89 + length = get_unaligned_le32(&slice->length); 90 + 91 + /* Don't mess stuff up in case we receive garbage. */ 92 + if (length > buffer_len || offset > len) 93 + return -EPROTO; 94 + 95 + if (offset + length > len) 96 + length = len - offset; 97 + 98 + memcpy(buf + offset, &slice->data[0], length); 99 + 100 + offset += length; 101 + length = buffer_len; 102 + } 103 + 104 + if (offset != len) { 105 + dev_err(shid->dev, "unexpected descriptor length: got %u, expected %zu\n", 106 + offset, len); 107 + return -EPROTO; 108 + } 109 + 110 + return 0; 111 + } 112 + 113 + static int ssam_hid_set_raw_report(struct surface_hid_device *shid, u8 rprt_id, bool feature, 114 + u8 *buf, size_t len) 115 + { 116 + struct ssam_request rqst; 117 + u8 cid; 118 + 119 + if (feature) 120 + cid = SURFACE_HID_CID_SET_FEATURE_REPORT; 121 + else 122 + cid = SURFACE_HID_CID_OUTPUT_REPORT; 123 + 124 + rqst.target_category = shid->uid.category; 125 + rqst.target_id = shid->uid.target; 126 + rqst.instance_id = shid->uid.instance; 127 + rqst.command_id = cid; 128 + rqst.flags = 0; 129 + rqst.length = len; 130 + rqst.payload = buf; 131 + 132 + buf[0] = rprt_id; 133 + 134 + return ssam_retry(ssam_request_sync, shid->ctrl, &rqst, NULL); 135 + } 136 + 137 + static int ssam_hid_get_raw_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) 138 + { 139 + struct ssam_request rqst; 140 + struct ssam_response rsp; 141 + 142 + rqst.target_category = shid->uid.category; 143 + rqst.target_id = shid->uid.target; 144 + rqst.instance_id = shid->uid.instance; 145 + rqst.command_id = SURFACE_HID_CID_GET_FEATURE_REPORT; 146 + rqst.flags = 0; 147 + rqst.length = sizeof(rprt_id); 148 + rqst.payload = &rprt_id; 149 + 150 + rsp.capacity = len; 151 + rsp.length = 0; 152 + rsp.pointer = buf; 153 + 154 + return ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp, sizeof(rprt_id)); 155 + } 156 + 157 + static u32 ssam_hid_event_fn(struct ssam_event_notifier *nf, const struct ssam_event *event) 158 + { 159 + struct surface_hid_device *shid = container_of(nf, struct surface_hid_device, notif); 160 + 161 + if (event->command_id != 0x00) 162 + return 0; 163 + 164 + hid_input_report(shid->hid, HID_INPUT_REPORT, (u8 *)&event->data[0], event->length, 0); 165 + return SSAM_NOTIF_HANDLED; 166 + } 167 + 168 + 169 + /* -- Transport driver. ----------------------------------------------------- */ 170 + 171 + static int shid_output_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) 172 + { 173 + int status; 174 + 175 + status = ssam_hid_set_raw_report(shid, rprt_id, false, buf, len); 176 + return status >= 0 ? len : status; 177 + } 178 + 179 + static int shid_get_feature_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) 180 + { 181 + int status; 182 + 183 + status = ssam_hid_get_raw_report(shid, rprt_id, buf, len); 184 + return status >= 0 ? len : status; 185 + } 186 + 187 + static int shid_set_feature_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) 188 + { 189 + int status; 190 + 191 + status = ssam_hid_set_raw_report(shid, rprt_id, true, buf, len); 192 + return status >= 0 ? len : status; 193 + } 194 + 195 + 196 + /* -- Driver setup. --------------------------------------------------------- */ 197 + 198 + static int surface_hid_probe(struct ssam_device *sdev) 199 + { 200 + struct surface_hid_device *shid; 201 + 202 + shid = devm_kzalloc(&sdev->dev, sizeof(*shid), GFP_KERNEL); 203 + if (!shid) 204 + return -ENOMEM; 205 + 206 + shid->dev = &sdev->dev; 207 + shid->ctrl = sdev->ctrl; 208 + shid->uid = sdev->uid; 209 + 210 + shid->notif.base.priority = 1; 211 + shid->notif.base.fn = ssam_hid_event_fn; 212 + shid->notif.event.reg = SSAM_EVENT_REGISTRY_REG; 213 + shid->notif.event.id.target_category = sdev->uid.category; 214 + shid->notif.event.id.instance = sdev->uid.instance; 215 + shid->notif.event.mask = SSAM_EVENT_MASK_STRICT; 216 + shid->notif.event.flags = 0; 217 + 218 + shid->ops.get_descriptor = ssam_hid_get_descriptor; 219 + shid->ops.output_report = shid_output_report; 220 + shid->ops.get_feature_report = shid_get_feature_report; 221 + shid->ops.set_feature_report = shid_set_feature_report; 222 + 223 + ssam_device_set_drvdata(sdev, shid); 224 + return surface_hid_device_add(shid); 225 + } 226 + 227 + static void surface_hid_remove(struct ssam_device *sdev) 228 + { 229 + surface_hid_device_destroy(ssam_device_get_drvdata(sdev)); 230 + } 231 + 232 + static const struct ssam_device_id surface_hid_match[] = { 233 + { SSAM_SDEV(HID, 0x02, SSAM_ANY_IID, 0x00) }, 234 + { }, 235 + }; 236 + MODULE_DEVICE_TABLE(ssam, surface_hid_match); 237 + 238 + static struct ssam_device_driver surface_hid_driver = { 239 + .probe = surface_hid_probe, 240 + .remove = surface_hid_remove, 241 + .match_table = surface_hid_match, 242 + .driver = { 243 + .name = "surface_hid", 244 + .pm = &surface_hid_pm_ops, 245 + .probe_type = PROBE_PREFER_ASYNCHRONOUS, 246 + }, 247 + }; 248 + module_ssam_device_driver(surface_hid_driver); 249 + 250 + MODULE_AUTHOR("Blaž Hrastnik <blaz@mxxn.io>"); 251 + MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); 252 + MODULE_DESCRIPTION("HID transport driver for Surface System Aggregator Module"); 253 + MODULE_LICENSE("GPL");
+272
drivers/hid/surface-hid/surface_hid_core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Common/core components for the Surface System Aggregator Module (SSAM) HID 4 + * transport driver. Provides support for integrated HID devices on Microsoft 5 + * Surface models. 6 + * 7 + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com> 8 + */ 9 + 10 + #include <asm/unaligned.h> 11 + #include <linux/hid.h> 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/types.h> 15 + #include <linux/usb/ch9.h> 16 + 17 + #include <linux/surface_aggregator/controller.h> 18 + 19 + #include "surface_hid_core.h" 20 + 21 + 22 + /* -- Device descriptor access. --------------------------------------------- */ 23 + 24 + static int surface_hid_load_hid_descriptor(struct surface_hid_device *shid) 25 + { 26 + int status; 27 + 28 + status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_HID, 29 + (u8 *)&shid->hid_desc, sizeof(shid->hid_desc)); 30 + if (status) 31 + return status; 32 + 33 + if (shid->hid_desc.desc_len != sizeof(shid->hid_desc)) { 34 + dev_err(shid->dev, "unexpected HID descriptor length: got %u, expected %zu\n", 35 + shid->hid_desc.desc_len, sizeof(shid->hid_desc)); 36 + return -EPROTO; 37 + } 38 + 39 + if (shid->hid_desc.desc_type != HID_DT_HID) { 40 + dev_err(shid->dev, "unexpected HID descriptor type: got %#04x, expected %#04x\n", 41 + shid->hid_desc.desc_type, HID_DT_HID); 42 + return -EPROTO; 43 + } 44 + 45 + if (shid->hid_desc.num_descriptors != 1) { 46 + dev_err(shid->dev, "unexpected number of descriptors: got %u, expected 1\n", 47 + shid->hid_desc.num_descriptors); 48 + return -EPROTO; 49 + } 50 + 51 + if (shid->hid_desc.report_desc_type != HID_DT_REPORT) { 52 + dev_err(shid->dev, "unexpected report descriptor type: got %#04x, expected %#04x\n", 53 + shid->hid_desc.report_desc_type, HID_DT_REPORT); 54 + return -EPROTO; 55 + } 56 + 57 + return 0; 58 + } 59 + 60 + static int surface_hid_load_device_attributes(struct surface_hid_device *shid) 61 + { 62 + int status; 63 + 64 + status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_ATTRS, 65 + (u8 *)&shid->attrs, sizeof(shid->attrs)); 66 + if (status) 67 + return status; 68 + 69 + if (get_unaligned_le32(&shid->attrs.length) != sizeof(shid->attrs)) { 70 + dev_err(shid->dev, "unexpected attribute length: got %u, expected %zu\n", 71 + get_unaligned_le32(&shid->attrs.length), sizeof(shid->attrs)); 72 + return -EPROTO; 73 + } 74 + 75 + return 0; 76 + } 77 + 78 + 79 + /* -- Transport driver (common). -------------------------------------------- */ 80 + 81 + static int surface_hid_start(struct hid_device *hid) 82 + { 83 + struct surface_hid_device *shid = hid->driver_data; 84 + 85 + return ssam_notifier_register(shid->ctrl, &shid->notif); 86 + } 87 + 88 + static void surface_hid_stop(struct hid_device *hid) 89 + { 90 + struct surface_hid_device *shid = hid->driver_data; 91 + 92 + /* Note: This call will log errors for us, so ignore them here. */ 93 + ssam_notifier_unregister(shid->ctrl, &shid->notif); 94 + } 95 + 96 + static int surface_hid_open(struct hid_device *hid) 97 + { 98 + return 0; 99 + } 100 + 101 + static void surface_hid_close(struct hid_device *hid) 102 + { 103 + } 104 + 105 + static int surface_hid_parse(struct hid_device *hid) 106 + { 107 + struct surface_hid_device *shid = hid->driver_data; 108 + size_t len = get_unaligned_le16(&shid->hid_desc.report_desc_len); 109 + u8 *buf; 110 + int status; 111 + 112 + buf = kzalloc(len, GFP_KERNEL); 113 + if (!buf) 114 + return -ENOMEM; 115 + 116 + status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_REPORT, buf, len); 117 + if (!status) 118 + status = hid_parse_report(hid, buf, len); 119 + 120 + kfree(buf); 121 + return status; 122 + } 123 + 124 + static int surface_hid_raw_request(struct hid_device *hid, unsigned char reportnum, u8 *buf, 125 + size_t len, unsigned char rtype, int reqtype) 126 + { 127 + struct surface_hid_device *shid = hid->driver_data; 128 + 129 + if (rtype == HID_OUTPUT_REPORT && reqtype == HID_REQ_SET_REPORT) 130 + return shid->ops.output_report(shid, reportnum, buf, len); 131 + 132 + else if (rtype == HID_FEATURE_REPORT && reqtype == HID_REQ_GET_REPORT) 133 + return shid->ops.get_feature_report(shid, reportnum, buf, len); 134 + 135 + else if (rtype == HID_FEATURE_REPORT && reqtype == HID_REQ_SET_REPORT) 136 + return shid->ops.set_feature_report(shid, reportnum, buf, len); 137 + 138 + return -EIO; 139 + } 140 + 141 + static struct hid_ll_driver surface_hid_ll_driver = { 142 + .start = surface_hid_start, 143 + .stop = surface_hid_stop, 144 + .open = surface_hid_open, 145 + .close = surface_hid_close, 146 + .parse = surface_hid_parse, 147 + .raw_request = surface_hid_raw_request, 148 + }; 149 + 150 + 151 + /* -- Common device setup. -------------------------------------------------- */ 152 + 153 + int surface_hid_device_add(struct surface_hid_device *shid) 154 + { 155 + int status; 156 + 157 + status = surface_hid_load_hid_descriptor(shid); 158 + if (status) 159 + return status; 160 + 161 + status = surface_hid_load_device_attributes(shid); 162 + if (status) 163 + return status; 164 + 165 + shid->hid = hid_allocate_device(); 166 + if (IS_ERR(shid->hid)) 167 + return PTR_ERR(shid->hid); 168 + 169 + shid->hid->dev.parent = shid->dev; 170 + shid->hid->bus = BUS_HOST; 171 + shid->hid->vendor = cpu_to_le16(shid->attrs.vendor); 172 + shid->hid->product = cpu_to_le16(shid->attrs.product); 173 + shid->hid->version = cpu_to_le16(shid->hid_desc.hid_version); 174 + shid->hid->country = shid->hid_desc.country_code; 175 + 176 + snprintf(shid->hid->name, sizeof(shid->hid->name), "Microsoft Surface %04X:%04X", 177 + shid->hid->vendor, shid->hid->product); 178 + 179 + strscpy(shid->hid->phys, dev_name(shid->dev), sizeof(shid->hid->phys)); 180 + 181 + shid->hid->driver_data = shid; 182 + shid->hid->ll_driver = &surface_hid_ll_driver; 183 + 184 + status = hid_add_device(shid->hid); 185 + if (status) 186 + hid_destroy_device(shid->hid); 187 + 188 + return status; 189 + } 190 + EXPORT_SYMBOL_GPL(surface_hid_device_add); 191 + 192 + void surface_hid_device_destroy(struct surface_hid_device *shid) 193 + { 194 + hid_destroy_device(shid->hid); 195 + } 196 + EXPORT_SYMBOL_GPL(surface_hid_device_destroy); 197 + 198 + 199 + /* -- PM ops. --------------------------------------------------------------- */ 200 + 201 + #ifdef CONFIG_PM_SLEEP 202 + 203 + static int surface_hid_suspend(struct device *dev) 204 + { 205 + struct surface_hid_device *d = dev_get_drvdata(dev); 206 + 207 + if (d->hid->driver && d->hid->driver->suspend) 208 + return d->hid->driver->suspend(d->hid, PMSG_SUSPEND); 209 + 210 + return 0; 211 + } 212 + 213 + static int surface_hid_resume(struct device *dev) 214 + { 215 + struct surface_hid_device *d = dev_get_drvdata(dev); 216 + 217 + if (d->hid->driver && d->hid->driver->resume) 218 + return d->hid->driver->resume(d->hid); 219 + 220 + return 0; 221 + } 222 + 223 + static int surface_hid_freeze(struct device *dev) 224 + { 225 + struct surface_hid_device *d = dev_get_drvdata(dev); 226 + 227 + if (d->hid->driver && d->hid->driver->suspend) 228 + return d->hid->driver->suspend(d->hid, PMSG_FREEZE); 229 + 230 + return 0; 231 + } 232 + 233 + static int surface_hid_poweroff(struct device *dev) 234 + { 235 + struct surface_hid_device *d = dev_get_drvdata(dev); 236 + 237 + if (d->hid->driver && d->hid->driver->suspend) 238 + return d->hid->driver->suspend(d->hid, PMSG_HIBERNATE); 239 + 240 + return 0; 241 + } 242 + 243 + static int surface_hid_restore(struct device *dev) 244 + { 245 + struct surface_hid_device *d = dev_get_drvdata(dev); 246 + 247 + if (d->hid->driver && d->hid->driver->reset_resume) 248 + return d->hid->driver->reset_resume(d->hid); 249 + 250 + return 0; 251 + } 252 + 253 + const struct dev_pm_ops surface_hid_pm_ops = { 254 + .freeze = surface_hid_freeze, 255 + .thaw = surface_hid_resume, 256 + .suspend = surface_hid_suspend, 257 + .resume = surface_hid_resume, 258 + .poweroff = surface_hid_poweroff, 259 + .restore = surface_hid_restore, 260 + }; 261 + EXPORT_SYMBOL_GPL(surface_hid_pm_ops); 262 + 263 + #else /* CONFIG_PM_SLEEP */ 264 + 265 + const struct dev_pm_ops surface_hid_pm_ops = { }; 266 + EXPORT_SYMBOL_GPL(surface_hid_pm_ops); 267 + 268 + #endif /* CONFIG_PM_SLEEP */ 269 + 270 + MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); 271 + MODULE_DESCRIPTION("HID transport driver core for Surface System Aggregator Module"); 272 + MODULE_LICENSE("GPL");
+77
drivers/hid/surface-hid/surface_hid_core.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Common/core components for the Surface System Aggregator Module (SSAM) HID 4 + * transport driver. Provides support for integrated HID devices on Microsoft 5 + * Surface models. 6 + * 7 + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com> 8 + */ 9 + 10 + #ifndef SURFACE_HID_CORE_H 11 + #define SURFACE_HID_CORE_H 12 + 13 + #include <linux/hid.h> 14 + #include <linux/pm.h> 15 + #include <linux/types.h> 16 + 17 + #include <linux/surface_aggregator/controller.h> 18 + #include <linux/surface_aggregator/device.h> 19 + 20 + enum surface_hid_descriptor_entry { 21 + SURFACE_HID_DESC_HID = 0, 22 + SURFACE_HID_DESC_REPORT = 1, 23 + SURFACE_HID_DESC_ATTRS = 2, 24 + }; 25 + 26 + struct surface_hid_descriptor { 27 + __u8 desc_len; /* = 9 */ 28 + __u8 desc_type; /* = HID_DT_HID */ 29 + __le16 hid_version; 30 + __u8 country_code; 31 + __u8 num_descriptors; /* = 1 */ 32 + 33 + __u8 report_desc_type; /* = HID_DT_REPORT */ 34 + __le16 report_desc_len; 35 + } __packed; 36 + 37 + static_assert(sizeof(struct surface_hid_descriptor) == 9); 38 + 39 + struct surface_hid_attributes { 40 + __le32 length; 41 + __le16 vendor; 42 + __le16 product; 43 + __le16 version; 44 + __u8 _unknown[22]; 45 + } __packed; 46 + 47 + static_assert(sizeof(struct surface_hid_attributes) == 32); 48 + 49 + struct surface_hid_device; 50 + 51 + struct surface_hid_device_ops { 52 + int (*get_descriptor)(struct surface_hid_device *shid, u8 entry, u8 *buf, size_t len); 53 + int (*output_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len); 54 + int (*get_feature_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len); 55 + int (*set_feature_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len); 56 + }; 57 + 58 + struct surface_hid_device { 59 + struct device *dev; 60 + struct ssam_controller *ctrl; 61 + struct ssam_device_uid uid; 62 + 63 + struct surface_hid_descriptor hid_desc; 64 + struct surface_hid_attributes attrs; 65 + 66 + struct ssam_event_notifier notif; 67 + struct hid_device *hid; 68 + 69 + struct surface_hid_device_ops ops; 70 + }; 71 + 72 + int surface_hid_device_add(struct surface_hid_device *shid); 73 + void surface_hid_device_destroy(struct surface_hid_device *shid); 74 + 75 + extern const struct dev_pm_ops surface_hid_pm_ops; 76 + 77 + #endif /* SURFACE_HID_CORE_H */
+300
drivers/hid/surface-hid/surface_kbd.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Surface System Aggregator Module (SSAM) HID transport driver for the legacy 4 + * keyboard interface (KBD/TC=0x08 subsystem). Provides support for the 5 + * integrated HID keyboard on Surface Laptops 1 and 2. 6 + * 7 + * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com> 8 + */ 9 + 10 + #include <asm/unaligned.h> 11 + #include <linux/hid.h> 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/types.h> 16 + 17 + #include <linux/surface_aggregator/controller.h> 18 + 19 + #include "surface_hid_core.h" 20 + 21 + 22 + /* -- SAM interface (KBD). -------------------------------------------------- */ 23 + 24 + #define KBD_FEATURE_REPORT_SIZE 7 /* 6 + report ID */ 25 + 26 + enum surface_kbd_cid { 27 + SURFACE_KBD_CID_GET_DESCRIPTOR = 0x00, 28 + SURFACE_KBD_CID_SET_CAPSLOCK_LED = 0x01, 29 + SURFACE_KBD_CID_EVT_INPUT_GENERIC = 0x03, 30 + SURFACE_KBD_CID_EVT_INPUT_HOTKEYS = 0x04, 31 + SURFACE_KBD_CID_GET_FEATURE_REPORT = 0x0b, 32 + }; 33 + 34 + static int ssam_kbd_get_descriptor(struct surface_hid_device *shid, u8 entry, u8 *buf, size_t len) 35 + { 36 + struct ssam_request rqst; 37 + struct ssam_response rsp; 38 + int status; 39 + 40 + rqst.target_category = shid->uid.category; 41 + rqst.target_id = shid->uid.target; 42 + rqst.command_id = SURFACE_KBD_CID_GET_DESCRIPTOR; 43 + rqst.instance_id = shid->uid.instance; 44 + rqst.flags = SSAM_REQUEST_HAS_RESPONSE; 45 + rqst.length = sizeof(entry); 46 + rqst.payload = &entry; 47 + 48 + rsp.capacity = len; 49 + rsp.length = 0; 50 + rsp.pointer = buf; 51 + 52 + status = ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp, sizeof(entry)); 53 + if (status) 54 + return status; 55 + 56 + if (rsp.length != len) { 57 + dev_err(shid->dev, "invalid descriptor length: got %zu, expected, %zu\n", 58 + rsp.length, len); 59 + return -EPROTO; 60 + } 61 + 62 + return 0; 63 + } 64 + 65 + static int ssam_kbd_set_caps_led(struct surface_hid_device *shid, bool value) 66 + { 67 + struct ssam_request rqst; 68 + u8 value_u8 = value; 69 + 70 + rqst.target_category = shid->uid.category; 71 + rqst.target_id = shid->uid.target; 72 + rqst.command_id = SURFACE_KBD_CID_SET_CAPSLOCK_LED; 73 + rqst.instance_id = shid->uid.instance; 74 + rqst.flags = 0; 75 + rqst.length = sizeof(value_u8); 76 + rqst.payload = &value_u8; 77 + 78 + return ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, NULL, sizeof(value_u8)); 79 + } 80 + 81 + static int ssam_kbd_get_feature_report(struct surface_hid_device *shid, u8 *buf, size_t len) 82 + { 83 + struct ssam_request rqst; 84 + struct ssam_response rsp; 85 + u8 payload = 0; 86 + int status; 87 + 88 + rqst.target_category = shid->uid.category; 89 + rqst.target_id = shid->uid.target; 90 + rqst.command_id = SURFACE_KBD_CID_GET_FEATURE_REPORT; 91 + rqst.instance_id = shid->uid.instance; 92 + rqst.flags = SSAM_REQUEST_HAS_RESPONSE; 93 + rqst.length = sizeof(payload); 94 + rqst.payload = &payload; 95 + 96 + rsp.capacity = len; 97 + rsp.length = 0; 98 + rsp.pointer = buf; 99 + 100 + status = ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp, sizeof(payload)); 101 + if (status) 102 + return status; 103 + 104 + if (rsp.length != len) { 105 + dev_err(shid->dev, "invalid feature report length: got %zu, expected, %zu\n", 106 + rsp.length, len); 107 + return -EPROTO; 108 + } 109 + 110 + return 0; 111 + } 112 + 113 + static bool ssam_kbd_is_input_event(const struct ssam_event *event) 114 + { 115 + if (event->command_id == SURFACE_KBD_CID_EVT_INPUT_GENERIC) 116 + return true; 117 + 118 + if (event->command_id == SURFACE_KBD_CID_EVT_INPUT_HOTKEYS) 119 + return true; 120 + 121 + return false; 122 + } 123 + 124 + static u32 ssam_kbd_event_fn(struct ssam_event_notifier *nf, const struct ssam_event *event) 125 + { 126 + struct surface_hid_device *shid = container_of(nf, struct surface_hid_device, notif); 127 + 128 + /* 129 + * Check against device UID manually, as registry and device target 130 + * category doesn't line up. 131 + */ 132 + 133 + if (shid->uid.category != event->target_category) 134 + return 0; 135 + 136 + if (shid->uid.target != event->target_id) 137 + return 0; 138 + 139 + if (shid->uid.instance != event->instance_id) 140 + return 0; 141 + 142 + if (!ssam_kbd_is_input_event(event)) 143 + return 0; 144 + 145 + hid_input_report(shid->hid, HID_INPUT_REPORT, (u8 *)&event->data[0], event->length, 0); 146 + return SSAM_NOTIF_HANDLED; 147 + } 148 + 149 + 150 + /* -- Transport driver (KBD). ----------------------------------------------- */ 151 + 152 + static int skbd_get_caps_led_value(struct hid_device *hid, u8 rprt_id, u8 *buf, size_t len) 153 + { 154 + struct hid_field *field; 155 + unsigned int offset, size; 156 + int i; 157 + 158 + /* Get LED field. */ 159 + field = hidinput_get_led_field(hid); 160 + if (!field) 161 + return -ENOENT; 162 + 163 + /* Check if we got the correct report. */ 164 + if (len != hid_report_len(field->report)) 165 + return -ENOENT; 166 + 167 + if (rprt_id != field->report->id) 168 + return -ENOENT; 169 + 170 + /* Get caps lock LED index. */ 171 + for (i = 0; i < field->report_count; i++) 172 + if ((field->usage[i].hid & 0xffff) == 0x02) 173 + break; 174 + 175 + if (i == field->report_count) 176 + return -ENOENT; 177 + 178 + /* Extract value. */ 179 + size = field->report_size; 180 + offset = field->report_offset + i * size; 181 + return !!hid_field_extract(hid, buf + 1, size, offset); 182 + } 183 + 184 + static int skbd_output_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) 185 + { 186 + int caps_led; 187 + int status; 188 + 189 + caps_led = skbd_get_caps_led_value(shid->hid, rprt_id, buf, len); 190 + if (caps_led < 0) 191 + return -EIO; /* Only caps LED output reports are supported. */ 192 + 193 + status = ssam_kbd_set_caps_led(shid, caps_led); 194 + if (status < 0) 195 + return status; 196 + 197 + return len; 198 + } 199 + 200 + static int skbd_get_feature_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) 201 + { 202 + u8 report[KBD_FEATURE_REPORT_SIZE]; 203 + int status; 204 + 205 + /* 206 + * The keyboard only has a single hard-coded read-only feature report 207 + * of size KBD_FEATURE_REPORT_SIZE. Try to load it and compare its 208 + * report ID against the requested one. 209 + */ 210 + 211 + if (len < ARRAY_SIZE(report)) 212 + return -ENOSPC; 213 + 214 + status = ssam_kbd_get_feature_report(shid, report, ARRAY_SIZE(report)); 215 + if (status < 0) 216 + return status; 217 + 218 + if (rprt_id != report[0]) 219 + return -ENOENT; 220 + 221 + memcpy(buf, report, ARRAY_SIZE(report)); 222 + return len; 223 + } 224 + 225 + static int skbd_set_feature_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) 226 + { 227 + /* Not supported. See skbd_get_feature_report() for details. */ 228 + return -EIO; 229 + } 230 + 231 + 232 + /* -- Driver setup. --------------------------------------------------------- */ 233 + 234 + static int surface_kbd_probe(struct platform_device *pdev) 235 + { 236 + struct ssam_controller *ctrl; 237 + struct surface_hid_device *shid; 238 + 239 + /* Add device link to EC. */ 240 + ctrl = ssam_client_bind(&pdev->dev); 241 + if (IS_ERR(ctrl)) 242 + return PTR_ERR(ctrl) == -ENODEV ? -EPROBE_DEFER : PTR_ERR(ctrl); 243 + 244 + shid = devm_kzalloc(&pdev->dev, sizeof(*shid), GFP_KERNEL); 245 + if (!shid) 246 + return -ENOMEM; 247 + 248 + shid->dev = &pdev->dev; 249 + shid->ctrl = ctrl; 250 + 251 + shid->uid.domain = SSAM_DOMAIN_SERIALHUB; 252 + shid->uid.category = SSAM_SSH_TC_KBD; 253 + shid->uid.target = 2; 254 + shid->uid.instance = 0; 255 + shid->uid.function = 0; 256 + 257 + shid->notif.base.priority = 1; 258 + shid->notif.base.fn = ssam_kbd_event_fn; 259 + shid->notif.event.reg = SSAM_EVENT_REGISTRY_SAM; 260 + shid->notif.event.id.target_category = shid->uid.category; 261 + shid->notif.event.id.instance = shid->uid.instance; 262 + shid->notif.event.mask = SSAM_EVENT_MASK_NONE; 263 + shid->notif.event.flags = 0; 264 + 265 + shid->ops.get_descriptor = ssam_kbd_get_descriptor; 266 + shid->ops.output_report = skbd_output_report; 267 + shid->ops.get_feature_report = skbd_get_feature_report; 268 + shid->ops.set_feature_report = skbd_set_feature_report; 269 + 270 + platform_set_drvdata(pdev, shid); 271 + return surface_hid_device_add(shid); 272 + } 273 + 274 + static int surface_kbd_remove(struct platform_device *pdev) 275 + { 276 + surface_hid_device_destroy(platform_get_drvdata(pdev)); 277 + return 0; 278 + } 279 + 280 + static const struct acpi_device_id surface_kbd_match[] = { 281 + { "MSHW0096" }, 282 + { }, 283 + }; 284 + MODULE_DEVICE_TABLE(acpi, surface_kbd_match); 285 + 286 + static struct platform_driver surface_kbd_driver = { 287 + .probe = surface_kbd_probe, 288 + .remove = surface_kbd_remove, 289 + .driver = { 290 + .name = "surface_keyboard", 291 + .acpi_match_table = surface_kbd_match, 292 + .pm = &surface_hid_pm_ops, 293 + .probe_type = PROBE_PREFER_ASYNCHRONOUS, 294 + }, 295 + }; 296 + module_platform_driver(surface_kbd_driver); 297 + 298 + MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); 299 + MODULE_DESCRIPTION("HID legacy transport driver for Surface System Aggregator Module"); 300 + MODULE_LICENSE("GPL");
+2 -2
drivers/hid/usbhid/hid-pidff.c
··· 505 505 HID_REQ_SET_REPORT); 506 506 } 507 507 508 - /** 508 + /* 509 509 * Play the effect with effect id @effect_id for @value times 510 510 */ 511 511 static int pidff_playback(struct input_dev *dev, int effect_id, int value) ··· 997 997 return 0; 998 998 } 999 999 1000 - /** 1000 + /* 1001 1001 * Find the implemented effect types 1002 1002 */ 1003 1003 static int pidff_find_effects(struct pidff_device *pidff,
+3 -3
drivers/hid/usbhid/hiddev.c
··· 887 887 break; 888 888 889 889 if (i == hid->maxcollection) 890 - return -1; 890 + return -EINVAL; 891 891 } 892 892 893 893 if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) 894 - return -1; 894 + return -ENOMEM; 895 895 896 896 init_waitqueue_head(&hiddev->wait); 897 897 INIT_LIST_HEAD(&hiddev->list); ··· 905 905 hid_err(hid, "Not able to get a minor for this device\n"); 906 906 hid->hiddev = NULL; 907 907 kfree(hiddev); 908 - return -1; 908 + return retval; 909 909 } 910 910 911 911 /*
+9 -9
drivers/hid/usbhid/usbkbd.c
··· 63 63 * new key is pressed or a key that was pressed is released. 64 64 * @led: URB for sending LEDs (e.g. numlock, ...) 65 65 * @newleds: data that will be sent with the @led URB representing which LEDs 66 - should be on 66 + * should be on 67 67 * @name: Name of the keyboard. @dev's name field points to this buffer 68 68 * @phys: Physical path of the keyboard. @dev's phys field points to this 69 69 * buffer ··· 91 91 unsigned char *leds; 92 92 dma_addr_t new_dma; 93 93 dma_addr_t leds_dma; 94 - 94 + 95 95 spinlock_t leds_lock; 96 96 bool led_urb_submitted; 97 97 ··· 175 175 } 176 176 177 177 *(kbd->leds) = kbd->newleds; 178 - 178 + 179 179 kbd->led->dev = kbd->usbdev; 180 180 if (usb_submit_urb(kbd->led, GFP_ATOMIC)) 181 181 pr_err("usb_submit_urb(leds) failed\n"); 182 182 else 183 183 kbd->led_urb_submitted = true; 184 - 184 + 185 185 spin_unlock_irqrestore(&kbd->leds_lock, flags); 186 - 186 + 187 187 return 0; 188 188 } 189 189 ··· 205 205 } 206 206 207 207 *(kbd->leds) = kbd->newleds; 208 - 208 + 209 209 kbd->led->dev = kbd->usbdev; 210 210 if (usb_submit_urb(kbd->led, GFP_ATOMIC)){ 211 211 hid_err(urb->dev, "usb_submit_urb(leds) failed\n"); 212 212 kbd->led_urb_submitted = false; 213 213 } 214 214 spin_unlock_irqrestore(&kbd->leds_lock, flags); 215 - 215 + 216 216 } 217 217 218 218 static int usb_kbd_open(struct input_dev *dev) ··· 358 358 device_set_wakeup_enable(&dev->dev, 1); 359 359 return 0; 360 360 361 - fail2: 361 + fail2: 362 362 usb_kbd_free_mem(dev, kbd); 363 - fail1: 363 + fail1: 364 364 input_free_device(input_dev); 365 365 kfree(kbd); 366 366 return error;
+1 -1
drivers/hid/wacom_sys.c
··· 1495 1495 return &group->leds[id]; 1496 1496 } 1497 1497 1498 - /** 1498 + /* 1499 1499 * wacom_led_next: gives the next available led with a wacom trigger. 1500 1500 * 1501 1501 * returns the next available struct wacom_led which has its default trigger
+26 -24
drivers/hid/wacom_wac.c
··· 1860 1860 usage->type = type; 1861 1861 usage->code = code; 1862 1862 1863 - set_bit(type, input->evbit); 1864 - 1865 1863 switch (type) { 1866 1864 case EV_ABS: 1867 1865 input_set_abs_params(input, code, fmin, fmax, fuzz, 0); ··· 1867 1869 hidinput_calc_abs_res(field, resolution_code)); 1868 1870 break; 1869 1871 case EV_KEY: 1870 - input_set_capability(input, EV_KEY, code); 1871 - break; 1872 1872 case EV_MSC: 1873 - input_set_capability(input, EV_MSC, code); 1874 - break; 1875 1873 case EV_SW: 1876 - input_set_capability(input, EV_SW, code); 1874 + input_set_capability(input, type, code); 1877 1875 break; 1878 1876 } 1879 1877 } ··· 2181 2187 } 2182 2188 } 2183 2189 2190 + static void wacom_set_barrel_switch3_usage(struct wacom_wac *wacom_wac) 2191 + { 2192 + struct input_dev *input = wacom_wac->pen_input; 2193 + struct wacom_features *features = &wacom_wac->features; 2194 + 2195 + if (!(features->quirks & WACOM_QUIRK_AESPEN) && 2196 + wacom_wac->hid_data.barrelswitch && 2197 + wacom_wac->hid_data.barrelswitch2 && 2198 + wacom_wac->hid_data.serialhi) 2199 + input_set_capability(input, EV_KEY, BTN_STYLUS3); 2200 + } 2201 + 2184 2202 static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, 2185 2203 struct hid_field *field, struct hid_usage *usage) 2186 2204 { ··· 2233 2227 wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0); 2234 2228 break; 2235 2229 case HID_DG_ERASER: 2230 + input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER); 2231 + wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0); 2232 + break; 2236 2233 case HID_DG_TIPSWITCH: 2234 + input_set_capability(input, EV_KEY, BTN_TOOL_PEN); 2237 2235 wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0); 2238 2236 break; 2239 2237 case HID_DG_BARRELSWITCH: 2238 + wacom_wac->hid_data.barrelswitch = true; 2239 + wacom_set_barrel_switch3_usage(wacom_wac); 2240 2240 wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS, 0); 2241 2241 break; 2242 2242 case HID_DG_BARRELSWITCH2: 2243 + wacom_wac->hid_data.barrelswitch2 = true; 2244 + wacom_set_barrel_switch3_usage(wacom_wac); 2243 2245 wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS2, 0); 2244 2246 break; 2245 2247 case HID_DG_TOOLSERIALNUMBER: ··· 2259 2245 wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0); 2260 2246 break; 2261 2247 case WACOM_HID_WD_SERIALHI: 2248 + wacom_wac->hid_data.serialhi = true; 2249 + wacom_set_barrel_switch3_usage(wacom_wac); 2262 2250 wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0); 2263 - 2264 - if (!(features->quirks & WACOM_QUIRK_AESPEN)) { 2265 - set_bit(EV_KEY, input->evbit); 2266 - input_set_capability(input, EV_KEY, BTN_TOOL_PEN); 2267 - input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER); 2268 - input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH); 2269 - input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL); 2270 - input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH); 2271 - if (!(features->device_type & WACOM_DEVICETYPE_DIRECT)) { 2272 - input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE); 2273 - input_set_capability(input, EV_KEY, BTN_TOOL_LENS); 2274 - } 2275 - } 2276 2251 break; 2277 2252 case WACOM_HID_WD_FINGERWHEEL: 2253 + input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH); 2278 2254 wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); 2279 2255 break; 2280 2256 } ··· 3586 3582 else 3587 3583 __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 3588 3584 3589 - if (features->type == HID_GENERIC) { 3590 - /* setup has already been done; apply otherwise-undetectible quirks */ 3591 - input_set_capability(input_dev, EV_KEY, BTN_STYLUS3); 3585 + if (features->type == HID_GENERIC) 3586 + /* setup has already been done */ 3592 3587 return 0; 3593 - } 3594 3588 3595 3589 input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 3596 3590 __set_bit(BTN_TOUCH, input_dev->keybit);
+1
drivers/hid/wacom_wac.h
··· 300 300 bool tipswitch; 301 301 bool barrelswitch; 302 302 bool barrelswitch2; 303 + bool serialhi; 303 304 int x; 304 305 int y; 305 306 int pressure;
+5
include/linux/hid.h
··· 153 153 #define HID_UP_CONSUMER 0x000c0000 154 154 #define HID_UP_DIGITIZER 0x000d0000 155 155 #define HID_UP_PID 0x000f0000 156 + #define HID_UP_BATTERY 0x00850000 156 157 #define HID_UP_HPVENDOR 0xff7f0000 157 158 #define HID_UP_HPVENDOR2 0xff010000 158 159 #define HID_UP_MSVENDOR 0xff000000 ··· 263 262 #define HID_CP_SELECTION 0x000c0080 264 263 #define HID_CP_MEDIASELECTION 0x000c0087 265 264 #define HID_CP_SELECTDISC 0x000c00ba 265 + #define HID_CP_VOLUMEUP 0x000c00e9 266 + #define HID_CP_VOLUMEDOWN 0x000c00ea 266 267 #define HID_CP_PLAYBACKSPEED 0x000c00f1 267 268 #define HID_CP_PROXIMITY 0x000c0109 268 269 #define HID_CP_SPEAKERSYSTEM 0x000c0160 ··· 299 296 #define HID_DG_BARRELSWITCH2 0x000d005a 300 297 #define HID_DG_TOOLSERIALNUMBER 0x000d005b 301 298 #define HID_DG_LATENCYMODE 0x000d0060 299 + 300 + #define HID_BAT_ABSOLUTESTATEOFCHARGE 0x00850065 302 301 303 302 #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076 304 303 /*