1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * HID driver for Steelseries devices 4 * 5 * Copyright (c) 2013 Simon Wood 6 * Copyright (c) 2023 Bastien Nocera 7 */ 8 9 /* 10 */ 11 12 #include <linux/device.h> 13 #include <linux/hid.h> 14 #include <linux/module.h> 15 #include <linux/usb.h> 16 #include <linux/leds.h> 17 18 #include "hid-ids.h" 19 20 #define STEELSERIES_SRWS1 BIT(0) 21 #define STEELSERIES_ARCTIS_1 BIT(1) 22 23 struct steelseries_device { 24 struct hid_device *hdev; 25 unsigned long quirks; 26 27 struct delayed_work battery_work; 28 spinlock_t lock; 29 bool removed; 30 31 struct power_supply_desc battery_desc; 32 struct power_supply *battery; 33 uint8_t battery_capacity; 34 bool headset_connected; 35 }; 36 37 #if IS_BUILTIN(CONFIG_LEDS_CLASS) || \ 38 (IS_MODULE(CONFIG_LEDS_CLASS) && IS_MODULE(CONFIG_HID_STEELSERIES)) 39 #define SRWS1_NUMBER_LEDS 15 40 struct steelseries_srws1_data { 41 __u16 led_state; 42 /* the last element is used for setting all leds simultaneously */ 43 struct led_classdev *led[SRWS1_NUMBER_LEDS + 1]; 44 }; 45 #endif 46 47 /* Fixed report descriptor for Steelseries SRW-S1 wheel controller 48 * 49 * The original descriptor hides the sensitivity and assists dials 50 * a custom vendor usage page. This inserts a patch to make them 51 * appear in the 'Generic Desktop' usage. 52 */ 53 54 static __u8 steelseries_srws1_rdesc_fixed[] = { 55 0x05, 0x01, /* Usage Page (Desktop) */ 56 0x09, 0x08, /* Usage (MultiAxis), Changed */ 57 0xA1, 0x01, /* Collection (Application), */ 58 0xA1, 0x02, /* Collection (Logical), */ 59 0x95, 0x01, /* Report Count (1), */ 60 0x05, 0x01, /* Changed Usage Page (Desktop), */ 61 0x09, 0x30, /* Changed Usage (X), */ 62 0x16, 0xF8, 0xF8, /* Logical Minimum (-1800), */ 63 0x26, 0x08, 0x07, /* Logical Maximum (1800), */ 64 0x65, 0x14, /* Unit (Degrees), */ 65 0x55, 0x0F, /* Unit Exponent (15), */ 66 0x75, 0x10, /* Report Size (16), */ 67 0x81, 0x02, /* Input (Variable), */ 68 0x09, 0x31, /* Changed Usage (Y), */ 69 0x15, 0x00, /* Logical Minimum (0), */ 70 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 71 0x75, 0x0C, /* Report Size (12), */ 72 0x81, 0x02, /* Input (Variable), */ 73 0x09, 0x32, /* Changed Usage (Z), */ 74 0x15, 0x00, /* Logical Minimum (0), */ 75 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 76 0x75, 0x0C, /* Report Size (12), */ 77 0x81, 0x02, /* Input (Variable), */ 78 0x05, 0x01, /* Usage Page (Desktop), */ 79 0x09, 0x39, /* Usage (Hat Switch), */ 80 0x25, 0x07, /* Logical Maximum (7), */ 81 0x35, 0x00, /* Physical Minimum (0), */ 82 0x46, 0x3B, 0x01, /* Physical Maximum (315), */ 83 0x65, 0x14, /* Unit (Degrees), */ 84 0x75, 0x04, /* Report Size (4), */ 85 0x95, 0x01, /* Report Count (1), */ 86 0x81, 0x02, /* Input (Variable), */ 87 0x25, 0x01, /* Logical Maximum (1), */ 88 0x45, 0x01, /* Physical Maximum (1), */ 89 0x65, 0x00, /* Unit, */ 90 0x75, 0x01, /* Report Size (1), */ 91 0x95, 0x03, /* Report Count (3), */ 92 0x81, 0x01, /* Input (Constant), */ 93 0x05, 0x09, /* Usage Page (Button), */ 94 0x19, 0x01, /* Usage Minimum (01h), */ 95 0x29, 0x11, /* Usage Maximum (11h), */ 96 0x95, 0x11, /* Report Count (17), */ 97 0x81, 0x02, /* Input (Variable), */ 98 /* ---- Dial patch starts here ---- */ 99 0x05, 0x01, /* Usage Page (Desktop), */ 100 0x09, 0x33, /* Usage (RX), */ 101 0x75, 0x04, /* Report Size (4), */ 102 0x95, 0x02, /* Report Count (2), */ 103 0x15, 0x00, /* Logical Minimum (0), */ 104 0x25, 0x0b, /* Logical Maximum (b), */ 105 0x81, 0x02, /* Input (Variable), */ 106 0x09, 0x35, /* Usage (RZ), */ 107 0x75, 0x04, /* Report Size (4), */ 108 0x95, 0x01, /* Report Count (1), */ 109 0x25, 0x03, /* Logical Maximum (3), */ 110 0x81, 0x02, /* Input (Variable), */ 111 /* ---- Dial patch ends here ---- */ 112 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 113 0x09, 0x01, /* Usage (01h), */ 114 0x75, 0x04, /* Changed Report Size (4), */ 115 0x95, 0x0D, /* Changed Report Count (13), */ 116 0x81, 0x02, /* Input (Variable), */ 117 0xC0, /* End Collection, */ 118 0xA1, 0x02, /* Collection (Logical), */ 119 0x09, 0x02, /* Usage (02h), */ 120 0x75, 0x08, /* Report Size (8), */ 121 0x95, 0x10, /* Report Count (16), */ 122 0x91, 0x02, /* Output (Variable), */ 123 0xC0, /* End Collection, */ 124 0xC0 /* End Collection */ 125 }; 126 127 #if IS_BUILTIN(CONFIG_LEDS_CLASS) || \ 128 (IS_MODULE(CONFIG_LEDS_CLASS) && IS_MODULE(CONFIG_HID_STEELSERIES)) 129 static void steelseries_srws1_set_leds(struct hid_device *hdev, __u16 leds) 130 { 131 struct list_head *report_list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; 132 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 133 __s32 *value = report->field[0]->value; 134 135 value[0] = 0x40; 136 value[1] = leds & 0xFF; 137 value[2] = leds >> 8; 138 value[3] = 0x00; 139 value[4] = 0x00; 140 value[5] = 0x00; 141 value[6] = 0x00; 142 value[7] = 0x00; 143 value[8] = 0x00; 144 value[9] = 0x00; 145 value[10] = 0x00; 146 value[11] = 0x00; 147 value[12] = 0x00; 148 value[13] = 0x00; 149 value[14] = 0x00; 150 value[15] = 0x00; 151 152 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 153 154 /* Note: LED change does not show on device until the device is read/polled */ 155 } 156 157 static void steelseries_srws1_led_all_set_brightness(struct led_classdev *led_cdev, 158 enum led_brightness value) 159 { 160 struct device *dev = led_cdev->dev->parent; 161 struct hid_device *hid = to_hid_device(dev); 162 struct steelseries_srws1_data *drv_data = hid_get_drvdata(hid); 163 164 if (!drv_data) { 165 hid_err(hid, "Device data not found."); 166 return; 167 } 168 169 if (value == LED_OFF) 170 drv_data->led_state = 0; 171 else 172 drv_data->led_state = (1 << (SRWS1_NUMBER_LEDS + 1)) - 1; 173 174 steelseries_srws1_set_leds(hid, drv_data->led_state); 175 } 176 177 static enum led_brightness steelseries_srws1_led_all_get_brightness(struct led_classdev *led_cdev) 178 { 179 struct device *dev = led_cdev->dev->parent; 180 struct hid_device *hid = to_hid_device(dev); 181 struct steelseries_srws1_data *drv_data; 182 183 drv_data = hid_get_drvdata(hid); 184 185 if (!drv_data) { 186 hid_err(hid, "Device data not found."); 187 return LED_OFF; 188 } 189 190 return (drv_data->led_state >> SRWS1_NUMBER_LEDS) ? LED_FULL : LED_OFF; 191 } 192 193 static void steelseries_srws1_led_set_brightness(struct led_classdev *led_cdev, 194 enum led_brightness value) 195 { 196 struct device *dev = led_cdev->dev->parent; 197 struct hid_device *hid = to_hid_device(dev); 198 struct steelseries_srws1_data *drv_data = hid_get_drvdata(hid); 199 int i, state = 0; 200 201 if (!drv_data) { 202 hid_err(hid, "Device data not found."); 203 return; 204 } 205 206 for (i = 0; i < SRWS1_NUMBER_LEDS; i++) { 207 if (led_cdev != drv_data->led[i]) 208 continue; 209 210 state = (drv_data->led_state >> i) & 1; 211 if (value == LED_OFF && state) { 212 drv_data->led_state &= ~(1 << i); 213 steelseries_srws1_set_leds(hid, drv_data->led_state); 214 } else if (value != LED_OFF && !state) { 215 drv_data->led_state |= 1 << i; 216 steelseries_srws1_set_leds(hid, drv_data->led_state); 217 } 218 break; 219 } 220 } 221 222 static enum led_brightness steelseries_srws1_led_get_brightness(struct led_classdev *led_cdev) 223 { 224 struct device *dev = led_cdev->dev->parent; 225 struct hid_device *hid = to_hid_device(dev); 226 struct steelseries_srws1_data *drv_data; 227 int i, value = 0; 228 229 drv_data = hid_get_drvdata(hid); 230 231 if (!drv_data) { 232 hid_err(hid, "Device data not found."); 233 return LED_OFF; 234 } 235 236 for (i = 0; i < SRWS1_NUMBER_LEDS; i++) 237 if (led_cdev == drv_data->led[i]) { 238 value = (drv_data->led_state >> i) & 1; 239 break; 240 } 241 242 return value ? LED_FULL : LED_OFF; 243 } 244 245 static int steelseries_srws1_probe(struct hid_device *hdev, 246 const struct hid_device_id *id) 247 { 248 int ret, i; 249 struct led_classdev *led; 250 size_t name_sz; 251 char *name; 252 253 struct steelseries_srws1_data *drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL); 254 255 if (drv_data == NULL) { 256 hid_err(hdev, "can't alloc SRW-S1 memory\n"); 257 return -ENOMEM; 258 } 259 260 hid_set_drvdata(hdev, drv_data); 261 262 ret = hid_parse(hdev); 263 if (ret) { 264 hid_err(hdev, "parse failed\n"); 265 goto err_free; 266 } 267 268 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 16)) { 269 ret = -ENODEV; 270 goto err_free; 271 } 272 273 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 274 if (ret) { 275 hid_err(hdev, "hw start failed\n"); 276 goto err_free; 277 } 278 279 /* register led subsystem */ 280 drv_data->led_state = 0; 281 for (i = 0; i < SRWS1_NUMBER_LEDS + 1; i++) 282 drv_data->led[i] = NULL; 283 284 steelseries_srws1_set_leds(hdev, 0); 285 286 name_sz = strlen(hdev->uniq) + 16; 287 288 /* 'ALL', for setting all LEDs simultaneously */ 289 led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); 290 if (!led) { 291 hid_err(hdev, "can't allocate memory for LED ALL\n"); 292 goto err_led; 293 } 294 295 name = (void *)(&led[1]); 296 snprintf(name, name_sz, "SRWS1::%s::RPMALL", hdev->uniq); 297 led->name = name; 298 led->brightness = 0; 299 led->max_brightness = 1; 300 led->brightness_get = steelseries_srws1_led_all_get_brightness; 301 led->brightness_set = steelseries_srws1_led_all_set_brightness; 302 303 drv_data->led[SRWS1_NUMBER_LEDS] = led; 304 ret = led_classdev_register(&hdev->dev, led); 305 if (ret) 306 goto err_led; 307 308 /* Each individual LED */ 309 for (i = 0; i < SRWS1_NUMBER_LEDS; i++) { 310 led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); 311 if (!led) { 312 hid_err(hdev, "can't allocate memory for LED %d\n", i); 313 goto err_led; 314 } 315 316 name = (void *)(&led[1]); 317 snprintf(name, name_sz, "SRWS1::%s::RPM%d", hdev->uniq, i+1); 318 led->name = name; 319 led->brightness = 0; 320 led->max_brightness = 1; 321 led->brightness_get = steelseries_srws1_led_get_brightness; 322 led->brightness_set = steelseries_srws1_led_set_brightness; 323 324 drv_data->led[i] = led; 325 ret = led_classdev_register(&hdev->dev, led); 326 327 if (ret) { 328 hid_err(hdev, "failed to register LED %d. Aborting.\n", i); 329 err_led: 330 /* Deregister all LEDs (if any) */ 331 for (i = 0; i < SRWS1_NUMBER_LEDS + 1; i++) { 332 led = drv_data->led[i]; 333 drv_data->led[i] = NULL; 334 if (!led) 335 continue; 336 led_classdev_unregister(led); 337 kfree(led); 338 } 339 goto out; /* but let the driver continue without LEDs */ 340 } 341 } 342 out: 343 return 0; 344 err_free: 345 kfree(drv_data); 346 return ret; 347 } 348 349 static void steelseries_srws1_remove(struct hid_device *hdev) 350 { 351 int i; 352 struct led_classdev *led; 353 354 struct steelseries_srws1_data *drv_data = hid_get_drvdata(hdev); 355 356 if (drv_data) { 357 /* Deregister LEDs (if any) */ 358 for (i = 0; i < SRWS1_NUMBER_LEDS + 1; i++) { 359 led = drv_data->led[i]; 360 drv_data->led[i] = NULL; 361 if (!led) 362 continue; 363 led_classdev_unregister(led); 364 kfree(led); 365 } 366 367 } 368 369 hid_hw_stop(hdev); 370 kfree(drv_data); 371 return; 372 } 373 #endif 374 375 #define STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS 3000 376 377 #define ARCTIS_1_BATTERY_RESPONSE_LEN 8 378 static const char arctis_1_battery_request[] = { 0x06, 0x12 }; 379 380 static int steelseries_headset_arctis_1_fetch_battery(struct hid_device *hdev) 381 { 382 u8 *write_buf; 383 int ret; 384 385 /* Request battery information */ 386 write_buf = kmemdup(arctis_1_battery_request, sizeof(arctis_1_battery_request), GFP_KERNEL); 387 if (!write_buf) 388 return -ENOMEM; 389 390 ret = hid_hw_raw_request(hdev, arctis_1_battery_request[0], 391 write_buf, sizeof(arctis_1_battery_request), 392 HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 393 if (ret < sizeof(arctis_1_battery_request)) { 394 hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret); 395 ret = -ENODATA; 396 } 397 kfree(write_buf); 398 return ret; 399 } 400 401 static void steelseries_headset_fetch_battery(struct hid_device *hdev) 402 { 403 struct steelseries_device *sd = hid_get_drvdata(hdev); 404 int ret = 0; 405 406 if (sd->quirks & STEELSERIES_ARCTIS_1) 407 ret = steelseries_headset_arctis_1_fetch_battery(hdev); 408 409 if (ret < 0) 410 hid_dbg(hdev, 411 "Battery query failed (err: %d)\n", ret); 412 } 413 414 static void steelseries_headset_battery_timer_tick(struct work_struct *work) 415 { 416 struct steelseries_device *sd = container_of(work, 417 struct steelseries_device, battery_work.work); 418 struct hid_device *hdev = sd->hdev; 419 420 steelseries_headset_fetch_battery(hdev); 421 } 422 423 static int steelseries_headset_battery_get_property(struct power_supply *psy, 424 enum power_supply_property psp, 425 union power_supply_propval *val) 426 { 427 struct steelseries_device *sd = power_supply_get_drvdata(psy); 428 int ret = 0; 429 430 switch (psp) { 431 case POWER_SUPPLY_PROP_PRESENT: 432 val->intval = 1; 433 break; 434 case POWER_SUPPLY_PROP_STATUS: 435 val->intval = sd->headset_connected ? 436 POWER_SUPPLY_STATUS_DISCHARGING : 437 POWER_SUPPLY_STATUS_UNKNOWN; 438 break; 439 case POWER_SUPPLY_PROP_SCOPE: 440 val->intval = POWER_SUPPLY_SCOPE_DEVICE; 441 break; 442 case POWER_SUPPLY_PROP_CAPACITY: 443 val->intval = sd->battery_capacity; 444 break; 445 default: 446 ret = -EINVAL; 447 break; 448 } 449 return ret; 450 } 451 452 static void 453 steelseries_headset_set_wireless_status(struct hid_device *hdev, 454 bool connected) 455 { 456 struct usb_interface *intf; 457 458 if (!hid_is_usb(hdev)) 459 return; 460 461 intf = to_usb_interface(hdev->dev.parent); 462 usb_set_wireless_status(intf, connected ? 463 USB_WIRELESS_STATUS_CONNECTED : 464 USB_WIRELESS_STATUS_DISCONNECTED); 465 } 466 467 static enum power_supply_property steelseries_headset_battery_props[] = { 468 POWER_SUPPLY_PROP_PRESENT, 469 POWER_SUPPLY_PROP_STATUS, 470 POWER_SUPPLY_PROP_SCOPE, 471 POWER_SUPPLY_PROP_CAPACITY, 472 }; 473 474 static int steelseries_headset_battery_register(struct steelseries_device *sd) 475 { 476 static atomic_t battery_no = ATOMIC_INIT(0); 477 struct power_supply_config battery_cfg = { .drv_data = sd, }; 478 unsigned long n; 479 int ret; 480 481 sd->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY; 482 sd->battery_desc.properties = steelseries_headset_battery_props; 483 sd->battery_desc.num_properties = ARRAY_SIZE(steelseries_headset_battery_props); 484 sd->battery_desc.get_property = steelseries_headset_battery_get_property; 485 sd->battery_desc.use_for_apm = 0; 486 n = atomic_inc_return(&battery_no) - 1; 487 sd->battery_desc.name = devm_kasprintf(&sd->hdev->dev, GFP_KERNEL, 488 "steelseries_headset_battery_%ld", n); 489 if (!sd->battery_desc.name) 490 return -ENOMEM; 491 492 /* avoid the warning of 0% battery while waiting for the first info */ 493 steelseries_headset_set_wireless_status(sd->hdev, false); 494 sd->battery_capacity = 100; 495 496 sd->battery = devm_power_supply_register(&sd->hdev->dev, 497 &sd->battery_desc, &battery_cfg); 498 if (IS_ERR(sd->battery)) { 499 ret = PTR_ERR(sd->battery); 500 hid_err(sd->hdev, 501 "%s:power_supply_register failed with error %d\n", 502 __func__, ret); 503 return ret; 504 } 505 power_supply_powers(sd->battery, &sd->hdev->dev); 506 507 INIT_DELAYED_WORK(&sd->battery_work, steelseries_headset_battery_timer_tick); 508 steelseries_headset_fetch_battery(sd->hdev); 509 510 return 0; 511 } 512 513 static int steelseries_probe(struct hid_device *hdev, const struct hid_device_id *id) 514 { 515 struct steelseries_device *sd; 516 int ret; 517 518 sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL); 519 if (!sd) 520 return -ENOMEM; 521 hid_set_drvdata(hdev, sd); 522 sd->hdev = hdev; 523 sd->quirks = id->driver_data; 524 525 if (sd->quirks & STEELSERIES_SRWS1) { 526 #if IS_BUILTIN(CONFIG_LEDS_CLASS) || \ 527 (IS_MODULE(CONFIG_LEDS_CLASS) && IS_MODULE(CONFIG_HID_STEELSERIES)) 528 return steelseries_srws1_probe(hdev, id); 529 #else 530 return -ENODEV; 531 #endif 532 } 533 534 ret = hid_parse(hdev); 535 if (ret) 536 return ret; 537 538 spin_lock_init(&sd->lock); 539 540 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 541 if (ret) 542 return ret; 543 544 if (steelseries_headset_battery_register(sd) < 0) 545 hid_err(sd->hdev, 546 "Failed to register battery for headset\n"); 547 548 return ret; 549 } 550 551 static void steelseries_remove(struct hid_device *hdev) 552 { 553 struct steelseries_device *sd = hid_get_drvdata(hdev); 554 unsigned long flags; 555 556 if (sd->quirks & STEELSERIES_SRWS1) { 557 #if IS_BUILTIN(CONFIG_LEDS_CLASS) || \ 558 (IS_MODULE(CONFIG_LEDS_CLASS) && IS_MODULE(CONFIG_HID_STEELSERIES)) 559 steelseries_srws1_remove(hdev); 560 #endif 561 return; 562 } 563 564 spin_lock_irqsave(&sd->lock, flags); 565 sd->removed = true; 566 spin_unlock_irqrestore(&sd->lock, flags); 567 568 cancel_delayed_work_sync(&sd->battery_work); 569 570 hid_hw_stop(hdev); 571 } 572 573 static __u8 *steelseries_srws1_report_fixup(struct hid_device *hdev, __u8 *rdesc, 574 unsigned int *rsize) 575 { 576 if (hdev->vendor != USB_VENDOR_ID_STEELSERIES || 577 hdev->product != USB_DEVICE_ID_STEELSERIES_SRWS1) 578 return rdesc; 579 580 if (*rsize >= 115 && rdesc[11] == 0x02 && rdesc[13] == 0xc8 581 && rdesc[29] == 0xbb && rdesc[40] == 0xc5) { 582 hid_info(hdev, "Fixing up Steelseries SRW-S1 report descriptor\n"); 583 rdesc = steelseries_srws1_rdesc_fixed; 584 *rsize = sizeof(steelseries_srws1_rdesc_fixed); 585 } 586 return rdesc; 587 } 588 589 static int steelseries_headset_raw_event(struct hid_device *hdev, 590 struct hid_report *report, u8 *read_buf, 591 int size) 592 { 593 struct steelseries_device *sd = hid_get_drvdata(hdev); 594 int capacity = sd->battery_capacity; 595 bool connected = sd->headset_connected; 596 unsigned long flags; 597 598 /* Not a headset */ 599 if (sd->quirks & STEELSERIES_SRWS1) 600 return 0; 601 602 if (sd->quirks & STEELSERIES_ARCTIS_1) { 603 hid_dbg(sd->hdev, 604 "Parsing raw event for Arctis 1 headset (%*ph)\n", size, read_buf); 605 if (size < ARCTIS_1_BATTERY_RESPONSE_LEN || 606 memcmp (read_buf, arctis_1_battery_request, sizeof(arctis_1_battery_request))) 607 return 0; 608 if (read_buf[2] == 0x01) { 609 connected = false; 610 capacity = 100; 611 } else { 612 connected = true; 613 capacity = read_buf[3]; 614 } 615 } 616 617 if (connected != sd->headset_connected) { 618 hid_dbg(sd->hdev, 619 "Connected status changed from %sconnected to %sconnected\n", 620 sd->headset_connected ? "" : "not ", 621 connected ? "" : "not "); 622 sd->headset_connected = connected; 623 steelseries_headset_set_wireless_status(hdev, connected); 624 } 625 626 if (capacity != sd->battery_capacity) { 627 hid_dbg(sd->hdev, 628 "Battery capacity changed from %d%% to %d%%\n", 629 sd->battery_capacity, capacity); 630 sd->battery_capacity = capacity; 631 power_supply_changed(sd->battery); 632 } 633 634 spin_lock_irqsave(&sd->lock, flags); 635 if (!sd->removed) 636 schedule_delayed_work(&sd->battery_work, 637 msecs_to_jiffies(STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS)); 638 spin_unlock_irqrestore(&sd->lock, flags); 639 640 return 0; 641 } 642 643 static const struct hid_device_id steelseries_devices[] = { 644 { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1), 645 .driver_data = STEELSERIES_SRWS1 }, 646 647 { /* SteelSeries Arctis 1 Wireless for XBox */ 648 HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, 0x12b6), 649 .driver_data = STEELSERIES_ARCTIS_1 }, 650 651 { } 652 }; 653 MODULE_DEVICE_TABLE(hid, steelseries_devices); 654 655 static struct hid_driver steelseries_driver = { 656 .name = "steelseries", 657 .id_table = steelseries_devices, 658 .probe = steelseries_probe, 659 .remove = steelseries_remove, 660 .report_fixup = steelseries_srws1_report_fixup, 661 .raw_event = steelseries_headset_raw_event, 662 }; 663 664 module_hid_driver(steelseries_driver); 665 MODULE_LICENSE("GPL"); 666 MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>"); 667 MODULE_AUTHOR("Simon Wood <simon@mungewell.org>"); 668