HeadsetControl
HeadsetControl copied to clipboard
Device Request: Corsair HS80
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?)
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
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?
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.
@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
Sidetone -> Full
They're the only things that appear in Wireshark when changing the sidetone - any tips?
Im not 100% sure why sometimes relevant packets are not visible via WireShark.
Can you also try it with the USBLyzer trial?
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.
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
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);
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 😞
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
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.
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:
- 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
- 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
- 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)
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.
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.
[...] 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
andurb_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
- Sidetone:
- [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 = 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.
Thanks @fwege. I've sadly not had much time over the past couple of weeks to look any further, so appreciate the help 🙂
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.
I've got a Mac that I can also try with :+1:
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
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 Interesting, so it sees 2 HID interfaces. Can you also provide the output of lsusb -d VENDORID:PRODUCTID -v
?
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)
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)
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
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.
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 calledHeadset 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
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).
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.
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.
Hey all, did anyone manage to get HeadsetControl working for the HS80? At least for the ability to view my battery?
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.