1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * HID driver for Corsair Void headsets 4 * 5 * Copyright (C) 2023-2024 Stuart Hayhurst 6 */ 7 8 /* -------------------------------------------------------------------------- */ 9 /* Receiver report information: (ID 100) */ 10 /* -------------------------------------------------------------------------- */ 11 /* 12 * When queried, the receiver reponds with 5 bytes to describe the battery 13 * The power button, mute button and moving the mic also trigger this report 14 * This includes power button + mic + connection + battery status and capacity 15 * The information below may not be perfect, it's been gathered through guesses 16 * 17 * 0: REPORT ID 18 * 100 for the battery packet 19 * 20 * 1: POWER BUTTON + (?) 21 * Largest bit is 1 when power button pressed 22 * 23 * 2: BATTERY CAPACITY + MIC STATUS 24 * Battery capacity: 25 * Seems to report ~54 higher than reality when charging 26 * Capped at 100, charging or not 27 * Microphone status: 28 * Largest bit is set to 1 when the mic is physically up 29 * No bits change when the mic is muted, only when physically moved 30 * This report is sent every time the mic is moved, no polling required 31 * 32 * 3: CONNECTION STATUS 33 * 16: Wired headset 34 * 38: Initialising 35 * 49: Lost connection 36 * 51: Disconnected, searching 37 * 52: Disconnected, not searching 38 * 177: Normal 39 * 40 * 4: BATTERY STATUS 41 * 0: Disconnected 42 * 1: Normal 43 * 2: Low 44 * 3: Critical - sent during shutdown 45 * 4: Fully charged 46 * 5: Charging 47 */ 48 /* -------------------------------------------------------------------------- */ 49 50 /* -------------------------------------------------------------------------- */ 51 /* Receiver report information: (ID 102) */ 52 /* -------------------------------------------------------------------------- */ 53 /* 54 * When queried, the receiver responds with 5 bytes to describe the firmware 55 * The first byte is the ID, then 2 bytes for the receiver, then 2 for the headset 56 * The headset firmware version will be 0 if no headset is connected 57 * 58 * 0: Report ID 59 * 102 for the firmware packet 60 * 61 * 1: Receiver firmware major version 62 * Major version of the receiver's firmware 63 * 64 * 2: Receiver firmware minor version 65 * Minor version of the receiver's firmware 66 * 67 * 3: Headset firmware major version 68 * Major version of the headset's firmware 69 * 70 * 4: Headset firmware minor version 71 * Minor version of the headset's firmware 72 */ 73 /* -------------------------------------------------------------------------- */ 74 75 #include <linux/bitfield.h> 76 #include <linux/bitops.h> 77 #include <linux/device.h> 78 #include <linux/hid.h> 79 #include <linux/module.h> 80 #include <linux/power_supply.h> 81 #include <linux/usb.h> 82 #include <linux/workqueue.h> 83 #include <asm/byteorder.h> 84 85 #include "hid-ids.h" 86 87 #define CORSAIR_VOID_DEVICE(id, type) { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, (id)), \ 88 .driver_data = (type) } 89 #define CORSAIR_VOID_WIRELESS_DEVICE(id) CORSAIR_VOID_DEVICE((id), CORSAIR_VOID_WIRELESS) 90 #define CORSAIR_VOID_WIRED_DEVICE(id) CORSAIR_VOID_DEVICE((id), CORSAIR_VOID_WIRED) 91 92 #define CORSAIR_VOID_STATUS_REQUEST_ID 0xC9 93 #define CORSAIR_VOID_NOTIF_REQUEST_ID 0xCA 94 #define CORSAIR_VOID_SIDETONE_REQUEST_ID 0xFF 95 #define CORSAIR_VOID_STATUS_REPORT_ID 0x64 96 #define CORSAIR_VOID_FIRMWARE_REPORT_ID 0x66 97 98 #define CORSAIR_VOID_STATUS_REPORT_SIZE 5 99 #define CORSAIR_VOID_FIRMWARE_REPORT_SIZE 5 100 101 #define CORSAIR_VOID_USB_SIDETONE_REQUEST 0x1 102 #define CORSAIR_VOID_USB_SIDETONE_REQUEST_TYPE 0x21 103 #define CORSAIR_VOID_USB_SIDETONE_VALUE 0x200 104 #define CORSAIR_VOID_USB_SIDETONE_INDEX 0xB00 105 106 #define CORSAIR_VOID_MIC_MASK GENMASK(7, 7) 107 #define CORSAIR_VOID_CAPACITY_MASK GENMASK(6, 0) 108 109 #define CORSAIR_VOID_WIRELESS_CONNECTED 177 110 111 #define CORSAIR_VOID_SIDETONE_MAX_WIRELESS 55 112 #define CORSAIR_VOID_SIDETONE_MAX_WIRED 4096 113 114 enum { 115 CORSAIR_VOID_WIRELESS, 116 CORSAIR_VOID_WIRED, 117 }; 118 119 enum { 120 CORSAIR_VOID_BATTERY_NORMAL = 1, 121 CORSAIR_VOID_BATTERY_LOW = 2, 122 CORSAIR_VOID_BATTERY_CRITICAL = 3, 123 CORSAIR_VOID_BATTERY_CHARGED = 4, 124 CORSAIR_VOID_BATTERY_CHARGING = 5, 125 }; 126 127 enum { 128 CORSAIR_VOID_ADD_BATTERY = 0, 129 CORSAIR_VOID_REMOVE_BATTERY = 1, 130 CORSAIR_VOID_UPDATE_BATTERY = 2, 131 }; 132 133 static enum power_supply_property corsair_void_battery_props[] = { 134 POWER_SUPPLY_PROP_STATUS, 135 POWER_SUPPLY_PROP_PRESENT, 136 POWER_SUPPLY_PROP_CAPACITY, 137 POWER_SUPPLY_PROP_CAPACITY_LEVEL, 138 POWER_SUPPLY_PROP_SCOPE, 139 POWER_SUPPLY_PROP_MODEL_NAME, 140 POWER_SUPPLY_PROP_MANUFACTURER, 141 }; 142 143 struct corsair_void_battery_data { 144 int status; 145 bool present; 146 int capacity; 147 int capacity_level; 148 }; 149 150 struct corsair_void_drvdata { 151 struct hid_device *hid_dev; 152 struct device *dev; 153 154 char *name; 155 bool is_wired; 156 unsigned int sidetone_max; 157 158 struct corsair_void_battery_data battery_data; 159 bool mic_up; 160 bool connected; 161 int fw_receiver_major; 162 int fw_receiver_minor; 163 int fw_headset_major; 164 int fw_headset_minor; 165 166 struct power_supply *battery; 167 struct power_supply_desc battery_desc; 168 169 struct delayed_work delayed_status_work; 170 struct delayed_work delayed_firmware_work; 171 172 unsigned long battery_work_flags; 173 struct work_struct battery_work; 174 }; 175 176 /* 177 * Functions to process receiver data 178 */ 179 180 static void corsair_void_set_wireless_status(struct corsair_void_drvdata *drvdata) 181 { 182 struct usb_interface *usb_if = to_usb_interface(drvdata->dev->parent); 183 184 if (drvdata->is_wired) 185 return; 186 187 usb_set_wireless_status(usb_if, drvdata->connected ? 188 USB_WIRELESS_STATUS_CONNECTED : 189 USB_WIRELESS_STATUS_DISCONNECTED); 190 } 191 192 static void corsair_void_set_unknown_batt(struct corsair_void_drvdata *drvdata) 193 { 194 struct corsair_void_battery_data *battery_data = &drvdata->battery_data; 195 196 battery_data->status = POWER_SUPPLY_STATUS_UNKNOWN; 197 battery_data->present = false; 198 battery_data->capacity = 0; 199 battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; 200 } 201 202 /* Reset data that may change between wireless connections */ 203 static void corsair_void_set_unknown_wireless_data(struct corsair_void_drvdata *drvdata) 204 { 205 /* Only 0 out headset, receiver is always known if relevant */ 206 drvdata->fw_headset_major = 0; 207 drvdata->fw_headset_minor = 0; 208 209 drvdata->connected = false; 210 drvdata->mic_up = false; 211 212 corsair_void_set_wireless_status(drvdata); 213 } 214 215 static void corsair_void_process_receiver(struct corsair_void_drvdata *drvdata, 216 int raw_battery_capacity, 217 int raw_connection_status, 218 int raw_battery_status) 219 { 220 struct corsair_void_battery_data *battery_data = &drvdata->battery_data; 221 struct corsair_void_battery_data orig_battery_data; 222 223 /* Save initial battery data, to compare later */ 224 orig_battery_data = *battery_data; 225 226 /* Headset not connected, or it's wired */ 227 if (raw_connection_status != CORSAIR_VOID_WIRELESS_CONNECTED) 228 goto unknown_battery; 229 230 /* Battery information unavailable */ 231 if (raw_battery_status == 0) 232 goto unknown_battery; 233 234 /* Battery must be connected then */ 235 battery_data->present = true; 236 battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 237 238 /* Set battery status */ 239 switch (raw_battery_status) { 240 case CORSAIR_VOID_BATTERY_NORMAL: 241 case CORSAIR_VOID_BATTERY_LOW: 242 case CORSAIR_VOID_BATTERY_CRITICAL: 243 battery_data->status = POWER_SUPPLY_STATUS_DISCHARGING; 244 if (raw_battery_status == CORSAIR_VOID_BATTERY_LOW) 245 battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; 246 else if (raw_battery_status == CORSAIR_VOID_BATTERY_CRITICAL) 247 battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; 248 249 break; 250 case CORSAIR_VOID_BATTERY_CHARGED: 251 battery_data->status = POWER_SUPPLY_STATUS_FULL; 252 break; 253 case CORSAIR_VOID_BATTERY_CHARGING: 254 battery_data->status = POWER_SUPPLY_STATUS_CHARGING; 255 break; 256 default: 257 hid_warn(drvdata->hid_dev, "unknown battery status '%d'", 258 raw_battery_status); 259 goto unknown_battery; 260 break; 261 } 262 263 battery_data->capacity = raw_battery_capacity; 264 corsair_void_set_wireless_status(drvdata); 265 266 goto success; 267 unknown_battery: 268 corsair_void_set_unknown_batt(drvdata); 269 success: 270 271 /* Inform power supply if battery values changed */ 272 if (memcmp(&orig_battery_data, battery_data, sizeof(*battery_data))) { 273 set_bit(CORSAIR_VOID_UPDATE_BATTERY, 274 &drvdata->battery_work_flags); 275 schedule_work(&drvdata->battery_work); 276 } 277 } 278 279 /* 280 * Functions to report stored data 281 */ 282 283 static int corsair_void_battery_get_property(struct power_supply *psy, 284 enum power_supply_property prop, 285 union power_supply_propval *val) 286 { 287 struct corsair_void_drvdata *drvdata = power_supply_get_drvdata(psy); 288 289 switch (prop) { 290 case POWER_SUPPLY_PROP_SCOPE: 291 val->intval = POWER_SUPPLY_SCOPE_DEVICE; 292 break; 293 case POWER_SUPPLY_PROP_MODEL_NAME: 294 if (!strncmp(drvdata->hid_dev->name, "Corsair ", 8)) 295 val->strval = drvdata->hid_dev->name + 8; 296 else 297 val->strval = drvdata->hid_dev->name; 298 break; 299 case POWER_SUPPLY_PROP_MANUFACTURER: 300 val->strval = "Corsair"; 301 break; 302 case POWER_SUPPLY_PROP_STATUS: 303 val->intval = drvdata->battery_data.status; 304 break; 305 case POWER_SUPPLY_PROP_PRESENT: 306 val->intval = drvdata->battery_data.present; 307 break; 308 case POWER_SUPPLY_PROP_CAPACITY: 309 val->intval = drvdata->battery_data.capacity; 310 break; 311 case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 312 val->intval = drvdata->battery_data.capacity_level; 313 break; 314 default: 315 return -EINVAL; 316 } 317 318 return 0; 319 } 320 321 static ssize_t microphone_up_show(struct device *dev, 322 struct device_attribute *attr, char *buf) 323 { 324 struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev); 325 326 if (!drvdata->connected) 327 return -ENODEV; 328 329 return sysfs_emit(buf, "%d\n", drvdata->mic_up); 330 } 331 332 static ssize_t fw_version_receiver_show(struct device *dev, 333 struct device_attribute *attr, 334 char *buf) 335 { 336 struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev); 337 338 if (drvdata->fw_receiver_major == 0 && drvdata->fw_receiver_minor == 0) 339 return -ENODATA; 340 341 return sysfs_emit(buf, "%d.%02d\n", drvdata->fw_receiver_major, 342 drvdata->fw_receiver_minor); 343 } 344 345 346 static ssize_t fw_version_headset_show(struct device *dev, 347 struct device_attribute *attr, 348 char *buf) 349 { 350 struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev); 351 352 if (drvdata->fw_headset_major == 0 && drvdata->fw_headset_minor == 0) 353 return -ENODATA; 354 355 return sysfs_emit(buf, "%d.%02d\n", drvdata->fw_headset_major, 356 drvdata->fw_headset_minor); 357 } 358 359 static ssize_t sidetone_max_show(struct device *dev, 360 struct device_attribute *attr, 361 char *buf) 362 { 363 struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev); 364 365 return sysfs_emit(buf, "%d\n", drvdata->sidetone_max); 366 } 367 368 /* 369 * Functions to send data to headset 370 */ 371 372 static ssize_t send_alert_store(struct device *dev, 373 struct device_attribute *attr, 374 const char *buf, size_t count) 375 { 376 struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev); 377 struct hid_device *hid_dev = drvdata->hid_dev; 378 unsigned char alert_id; 379 unsigned char *send_buf __free(kfree) = NULL; 380 int ret; 381 382 if (!drvdata->connected || drvdata->is_wired) 383 return -ENODEV; 384 385 /* Only accept 0 or 1 for alert ID */ 386 if (kstrtou8(buf, 10, &alert_id) || alert_id >= 2) 387 return -EINVAL; 388 389 send_buf = kmalloc(3, GFP_KERNEL); 390 if (!send_buf) 391 return -ENOMEM; 392 393 /* Packet format to send alert with ID alert_id */ 394 send_buf[0] = CORSAIR_VOID_NOTIF_REQUEST_ID; 395 send_buf[1] = 0x02; 396 send_buf[2] = alert_id; 397 398 ret = hid_hw_raw_request(hid_dev, CORSAIR_VOID_NOTIF_REQUEST_ID, 399 send_buf, 3, HID_OUTPUT_REPORT, 400 HID_REQ_SET_REPORT); 401 if (ret < 0) 402 hid_warn(hid_dev, "failed to send alert request (reason: %d)", 403 ret); 404 else 405 ret = count; 406 407 return ret; 408 } 409 410 static int corsair_void_set_sidetone_wired(struct device *dev, const char *buf, 411 unsigned int sidetone) 412 { 413 struct usb_interface *usb_if = to_usb_interface(dev->parent); 414 struct usb_device *usb_dev = interface_to_usbdev(usb_if); 415 416 /* Packet format to set sidetone for wired headsets */ 417 __le16 sidetone_le = cpu_to_le16(sidetone); 418 419 return usb_control_msg_send(usb_dev, 0, 420 CORSAIR_VOID_USB_SIDETONE_REQUEST, 421 CORSAIR_VOID_USB_SIDETONE_REQUEST_TYPE, 422 CORSAIR_VOID_USB_SIDETONE_VALUE, 423 CORSAIR_VOID_USB_SIDETONE_INDEX, 424 &sidetone_le, 2, USB_CTRL_SET_TIMEOUT, 425 GFP_KERNEL); 426 } 427 428 static int corsair_void_set_sidetone_wireless(struct device *dev, 429 const char *buf, 430 unsigned char sidetone) 431 { 432 struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev); 433 struct hid_device *hid_dev = drvdata->hid_dev; 434 unsigned char *send_buf __free(kfree) = NULL; 435 436 send_buf = kmalloc(12, GFP_KERNEL); 437 if (!send_buf) 438 return -ENOMEM; 439 440 /* Packet format to set sidetone for wireless headsets */ 441 send_buf[0] = CORSAIR_VOID_SIDETONE_REQUEST_ID; 442 send_buf[1] = 0x0B; 443 send_buf[2] = 0x00; 444 send_buf[3] = 0xFF; 445 send_buf[4] = 0x04; 446 send_buf[5] = 0x0E; 447 send_buf[6] = 0xFF; 448 send_buf[7] = 0x05; 449 send_buf[8] = 0x01; 450 send_buf[9] = 0x04; 451 send_buf[10] = 0x00; 452 send_buf[11] = sidetone + 200; 453 454 return hid_hw_raw_request(hid_dev, CORSAIR_VOID_SIDETONE_REQUEST_ID, 455 send_buf, 12, HID_FEATURE_REPORT, 456 HID_REQ_SET_REPORT); 457 } 458 459 static ssize_t set_sidetone_store(struct device *dev, 460 struct device_attribute *attr, 461 const char *buf, size_t count) 462 { 463 struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev); 464 struct hid_device *hid_dev = drvdata->hid_dev; 465 unsigned int sidetone; 466 int ret; 467 468 if (!drvdata->connected) 469 return -ENODEV; 470 471 /* sidetone must be between 0 and drvdata->sidetone_max inclusive */ 472 if (kstrtouint(buf, 10, &sidetone) || sidetone > drvdata->sidetone_max) 473 return -EINVAL; 474 475 if (drvdata->is_wired) 476 ret = corsair_void_set_sidetone_wired(dev, buf, sidetone); 477 else 478 ret = corsair_void_set_sidetone_wireless(dev, buf, sidetone); 479 480 if (ret < 0) 481 hid_warn(hid_dev, "failed to send sidetone (reason: %d)", ret); 482 else 483 ret = count; 484 485 return ret; 486 } 487 488 static int corsair_void_request_status(struct hid_device *hid_dev, int id) 489 { 490 unsigned char *send_buf __free(kfree) = NULL; 491 492 send_buf = kmalloc(2, GFP_KERNEL); 493 if (!send_buf) 494 return -ENOMEM; 495 496 /* Packet format to request data item (status / firmware) refresh */ 497 send_buf[0] = CORSAIR_VOID_STATUS_REQUEST_ID; 498 send_buf[1] = id; 499 500 /* Send request for data refresh */ 501 return hid_hw_raw_request(hid_dev, CORSAIR_VOID_STATUS_REQUEST_ID, 502 send_buf, 2, HID_OUTPUT_REPORT, 503 HID_REQ_SET_REPORT); 504 } 505 506 /* 507 * Headset connect / disconnect handlers and work handlers 508 */ 509 510 static void corsair_void_status_work_handler(struct work_struct *work) 511 { 512 struct corsair_void_drvdata *drvdata; 513 struct delayed_work *delayed_work; 514 int battery_ret; 515 516 delayed_work = to_delayed_work(work); 517 drvdata = container_of(delayed_work, struct corsair_void_drvdata, 518 delayed_status_work); 519 520 battery_ret = corsair_void_request_status(drvdata->hid_dev, 521 CORSAIR_VOID_STATUS_REPORT_ID); 522 if (battery_ret < 0) { 523 hid_warn(drvdata->hid_dev, 524 "failed to request battery (reason: %d)", battery_ret); 525 } 526 } 527 528 static void corsair_void_firmware_work_handler(struct work_struct *work) 529 { 530 struct corsair_void_drvdata *drvdata; 531 struct delayed_work *delayed_work; 532 int firmware_ret; 533 534 delayed_work = to_delayed_work(work); 535 drvdata = container_of(delayed_work, struct corsair_void_drvdata, 536 delayed_firmware_work); 537 538 firmware_ret = corsair_void_request_status(drvdata->hid_dev, 539 CORSAIR_VOID_FIRMWARE_REPORT_ID); 540 if (firmware_ret < 0) { 541 hid_warn(drvdata->hid_dev, 542 "failed to request firmware (reason: %d)", firmware_ret); 543 } 544 545 } 546 547 static void corsair_void_add_battery(struct corsair_void_drvdata *drvdata) 548 { 549 struct power_supply_config psy_cfg = {}; 550 struct power_supply *new_supply; 551 552 if (drvdata->battery) 553 return; 554 555 psy_cfg.drv_data = drvdata; 556 new_supply = power_supply_register(drvdata->dev, 557 &drvdata->battery_desc, 558 &psy_cfg); 559 560 if (IS_ERR(new_supply)) { 561 hid_err(drvdata->hid_dev, 562 "failed to register battery '%s' (reason: %pe)\n", 563 drvdata->battery_desc.name, new_supply); 564 return; 565 } 566 567 if (power_supply_powers(new_supply, drvdata->dev)) { 568 power_supply_unregister(new_supply); 569 return; 570 } 571 572 drvdata->battery = new_supply; 573 } 574 575 static void corsair_void_battery_work_handler(struct work_struct *work) 576 { 577 struct corsair_void_drvdata *drvdata = container_of(work, 578 struct corsair_void_drvdata, battery_work); 579 580 bool add_battery = test_and_clear_bit(CORSAIR_VOID_ADD_BATTERY, 581 &drvdata->battery_work_flags); 582 bool remove_battery = test_and_clear_bit(CORSAIR_VOID_REMOVE_BATTERY, 583 &drvdata->battery_work_flags); 584 bool update_battery = test_and_clear_bit(CORSAIR_VOID_UPDATE_BATTERY, 585 &drvdata->battery_work_flags); 586 587 if (add_battery && !remove_battery) { 588 corsair_void_add_battery(drvdata); 589 } else if (remove_battery && !add_battery && drvdata->battery) { 590 power_supply_unregister(drvdata->battery); 591 drvdata->battery = NULL; 592 } 593 594 if (update_battery && drvdata->battery) 595 power_supply_changed(drvdata->battery); 596 597 } 598 599 static void corsair_void_headset_connected(struct corsair_void_drvdata *drvdata) 600 { 601 set_bit(CORSAIR_VOID_ADD_BATTERY, &drvdata->battery_work_flags); 602 schedule_work(&drvdata->battery_work); 603 schedule_delayed_work(&drvdata->delayed_firmware_work, 604 msecs_to_jiffies(100)); 605 } 606 607 static void corsair_void_headset_disconnected(struct corsair_void_drvdata *drvdata) 608 { 609 set_bit(CORSAIR_VOID_REMOVE_BATTERY, &drvdata->battery_work_flags); 610 schedule_work(&drvdata->battery_work); 611 612 corsair_void_set_unknown_wireless_data(drvdata); 613 corsair_void_set_unknown_batt(drvdata); 614 } 615 616 /* 617 * Driver setup, probing and HID event handling 618 */ 619 620 static DEVICE_ATTR_RO(fw_version_receiver); 621 static DEVICE_ATTR_RO(fw_version_headset); 622 static DEVICE_ATTR_RO(microphone_up); 623 static DEVICE_ATTR_RO(sidetone_max); 624 625 static DEVICE_ATTR_WO(send_alert); 626 static DEVICE_ATTR_WO(set_sidetone); 627 628 static struct attribute *corsair_void_attrs[] = { 629 &dev_attr_fw_version_receiver.attr, 630 &dev_attr_fw_version_headset.attr, 631 &dev_attr_microphone_up.attr, 632 &dev_attr_send_alert.attr, 633 &dev_attr_set_sidetone.attr, 634 &dev_attr_sidetone_max.attr, 635 NULL, 636 }; 637 638 static const struct attribute_group corsair_void_attr_group = { 639 .attrs = corsair_void_attrs, 640 }; 641 642 static int corsair_void_probe(struct hid_device *hid_dev, 643 const struct hid_device_id *hid_id) 644 { 645 int ret; 646 struct corsair_void_drvdata *drvdata; 647 char *name; 648 649 if (!hid_is_usb(hid_dev)) 650 return -EINVAL; 651 652 drvdata = devm_kzalloc(&hid_dev->dev, sizeof(*drvdata), 653 GFP_KERNEL); 654 if (!drvdata) 655 return -ENOMEM; 656 657 hid_set_drvdata(hid_dev, drvdata); 658 dev_set_drvdata(&hid_dev->dev, drvdata); 659 660 drvdata->dev = &hid_dev->dev; 661 drvdata->hid_dev = hid_dev; 662 drvdata->is_wired = hid_id->driver_data == CORSAIR_VOID_WIRED; 663 664 drvdata->sidetone_max = CORSAIR_VOID_SIDETONE_MAX_WIRELESS; 665 if (drvdata->is_wired) 666 drvdata->sidetone_max = CORSAIR_VOID_SIDETONE_MAX_WIRED; 667 668 /* Set initial values for no wireless headset attached */ 669 /* If a headset is attached, it'll be prompted later */ 670 corsair_void_set_unknown_wireless_data(drvdata); 671 corsair_void_set_unknown_batt(drvdata); 672 673 /* Receiver version won't be reset after init */ 674 /* Headset version already set via set_unknown_wireless_data */ 675 drvdata->fw_receiver_major = 0; 676 drvdata->fw_receiver_minor = 0; 677 678 ret = hid_parse(hid_dev); 679 if (ret) { 680 hid_err(hid_dev, "parse failed (reason: %d)\n", ret); 681 return ret; 682 } 683 684 name = devm_kasprintf(drvdata->dev, GFP_KERNEL, 685 "corsair-void-%d-battery", hid_dev->id); 686 if (!name) 687 return -ENOMEM; 688 689 drvdata->battery_desc.name = name; 690 drvdata->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY; 691 drvdata->battery_desc.properties = corsair_void_battery_props; 692 drvdata->battery_desc.num_properties = ARRAY_SIZE(corsair_void_battery_props); 693 drvdata->battery_desc.get_property = corsair_void_battery_get_property; 694 695 drvdata->battery = NULL; 696 INIT_WORK(&drvdata->battery_work, corsair_void_battery_work_handler); 697 698 ret = sysfs_create_group(&hid_dev->dev.kobj, &corsair_void_attr_group); 699 if (ret) 700 return ret; 701 702 /* Any failures after here will need to call hid_hw_stop */ 703 ret = hid_hw_start(hid_dev, HID_CONNECT_DEFAULT); 704 if (ret) { 705 hid_err(hid_dev, "hid_hw_start failed (reason: %d)\n", ret); 706 goto failed_after_sysfs; 707 } 708 709 /* Refresh battery data, in case wireless headset is already connected */ 710 INIT_DELAYED_WORK(&drvdata->delayed_status_work, 711 corsair_void_status_work_handler); 712 schedule_delayed_work(&drvdata->delayed_status_work, 713 msecs_to_jiffies(100)); 714 715 /* Refresh firmware versions */ 716 INIT_DELAYED_WORK(&drvdata->delayed_firmware_work, 717 corsair_void_firmware_work_handler); 718 schedule_delayed_work(&drvdata->delayed_firmware_work, 719 msecs_to_jiffies(100)); 720 721 return 0; 722 723 failed_after_sysfs: 724 sysfs_remove_group(&hid_dev->dev.kobj, &corsair_void_attr_group); 725 return ret; 726 } 727 728 static void corsair_void_remove(struct hid_device *hid_dev) 729 { 730 struct corsair_void_drvdata *drvdata = hid_get_drvdata(hid_dev); 731 732 hid_hw_stop(hid_dev); 733 cancel_work_sync(&drvdata->battery_work); 734 if (drvdata->battery) 735 power_supply_unregister(drvdata->battery); 736 737 cancel_delayed_work_sync(&drvdata->delayed_status_work); 738 cancel_delayed_work_sync(&drvdata->delayed_firmware_work); 739 sysfs_remove_group(&hid_dev->dev.kobj, &corsair_void_attr_group); 740 } 741 742 static int corsair_void_raw_event(struct hid_device *hid_dev, 743 struct hid_report *hid_report, 744 u8 *data, int size) 745 { 746 struct corsair_void_drvdata *drvdata = hid_get_drvdata(hid_dev); 747 bool was_connected = drvdata->connected; 748 749 /* Description of packets are documented at the top of this file */ 750 if (hid_report->id == CORSAIR_VOID_STATUS_REPORT_ID) { 751 if (size < CORSAIR_VOID_STATUS_REPORT_SIZE) { 752 hid_warn_ratelimited(hid_dev, 753 "unexpected status report of size %d", 754 size); 755 return 1; 756 } 757 758 drvdata->mic_up = FIELD_GET(CORSAIR_VOID_MIC_MASK, data[2]); 759 drvdata->connected = (data[3] == CORSAIR_VOID_WIRELESS_CONNECTED) || 760 drvdata->is_wired; 761 762 corsair_void_process_receiver(drvdata, 763 FIELD_GET(CORSAIR_VOID_CAPACITY_MASK, data[2]), 764 data[3], data[4]); 765 } else if (hid_report->id == CORSAIR_VOID_FIRMWARE_REPORT_ID) { 766 if (size < CORSAIR_VOID_FIRMWARE_REPORT_SIZE) { 767 hid_warn_ratelimited(hid_dev, 768 "unexpected firmware report of size %d", 769 size); 770 return 1; 771 } 772 773 drvdata->fw_receiver_major = data[1]; 774 drvdata->fw_receiver_minor = data[2]; 775 drvdata->fw_headset_major = data[3]; 776 drvdata->fw_headset_minor = data[4]; 777 } 778 779 /* Handle wireless headset connect / disconnect */ 780 if ((was_connected != drvdata->connected) && !drvdata->is_wired) { 781 if (drvdata->connected) 782 corsair_void_headset_connected(drvdata); 783 else 784 corsair_void_headset_disconnected(drvdata); 785 } 786 787 return 0; 788 } 789 790 static const struct hid_device_id corsair_void_devices[] = { 791 /* Corsair Void Wireless */ 792 CORSAIR_VOID_WIRELESS_DEVICE(0x0a0c), 793 CORSAIR_VOID_WIRELESS_DEVICE(0x0a2b), 794 CORSAIR_VOID_WIRELESS_DEVICE(0x1b23), 795 CORSAIR_VOID_WIRELESS_DEVICE(0x1b25), 796 CORSAIR_VOID_WIRELESS_DEVICE(0x1b27), 797 798 /* Corsair Void USB */ 799 CORSAIR_VOID_WIRED_DEVICE(0x0a0f), 800 CORSAIR_VOID_WIRED_DEVICE(0x1b1c), 801 CORSAIR_VOID_WIRED_DEVICE(0x1b29), 802 CORSAIR_VOID_WIRED_DEVICE(0x1b2a), 803 804 /* Corsair Void Surround */ 805 CORSAIR_VOID_WIRED_DEVICE(0x0a30), 806 CORSAIR_VOID_WIRED_DEVICE(0x0a31), 807 808 /* Corsair Void Pro Wireless */ 809 CORSAIR_VOID_WIRELESS_DEVICE(0x0a14), 810 CORSAIR_VOID_WIRELESS_DEVICE(0x0a16), 811 CORSAIR_VOID_WIRELESS_DEVICE(0x0a1a), 812 813 /* Corsair Void Pro USB */ 814 CORSAIR_VOID_WIRED_DEVICE(0x0a17), 815 CORSAIR_VOID_WIRED_DEVICE(0x0a1d), 816 817 /* Corsair Void Pro Surround */ 818 CORSAIR_VOID_WIRED_DEVICE(0x0a18), 819 CORSAIR_VOID_WIRED_DEVICE(0x0a1e), 820 CORSAIR_VOID_WIRED_DEVICE(0x0a1f), 821 822 /* Corsair Void Elite Wireless */ 823 CORSAIR_VOID_WIRELESS_DEVICE(0x0a51), 824 CORSAIR_VOID_WIRELESS_DEVICE(0x0a55), 825 CORSAIR_VOID_WIRELESS_DEVICE(0x0a75), 826 827 /* Corsair Void Elite USB */ 828 CORSAIR_VOID_WIRED_DEVICE(0x0a52), 829 CORSAIR_VOID_WIRED_DEVICE(0x0a56), 830 831 /* Corsair Void Elite Surround */ 832 CORSAIR_VOID_WIRED_DEVICE(0x0a53), 833 CORSAIR_VOID_WIRED_DEVICE(0x0a57), 834 835 {} 836 }; 837 838 MODULE_DEVICE_TABLE(hid, corsair_void_devices); 839 840 static struct hid_driver corsair_void_driver = { 841 .name = "hid-corsair-void", 842 .id_table = corsair_void_devices, 843 .probe = corsair_void_probe, 844 .remove = corsair_void_remove, 845 .raw_event = corsair_void_raw_event, 846 }; 847 848 module_hid_driver(corsair_void_driver); 849 850 MODULE_LICENSE("GPL"); 851 MODULE_AUTHOR("Stuart Hayhurst <stuart.a.hayhurst@gmail.com>"); 852 MODULE_DESCRIPTION("HID driver for Corsair Void headsets"); 853