HeadsetControl icon indicating copy to clipboard operation
HeadsetControl copied to clipboard

Device Request: Corsair HS80

Open bnjns opened this issue 3 years ago • 32 comments

First off - love this product!

I've tried to add the Corsair HS80 (Product ID 0x0a6b), and while it recognises the device it doesn't appear to be able to do anything:

./headsetcontrol -s 70
Found Corsair Headset Device!

Failed to set sidetone. Error: -1: hid_error is not implemented yet

I'm more than happy to try and take a look at this, but I'm not super familiar with C or how this project works so would need some pointers (it looks like the hid_error is not implemented yet is a hidapi thing?)

bnjns avatar Oct 18 '21 10:10 bnjns

it looks like the hid_error is not implemented yet is a hidapi thing?

Yep. With some implementations (apparently the MacOS Implementation: https://github.com/libusb/hidapi/issues/310) it is simply not implemented. On Linux it is implemented, if you see on Linux this error message something is indeed off.

I think you need to use WireShark to get more details about the protocol for the HS80 - maybe it is different: https://github.com/Sapd/HeadsetControl/wiki/Development

Sapd avatar Oct 24 '21 11:10 Sapd

it looks like the hid_error is not implemented yet is a hidapi thing?

Yep. With some implementations (apparently the MacOS Implementation: libusb/hidapi#310) it is simply not implemented. On Linux it is implemented, if you see on Linux this error message something is indeed off.

I think you need to use WireShark to get more details about the protocol for the HS80 - maybe it is different: https://github.com/Sapd/HeadsetControl/wiki/Development

As you said in linux it is implemented, so the Corsair HS80 Wireless should work on Ubuntu 20.04?

roland-burke avatar Nov 11 '21 15:11 roland-burke

As you said in linux it is implemented, so the Corsair HS80 Wireless should work on Ubuntu 20.04?

That's just hid_error and not the headset itself. I'm hoping to take a look at the protocol using WireShark to see if I can get this implemented, but struggling to find the time at the moment.

bnjns avatar Nov 11 '21 15:11 bnjns

@Sapd I finally managed to get Windows booted, and I must be missing something as it looks like the HS80 is very different? I am not very familiar with USB/HID but going through the spec and some guides is leading me to believe these aren't the right captures as a bRequest of 1 should be GET_REPORT and not SET_REPORT? Plus, the values don't seem to make much sense.

Sidetone -> 0 wireshark_hs80_sidetone_0 Sidetone -> Full wireshark_hs80_sidetone_100

They're the only things that appear in Wireshark when changing the sidetone - any tips?

bnjns avatar Nov 12 '21 23:11 bnjns

Im not 100% sure why sometimes relevant packets are not visible via WireShark.

Can you also try it with the USBLyzer trial?

Sapd avatar Nov 13 '21 11:11 Sapd

Looks like I'm not having much luck. All I get in USBLyzer is a constant stream of URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER captures. And capturing the CORSAIR HS80 RGB Wireless Gaming Receiver gives me the same as WireShark.

usblyzer

bnjns avatar Nov 13 '21 17:11 bnjns

I made some notes, regarding the data in your first screenshot:

bmRequestType     0x21    // HID, Recipent is interface
bRequest                0x01    // CLEAR_FEATURE
wValue                    0x0200 // This defines the Feature Selector
wIndex                    0x0600 // Usually describes the interface, the request is meant to go to
wLength                  0x02    // Number of bytes to be transfered

Funnily, when using CLEAR_FEATURE, according to the spec, wLength must be 0. Also when looking into the old implementation of G430 https://github.com/Sapd/HeadsetControl/blob/master/src/devices/logitech_g430.c , it looked very very similar to this packet.

So it is probably the packet to the Sidetone. The question remains however, how to "convert" it to a HID command

Sapd avatar Nov 13 '21 21:11 Sapd

Ive read a bit in the HID specifications, and translated the data to HID:

bmRequestType     0x21   0b00100001   // This can only be valid for SET_REPORT
bRequest                0x01    // This is not really valid, as it can only be with GET_REPORT
wValue                    0x0200 // Report Type (Output) and ReportID which is 0.
wIndex                    0x0600 // interface in hid
wLength                  0x02    // Number of bytes to be transfered

So basically it does not make much sense, but its somehow definitely HID. But as it does not make much sense, WireShark does not parse it.

I would try both options (leading 0, for reportID 0), interface in decimal is 1536: ./headsetcontrol --dev -- --device 0x1b1c:0x0a6b --interface 1536 --send "0x00 0x00 0xd6" ./headsetcontrol --dev -- --device 0x1b1c:0x0a6b --interface 1536 --send-report "0x00 0x00 0xd6"

If this does not work, you could also try GET_REPORT with bRequest 0x01 which would be this call: hid_get_input_report E.g. (only in code)

/// in the init function
device_void.capability_details[CAP_SIDETONE]           = (struct capability_detail) { .interface = 1536 };```

/// then when sending
unsigned char data[3] = { 0x0, 0x00, 0xd6 };
hid_get_input_report(device_handle, data, 3);

Sapd avatar Nov 13 '21 22:11 Sapd

Unfortunately both --send and --send-feature error with Device not found (both when using --dev and in code). Using hid_get_input_report doesn't error out (and returns a positive number, which I believe means the request was successful) but doesn't do anything 😞

bnjns avatar Nov 15 '21 09:11 bnjns

Device not found means that the interface or vendor/device id is not correct. Maybe try to list all interfaces using ./headsetcontrol --dev -- --list and then work through them

Sapd avatar Nov 15 '21 09:11 Sapd

Yeah, with that there are 2 interfaces: 3 and 4, but both just time out when I try to use any of the above 😕 I'll try to do some deeper digging, but I may not have time until this weekend.

bnjns avatar Nov 15 '21 09:11 bnjns

Yep it is probably a more difficult topic :(

Im also not quite sure how such a capture can even exist, because like I said, it specifies that it uses HID, however the data is outside of its specifications. So it can be these reasons:

  1. Corsair is using HID normally and Windows does some weird stuff when transferring data. That would mean that it is possible to access it with some different - normal - HID request
  2. The Capture is wrong: Ive read that capturing on Windows is difficult and can lead to weird results. Some sources suggest, to use Windows in a VM, but then not to capture in Windows, but in a Linux host with Wireshark. This uses then the capturing interface of the Linux kernel which is more reliable: https://wiki.wireshark.org/CaptureSetup/USB#Windows
  3. Corsair or the chip they use, really send a custom - weird protocol - outside of the HID specifications. This would be bad for us, but also bad for Corsair, as this way it is not possible (at least in a simple way) to support the device on Mac (direct USB protocol on HID not allowed) and potentially on Linux (it allows USB, but is not the best way)

Sapd avatar Nov 15 '21 09:11 Sapd

I wouldn't be surprised if Corsair was doing something weird, although v4 of iCue for macOS does support the HS80 so hopefully not 🤞 I'll give the "software in VM, capture in linux" approach a try.

bnjns avatar Nov 15 '21 10:11 bnjns

It may not be Corsair itself, but a chip they use. Because the Logitech G430 capture looks like 90% similar, I guess that they may both have purchased the same hardware chip. Possibly also the reason why the protocol of the HS80 differs to the VOID versions (why should they invent a new protocol, when both do the same job?; they may have just decided for a different vendor of their usb chip or software)

I'm curious what the results will be, would be very interesting in any event also for future cases 🚀. But that a Mac version exists really gives hope, as I don't think that they would use a kernel-mode driver.

Sapd avatar Nov 15 '21 10:11 Sapd

[...] Some sources suggest, to use Windows in a VM, but then not to capture in Windows, but in a Linux host with Wireshark. This uses then the capturing interface of the Linux kernel which is more reliable [...]

As I am interested in HS80 support as well, I tried this to see how the packets look like when captured outside a VM.

Host: Ubuntu 20.04.03 Guest: Windows 10.0.19044 VBox: v6.1.26

I do not know much about URB frames, but currently I see the following:

  • I capture 66 bytes instead of 38 bytes.
  • [0-7] (URB id) vary between each packet (How are these ids generated?)
  • [8-15] seem to be endpoints and configuration flags that are fixed, at least for a certain HW configuration
  • [16-27] (urb_ts and urb_ts_us) seems like a timestamp
  • [40-47] might encode what value/option is modified, as it is different when changing other options, e.g.:
    • Sidetone: 21 01 00 02 00 06 02 00
    • Mic Volume: 21 01 01 02 00 03 02 00
  • [48-63] seem unused, or at least I haven't seen their use, yet
  • [64-65] is the data fragment and I caputre the same as @bnjns: sidetone -> full (0004) and sidetone -> 0 (00d6)

sidetone = 0: sidetone_0 sidetone = full: sidetone_full

If I find the time, I will try to look into how URB frames are structured and if this helps us to understand the HS80 protocol. If you know any good resources about URB, I would appreciate if you share them with me.

fwege avatar Nov 23 '21 22:11 fwege

Thanks @fwege. I've sadly not had much time over the past couple of weeks to look any further, so appreciate the help 🙂

bnjns avatar Nov 24 '21 08:11 bnjns

If I find the time, I will try to look into how URB frames are structured and if this helps us to understand the HS80 protocol. If you know any good resources about URB, I would appreciate if you share them with me.

URB simply consists of all relevant information for executing USB commands.

Thats why, only this information you listed is of interest:

  • [40-47] might encode what value/option is modified, as it is different when changing other options, e.g.:

    • Sidetone: 21 01 00 02 00 06 02 00
    • Mic Volume: 21 01 01 02 00 03 02 00
  • [48-63] seem unused, or at least I haven't seen their use, yet

  • [64-65] is the data fragment and I caputre the same as @bnjns: sidetone -> full (0004) and sidetone -> 0 (00d6)

The data you got, is exactly the same as @bnjns capture

I described it above:

bmRequestType     0x21    // HID, Recipent is interface
bRequest                0x01    // CLEAR_FEATURE
wValue                    0x0200 // This defines the Feature Selector
wIndex                    0x0600 // Usually describes the interface, the request is meant to go to
wLength                  0x02    // Number of bytes to be transfered

or, when treating it as HID:

bmRequestType     0x21   0b00100001   // This can only be valid for SET_REPORT
bRequest                0x01    // This is not really valid, as it can only be with GET_REPORT
wValue                    0x0200 // Report Type (Output) and ReportID which is 0.
wIndex                    0x0600 // interface in hid
wLength                  0x02    // Number of bytes to be transfered

For HID the relevant documentation is here: https://www.usb.org/sites/default/files/hid1_11.pdf Look at page 52 Note that HID simply uses USB and standardises some things. For USB itself, you can find an overview here: https://www.beyondlogic.org/usbnutshell/usb6.shtml

As both your captures are the same, We probably have to go a different way here. (Except if you have a Mac, then another capture would be useful).

I would suggest that you generate a report of the so-called HID descriptors. On Linux (while the headset is plugged in) use (and replaced vendor/productid):

sudo usbhid-dump -d THEVENDORID:PRODUCTID -e all -i 255

I think the relevant package is called usbutils e.g. apt-get install usbutils

Copy-paste the output here, you can additionally also copy paste it here: https://eleccelerator.com/usbdescreqparser/ and click on "USB HID Report Descriptor" and then also paste it here. It may give more information about the problem together with the captures above.

Sapd avatar Nov 24 '21 09:11 Sapd

I've got a Mac that I can also try with :+1:

bnjns avatar Nov 24 '21 10:11 bnjns

Thats very good. Because (in my opinion) the corsair mac driver software is forced to correctly use HID on mac. Because its very unlikely that they have written a kernel driver. So we may get the correct commands for HID directly without looking at the reports.

Note that for capturing on Mac, you may have to disable SIP temporarily: https://wiki.wireshark.org/CaptureSetup/USB#macOS

Sapd avatar Nov 24 '21 10:11 Sapd

Hi, I found the issue here because i also wanted to use the HS80 I'm using manjaro arch so maybe it's not the same. Hope this still helps:

btw I build it with the productID but don't have the exact problems

./headsetcontrol -b Found Corsair Headset Device! Battery: Unavailable Success!

./headsetcontrol -l 0 Found Corsair Headset Device! Success! (does not work just says success)

Raw data
003:003:004:DESCRIPTOR         1637753481.822729
 05 01 09 02 A1 01 09 01 A1 00 85 22 05 09 19 01
 29 20 15 00 25 01 95 20 75 01 81 02 75 10 95 02
 05 01 09 30 09 31 16 01 80 26 FF 7F 81 06 75 08
 95 01 05 01 09 38 15 81 25 7F 81 06 75 08 95 05
 06 00 FF 09 F1 15 00 26 FF 00 81 00 C0 C0

003:003:003:DESCRIPTOR         1637753481.826707
 05 01 09 06 A1 01 85 11 05 08 95 03 75 01 19 01
 29 03 15 00 25 01 91 02 95 05 91 03 05 07 75 01
 19 E0 29 E7 95 08 81 02 19 00 29 67 95 68 81 02
 19 87 29 8E 95 08 81 02 C0 05 0C 09 01 A1 01 85
 0F 95 01 75 10 15 00 26 FF 03 19 00 2A FF 03 81
 00 C0 05 0C 09 01 A1 01 85 0E 15 00 25 01 09 E9
 09 EA 75 01 95 02 81 02 09 E2 75 01 95 01 81 02
 75 01 95 05 81 03 C0 06 42 FF 09 01 A1 01 85 01
 15 00 26 FF 00 75 08 95 3F 09 01 81 02 85 02 95
 3F 09 01 91 02 C0 06 42 FF 09 02 A1 01 85 03 15
 00 26 FF 00 75 08 95 3F 09 01 81 02 C0 06 58 FF
 09 01 A1 01 85 58 09 01 15 00 26 FF 00 95 3F 75
 08 81 02 85 58 09 01 15 00 26 FF 00 95 3F 75 08
 91 02 C0
Parsed, Interface 4
0x03, 0x03, 0x04, 0x05, 0x01,  // Unknown (bTag: 0x00, bType: 0x00)
0x09, 0x02,        // Usage (0x02)
0xA1, 0x01,        // Collection (Application)
0x09, 0x01,        //   Usage (0x01)
0xA1, 0x00,        //   Collection (Physical)
0x85, 0x22,        //     Report ID (34)
0x05, 0x09,        //     Usage Page (Button)
0x19, 0x01,        //     Usage Minimum (0x01)
0x29, 0x20,        //     Usage Maximum (0x20)
0x15, 0x00,        //     Logical Minimum (0)
0x25, 0x01,        //     Logical Maximum (1)
0x95, 0x20,        //     Report Count (32)
0x75, 0x01,        //     Report Size (1)
0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x10,        //     Report Size (16)
0x95, 0x02,        //     Report Count (2)
0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x30,        //     Usage (X)
0x09, 0x31,        //     Usage (Y)
0x16, 0x01, 0x80,  //     Logical Minimum (-32767)
0x26, 0xFF, 0x7F,  //     Logical Maximum (32767)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x08,        //     Report Size (8)
0x95, 0x01,        //     Report Count (1)
0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x38,        //     Usage (Wheel)
0x15, 0x81,        //     Logical Minimum (-127)
0x25, 0x7F,        //     Logical Maximum (127)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x08,        //     Report Size (8)
0x95, 0x05,        //     Report Count (5)
0x06, 0x00, 0xFF,  //     Usage Page (Vendor Defined 0xFF00)
0x09, 0xF1,        //     Usage (0xF1)
0x15, 0x00,        //     Logical Minimum (0)
0x26, 0xFF, 0x00,  //     Logical Maximum (255)
0x81, 0x00,        //     Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              //   End Collection
0xC0,              // End Collection

// 81 bytes
Parsed, Interface 3

0x03, 0x03, 0x03, 0x05, 0x01,  // Unknown (bTag: 0x00, bType: 0x00)
0x09, 0x06,        // Usage (0x06)
0xA1, 0x01,        // Collection (Application)
0x85, 0x11,        //   Report ID (17)
0x05, 0x08,        //   Usage Page (LEDs)
0x95, 0x03,        //   Report Count (3)
0x75, 0x01,        //   Report Size (1)
0x19, 0x01,        //   Usage Minimum (Num Lock)
0x29, 0x03,        //   Usage Maximum (Scroll Lock)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x05,        //   Report Count (5)
0x91, 0x03,        //   Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
0x75, 0x01,        //   Report Size (1)
0x19, 0xE0,        //   Usage Minimum (0xE0)
0x29, 0xE7,        //   Usage Maximum (0xE7)
0x95, 0x08,        //   Report Count (8)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x19, 0x00,        //   Usage Minimum (0x00)
0x29, 0x67,        //   Usage Maximum (0x67)
0x95, 0x68,        //   Report Count (104)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x19, 0x87,        //   Usage Minimum (0x87)
0x29, 0x8E,        //   Usage Maximum (0x8E)
0x95, 0x08,        //   Report Count (8)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              // End Collection
0x05, 0x0C,        // Usage Page (Consumer)
0x09, 0x01,        // Usage (Consumer Control)
0xA1, 0x01,        // Collection (Application)
0x85, 0x0F,        //   Report ID (15)
0x95, 0x01,        //   Report Count (1)
0x75, 0x10,        //   Report Size (16)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x03,  //   Logical Maximum (1023)
0x19, 0x00,        //   Usage Minimum (Unassigned)
0x2A, 0xFF, 0x03,  //   Usage Maximum (0x03FF)
0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              // End Collection
0x05, 0x0C,        // Usage Page (Consumer)
0x09, 0x01,        // Usage (Consumer Control)
0xA1, 0x01,        // Collection (Application)
0x85, 0x0E,        //   Report ID (14)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x09, 0xE9,        //   Usage (Volume Increment)
0x09, 0xEA,        //   Usage (Volume Decrement)
0x75, 0x01,        //   Report Size (1)
0x95, 0x02,        //   Report Count (2)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0xE2,        //   Usage (Mute)
0x75, 0x01,        //   Report Size (1)
0x95, 0x01,        //   Report Count (1)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x01,        //   Report Size (1)
0x95, 0x05,        //   Report Count (5)
0x81, 0x03,        //   Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              // End Collection
0x06, 0x42, 0xFF,  // Usage Page (Vendor Defined 0xFF42)
0x09, 0x01,        // Usage (0x01)
0xA1, 0x01,        // Collection (Application)
0x85, 0x01,        //   Report ID (1)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x75, 0x08,        //   Report Size (8)
0x95, 0x3F,        //   Report Count (63)
0x09, 0x01,        //   Usage (0x01)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x85, 0x02,        //   Report ID (2)
0x95, 0x3F,        //   Report Count (63)
0x09, 0x01,        //   Usage (0x01)
0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0,              // End Collection
0x06, 0x42, 0xFF,  // Usage Page (Vendor Defined 0xFF42)
0x09, 0x02,        // Usage (0x02)
0xA1, 0x01,        // Collection (Application)
0x85, 0x03,        //   Report ID (3)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x75, 0x08,        //   Report Size (8)
0x95, 0x3F,        //   Report Count (63)
0x09, 0x01,        //   Usage (0x01)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              // End Collection
0x06, 0x58, 0xFF,  // Usage Page (Vendor Defined 0xFF58)
0x09, 0x01,        // Usage (0x01)
0xA1, 0x01,        // Collection (Application)
0x85, 0x58,        //   Report ID (88)
0x09, 0x01,        //   Usage (0x01)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x95, 0x3F,        //   Report Count (63)
0x75, 0x08,        //   Report Size (8)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x85, 0x58,        //   Report ID (88)
0x09, 0x01,        //   Usage (0x01)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x95, 0x3F,        //   Report Count (63)
0x75, 0x08,        //   Report Size (8)
0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0,              // End Collection

// 214 bytes

Roadis avatar Nov 24 '21 11:11 Roadis

@Roadis Interesting, so it sees 2 HID interfaces. Can you also provide the output of lsusb -d VENDORID:PRODUCTID -v ?

Sapd avatar Nov 24 '21 13:11 Sapd

lsusb -d 1b1c:0a6b -v
bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x1b1c Corsair
  idProduct          0x0a6b 
  bcdDevice            0.00
  iManufacturer           1 Corsair
  iProduct                2 CORSAIR HS80 RGB Wireless Gaming Receiver
  iSerial                 3 16af3bee000100da
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x01a3
    bNumInterfaces          5
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface              0 
      AudioControl Interface Descriptor:
        bLength                10
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x005d
        bInCollection           2
        baInterfaceNr(0)        1
        baInterfaceNr(1)        2
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             1
        wTerminalType      0x0402 Headset
        bAssocTerminal          0
        bNrChannels             1
        wChannelConfig     0x0004
          Center Front (C)
        iChannelNames           0 
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 3
        bSourceID               1
        bControlSize            1
        bmaControls(0)       0x01
          Mute Control
        bmaControls(1)       0x02
          Volume Control
        iFeature                0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID             4
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bSourceID               3
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             5
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bNrChannels             2
        wChannelConfig     0x0003
          Left Front (L)
          Right Front (R)
        iChannelNames           0 
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                10
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 8
        bSourceID               7
        bControlSize            1
        bmaControls(0)       0x01
          Mute Control
        bmaControls(1)       0x02
          Volume Control
        bmaControls(2)       0x02
          Volume Control
        iFeature                0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 6
        bSourceID               1
        bControlSize            1
        bmaControls(0)       0x03
          Mute Control
          Volume Control
        bmaControls(1)       0x00
        iFeature                0 
      AudioControl Interface Descriptor:
        bLength                13
        bDescriptorType        36
        bDescriptorSubtype      4 (MIXER_UNIT)
        bUnitID                 7
        bNrInPins               2
        baSourceID(0)           5
        baSourceID(1)           6
        bNrChannels             2
        wChannelConfig     0x0003
          Left Front (L)
          Right Front (R)
        iChannelNames           0 
        bmControls(0)        0x00
        iMixer                  0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID             9
        wTerminalType      0x0402 Headset
        bAssocTerminal          0
        bSourceID               8
        iTerminal               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           4
        bDelay                  1 frames
        wFormatTag         0x0001 PCM
      AudioStreaming Interface Descriptor:
        bLength                32
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             1
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            8 Discrete
        tSamFreq[ 0]         8000
        tSamFreq[ 1]        11025
        tSamFreq[ 2]        16000
        tSamFreq[ 3]        22050
        tSamFreq[ 4]        24000
        tSamFreq[ 5]        32000
        tSamFreq[ 6]        44100
        tSamFreq[ 7]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes           13
          Transfer Type            Isochronous
          Synch Type               Synchronous
          Usage Type               Data
        wMaxPacketSize     0x0062  1x 98 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        AudioStreaming Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         1 Milliseconds
          wLockDelay         0x0001
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       2
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           4
        bDelay                  1 frames
        wFormatTag         0x0001 PCM
      AudioStreaming Interface Descriptor:
        bLength                32
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             1
        bSubframeSize           3
        bBitResolution         24
        bSamFreqType            8 Discrete
        tSamFreq[ 0]         8000
        tSamFreq[ 1]        11025
        tSamFreq[ 2]        16000
        tSamFreq[ 3]        22050
        tSamFreq[ 4]        24000
        tSamFreq[ 5]        32000
        tSamFreq[ 6]        44100
        tSamFreq[ 7]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes           13
          Transfer Type            Isochronous
          Synch Type               Synchronous
          Usage Type               Data
        wMaxPacketSize     0x0093  1x 147 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        AudioStreaming Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         1 Milliseconds
          wLockDelay         0x0001
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           5
        bDelay                  1 frames
        wFormatTag         0x0001 PCM
      AudioStreaming Interface Descriptor:
        bLength                17
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             2
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            3 Discrete
        tSamFreq[ 0]        32000
        tSamFreq[ 1]        44100
        tSamFreq[ 2]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes           13
          Transfer Type            Isochronous
          Synch Type               Synchronous
          Usage Type               Data
        wMaxPacketSize     0x00c4  1x 196 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        AudioStreaming Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         1 Milliseconds
          wLockDelay         0x0001
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       2
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           5
        bDelay                  1 frames
        wFormatTag         0x0001 PCM
      AudioStreaming Interface Descriptor:
        bLength                17
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             2
        bSubframeSize           3
        bBitResolution         24
        bSamFreqType            3 Discrete
        tSamFreq[ 0]        32000
        tSamFreq[ 1]        44100
        tSamFreq[ 2]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes           13
          Transfer Type            Isochronous
          Synch Type               Synchronous
          Usage Type               Data
        wMaxPacketSize     0x0126  1x 294 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        AudioStreaming Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         1 Milliseconds
          wLockDelay         0x0001
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     211
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        4
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      78
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
Device Status:     0x0000
  (Bus Powered)

Roadis avatar Nov 24 '21 13:11 Roadis

image

Is it possible, that you are able to control Sidetone from alsamixer in Linux?

Because I noticed now, after a lot of googeling, that the packets @bnjs found for Mic and Sidetone, are exactly the same as for the AudioControl specification. This could be a problem, because then the software is indeed not controlling it via HID directly, but just says to the OS, to adjust the volume of a channel (and sidetone is also a channel)

Sapd avatar Nov 24 '21 15:11 Sapd

Is it possible, that you are able to control Sidetone from alsamixer in Linux?

Yeah, that seems to work! Although the naming of the channels is a bit confusing: The sidetone channel ist called Headset while the actual audio output channel is called Headset 1, at least in my case.

Sidetone turned off via alsamixer alsamixer_sidetone

To be honest: I thought I already tried that at the beginning before considering using your tool and it didn't work... Either I was just confused by the naming or, which is more unlikely, it is related to the firmware update of the headset and the USB dongle I did via iCUE on Windows.

fwege avatar Nov 24 '21 15:11 fwege

Is it possible, that you are able to control Sidetone from alsamixer in Linux?

Yeah, that seems to work! Although the naming of the channels is a bit confusing: The sidetone channel ist called Headset while the actual audio output channel is called Headset 1, at least in my case.

Ah that explains everything :D Also explains why the packets looked so weird (as they are actually AudioControl packets and not plain HID).

That basically means:

  • Sidetone cannot be controlled from HeadsetControl, but from Alsa
    • If there is demand, I may try to link Alsa for Linux, CoreAudio for Windows and Apples CoreAudio for Mac. However it is not trivial at all. However other headsets could need that too.
  • Battery, LEDs and co, still can be controlled from HeadsetControl (by doing further captures)

I will also adapt the Readme this week to give hint for Corsair Virtuso/HS devices

Sapd avatar Nov 24 '21 16:11 Sapd

Ah, that's super frustrating but at least alsa works 🤷

I can continue to take a look at battery etc (unless anyone else is keen to pick up from me).

bnjns avatar Nov 24 '21 16:11 bnjns

Although the "Headset 1" only affects the headset volume levels, the "Headset" affects both the sidetone and the volume levels, so muting it through Alsa will result with no audio at all, setting it at 0 and handling the volume through "Headset 1" will result on good audio and a slightly present sidetone. It seems for now that there's no way to disable/change the sidetone without affecting the overall volume of the headset.

frandmb avatar Dec 07 '21 15:12 frandmb

Researching this issue, I found a simple solution. If you enter "alsamixer" into the terminal it opens an application which you can control the sound levels. Through this I found that corsair uses a extra audio input as its sidetone. If you turn that down to 0 it should work. Steps => open alsamixer | Click F6 | Turn "Headset" to 0. Works with Corsair Void Pro, Ubuntu 20.04 LTS. image

waylenwasywas avatar Jan 18 '22 04:01 waylenwasywas

Hey all, did anyone manage to get HeadsetControl working for the HS80? At least for the ability to view my battery?

Leah-UK avatar Mar 24 '22 19:03 Leah-UK

Might be necro-bumping here, apologies, but for me, I have a Corsair HS80 Wireless RGB and it currently is not working, returning "No supported headset found". Not sure how to fix it.

imskyyc avatar Aug 24 '22 04:08 imskyyc