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