1 // SPDX-License-Identifier: GPL-2.0 2 3 /* 4 * HID driver for WinWing Orion 2 throttle 5 * 6 * Copyright (c) 2023 Ivan Gorinov 7 */ 8 9 #include <linux/device.h> 10 #include <linux/hid.h> 11 #include <linux/hidraw.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/mutex.h> 15 #include <linux/workqueue.h> 16 17 #define MAX_REPORT 16 18 19 struct winwing_led { 20 struct led_classdev cdev; 21 struct hid_device *hdev; 22 int number; 23 }; 24 25 struct winwing_led_info { 26 int number; 27 int max_brightness; 28 const char *led_name; 29 }; 30 31 static const struct winwing_led_info led_info[3] = { 32 { 0, 255, "backlight" }, 33 { 1, 1, "a-a" }, 34 { 2, 1, "a-g" }, 35 }; 36 37 struct winwing_drv_data { 38 struct hid_device *hdev; 39 struct mutex lights_lock; 40 __u8 *report_lights; 41 __u8 *report_rumble; 42 struct work_struct rumble_work; 43 struct ff_rumble_effect rumble; 44 int rumble_left; 45 int rumble_right; 46 int has_grip15; 47 struct winwing_led leds[]; 48 }; 49 50 static int winwing_led_write(struct led_classdev *cdev, 51 enum led_brightness br) 52 { 53 struct winwing_led *led = (struct winwing_led *) cdev; 54 struct winwing_drv_data *data = hid_get_drvdata(led->hdev); 55 __u8 *buf = data->report_lights; 56 int ret; 57 58 mutex_lock(&data->lights_lock); 59 60 /* 61 * Mimicking requests captured by usbmon when LEDs 62 * are controlled by the vendor's app in a VM. 63 */ 64 buf[0] = 0x02; 65 buf[1] = 0x60; 66 buf[2] = 0xbe; 67 buf[3] = 0x00; 68 buf[4] = 0x00; 69 buf[5] = 0x03; 70 buf[6] = 0x49; 71 buf[7] = led->number; 72 buf[8] = br; 73 buf[9] = 0x00; 74 buf[10] = 0; 75 buf[11] = 0; 76 buf[12] = 0; 77 buf[13] = 0; 78 79 ret = hid_hw_output_report(led->hdev, buf, 14); 80 81 mutex_unlock(&data->lights_lock); 82 83 return ret; 84 } 85 86 static int winwing_init_led(struct hid_device *hdev, 87 struct input_dev *input) 88 { 89 struct winwing_drv_data *data; 90 struct winwing_led *led; 91 int ret; 92 int i; 93 94 data = hid_get_drvdata(hdev); 95 96 if (!data) 97 return -EINVAL; 98 99 data->report_lights = devm_kzalloc(&hdev->dev, MAX_REPORT, GFP_KERNEL); 100 101 if (!data->report_lights) 102 return -ENOMEM; 103 104 for (i = 0; i < 3; i += 1) { 105 const struct winwing_led_info *info = &led_info[i]; 106 107 led = &data->leds[i]; 108 led->hdev = hdev; 109 led->number = info->number; 110 led->cdev.max_brightness = info->max_brightness; 111 led->cdev.brightness_set_blocking = winwing_led_write; 112 led->cdev.flags = LED_HW_PLUGGABLE; 113 led->cdev.name = devm_kasprintf(&hdev->dev, GFP_KERNEL, 114 "%s::%s", 115 dev_name(&input->dev), 116 info->led_name); 117 118 if (!led->cdev.name) 119 return -ENOMEM; 120 121 ret = devm_led_classdev_register(&hdev->dev, &led->cdev); 122 if (ret) 123 return ret; 124 } 125 126 return ret; 127 } 128 129 static int winwing_map_button(int button, int has_grip15) 130 { 131 if (button < 1) 132 return KEY_RESERVED; 133 134 if (button > 112) 135 return KEY_RESERVED; 136 137 if (button <= 16) { 138 /* 139 * Grip buttons [1 .. 16] are mapped to 140 * key codes BTN_TRIGGER .. BTN_DEAD 141 */ 142 return (button - 1) + BTN_JOYSTICK; 143 } 144 145 if (button >= 65) { 146 /* 147 * Base buttons [65 .. 112] are mapped to 148 * key codes BTN_TRIGGER_HAPPY17 .. KEY_MAX 149 */ 150 return (button - 65) + BTN_TRIGGER_HAPPY17; 151 } 152 153 if (!has_grip15) { 154 /* 155 * Not mapping numbers [33 .. 64] which 156 * are not assigned to any real buttons 157 */ 158 if (button >= 33) 159 return KEY_RESERVED; 160 /* 161 * Grip buttons [17 .. 32] are mapped to 162 * BTN_TRIGGER_HAPPY1 .. BTN_TRIGGER_HAPPY16 163 */ 164 return (button - 17) + BTN_TRIGGER_HAPPY1; 165 } 166 167 if (button >= 49) { 168 /* 169 * Grip buttons [49 .. 64] are mapped to 170 * BTN_TRIGGER_HAPPY1 .. BTN_TRIGGER_HAPPY16 171 */ 172 return (button - 49) + BTN_TRIGGER_HAPPY1; 173 } 174 175 /* 176 * Grip buttons [17 .. 44] are mapped to 177 * key codes KEY_MACRO1 .. KEY_MACRO28; 178 * also mapping numbers [45 .. 48] which 179 * are not assigned to any real buttons. 180 */ 181 return (button - 17) + KEY_MACRO1; 182 } 183 184 static int winwing_input_mapping(struct hid_device *hdev, 185 struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, 186 unsigned long **bit, int *max) 187 { 188 struct winwing_drv_data *data; 189 int code = KEY_RESERVED; 190 int button = 0; 191 192 data = hid_get_drvdata(hdev); 193 194 if (!data) 195 return -EINVAL; 196 197 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 198 return 0; 199 200 if (field->application != HID_GD_JOYSTICK) 201 return 0; 202 203 /* Button numbers start with 1 */ 204 button = usage->hid & HID_USAGE; 205 206 code = winwing_map_button(button, data->has_grip15); 207 208 hid_map_usage(hi, usage, bit, max, EV_KEY, code); 209 210 return 1; 211 } 212 213 /* 214 * If x ≤ 0, return 0; 215 * if x is in [1 .. 65535], return a value in [1 .. 255] 216 */ 217 static inline int convert_magnitude(int x) 218 { 219 if (x < 1) 220 return 0; 221 222 return ((x * 255) >> 16) + 1; 223 } 224 225 static int winwing_haptic_rumble(struct winwing_drv_data *data) 226 { 227 __u8 *buf; 228 __u8 m; 229 230 if (!data) 231 return -EINVAL; 232 233 if (!data->hdev) 234 return -EINVAL; 235 236 buf = data->report_rumble; 237 238 if (!buf) 239 return -EINVAL; 240 241 m = convert_magnitude(data->rumble.strong_magnitude); 242 if (m != data->rumble_left) { 243 int ret; 244 245 /* 246 * Mimicking requests captured by usbmon when rumble 247 * is activated by the vendor's app in a VM. 248 */ 249 buf[0] = 0x02; 250 buf[1] = 0x01; 251 buf[2] = 0xbf; 252 buf[3] = 0x00; 253 buf[4] = 0x00; 254 buf[5] = 0x03; 255 buf[6] = 0x49; 256 buf[7] = 0x00; 257 buf[8] = m; 258 buf[9] = 0x00; 259 buf[10] = 0; 260 buf[11] = 0; 261 buf[12] = 0; 262 buf[13] = 0; 263 264 ret = hid_hw_output_report(data->hdev, buf, 14); 265 if (ret < 0) { 266 hid_err(data->hdev, "error %d (%*ph)\n", ret, 14, buf); 267 return ret; 268 } 269 data->rumble_left = m; 270 } 271 272 m = convert_magnitude(data->rumble.weak_magnitude); 273 if (m != data->rumble_right) { 274 int ret; 275 276 /* 277 * Mimicking requests captured by usbmon when rumble 278 * is activated by the vendor's app in a VM. 279 */ 280 buf[0] = 0x02; 281 buf[1] = 0x03; 282 buf[2] = 0xbf; 283 buf[3] = 0x00; 284 buf[4] = 0x00; 285 buf[5] = 0x03; 286 buf[6] = 0x49; 287 buf[7] = 0x00; 288 buf[8] = m; 289 buf[9] = 0x00; 290 buf[10] = 0; 291 buf[11] = 0; 292 buf[12] = 0; 293 buf[13] = 0; 294 295 ret = hid_hw_output_report(data->hdev, buf, 14); 296 if (ret < 0) { 297 hid_err(data->hdev, "error %d (%*ph)\n", ret, 14, buf); 298 return ret; 299 } 300 data->rumble_right = m; 301 } 302 303 return 0; 304 } 305 306 307 static void winwing_haptic_rumble_cb(struct work_struct *work) 308 { 309 struct winwing_drv_data *data; 310 311 data = container_of(work, struct winwing_drv_data, rumble_work); 312 winwing_haptic_rumble(data); 313 } 314 315 static int winwing_play_effect(struct input_dev *dev, void *context, 316 struct ff_effect *effect) 317 { 318 struct winwing_drv_data *data = (struct winwing_drv_data *) context; 319 320 if (effect->type != FF_RUMBLE) 321 return 0; 322 323 if (!data) 324 return -EINVAL; 325 326 data->rumble = effect->u.rumble; 327 328 return schedule_work(&data->rumble_work); 329 } 330 331 static int winwing_init_ff(struct hid_device *hdev, struct hid_input *hidinput) 332 { 333 struct winwing_drv_data *data; 334 335 data = (struct winwing_drv_data *) hid_get_drvdata(hdev); 336 if (!data) 337 return -EINVAL; 338 339 data->report_rumble = devm_kzalloc(&hdev->dev, MAX_REPORT, GFP_KERNEL); 340 data->rumble_left = -1; 341 data->rumble_right = -1; 342 343 input_set_capability(hidinput->input, EV_FF, FF_RUMBLE); 344 345 return input_ff_create_memless(hidinput->input, data, 346 winwing_play_effect); 347 } 348 349 static int winwing_probe(struct hid_device *hdev, 350 const struct hid_device_id *id) 351 { 352 struct winwing_drv_data *data; 353 size_t data_size = struct_size(data, leds, 3); 354 int ret; 355 356 ret = hid_parse(hdev); 357 if (ret) { 358 hid_err(hdev, "parse failed\n"); 359 return ret; 360 } 361 362 data = devm_kzalloc(&hdev->dev, data_size, GFP_KERNEL); 363 364 if (!data) 365 return -ENOMEM; 366 367 data->hdev = hdev; 368 data->has_grip15 = id->driver_data; 369 hid_set_drvdata(hdev, data); 370 371 INIT_WORK(&data->rumble_work, winwing_haptic_rumble_cb); 372 373 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 374 if (ret) { 375 hid_err(hdev, "hw start failed\n"); 376 return ret; 377 } 378 379 return 0; 380 } 381 382 static void winwing_remove(struct hid_device *hdev) 383 { 384 struct winwing_drv_data *data; 385 386 data = (struct winwing_drv_data *) hid_get_drvdata(hdev); 387 388 if (data) 389 cancel_work_sync(&data->rumble_work); 390 391 hid_hw_close(hdev); 392 hid_hw_stop(hdev); 393 } 394 395 static int winwing_input_configured(struct hid_device *hdev, 396 struct hid_input *hidinput) 397 { 398 struct winwing_drv_data *data; 399 int ret; 400 401 data = (struct winwing_drv_data *) hid_get_drvdata(hdev); 402 403 ret = winwing_init_led(hdev, hidinput->input); 404 405 if (ret) 406 hid_err(hdev, "led init failed\n"); 407 408 if (data->has_grip15) 409 winwing_init_ff(hdev, hidinput); 410 411 return ret; 412 } 413 414 /* Set driver_data to 1 for grips with rumble motor and more than 32 buttons */ 415 static const struct hid_device_id winwing_devices[] = { 416 { HID_USB_DEVICE(0x4098, 0xbd65), .driver_data = 1 }, /* TGRIP-15E */ 417 { HID_USB_DEVICE(0x4098, 0xbd64), .driver_data = 1 }, /* TGRIP-15EX */ 418 { HID_USB_DEVICE(0x4098, 0xbe68), .driver_data = 0 }, /* TGRIP-16EX */ 419 { HID_USB_DEVICE(0x4098, 0xbe62), .driver_data = 0 }, /* TGRIP-18 */ 420 {} 421 }; 422 423 MODULE_DEVICE_TABLE(hid, winwing_devices); 424 425 static struct hid_driver winwing_driver = { 426 .name = "winwing", 427 .id_table = winwing_devices, 428 .input_configured = winwing_input_configured, 429 .input_mapping = winwing_input_mapping, 430 .probe = winwing_probe, 431 .remove = winwing_remove, 432 }; 433 module_hid_driver(winwing_driver); 434 435 MODULE_DESCRIPTION("HID driver for WinWing Orion 2 throttle"); 436 MODULE_LICENSE("GPL"); 437