This report may only be relevant for Logitech headset devices and is certainly not relevant for USB in general but there doesn't seem to be a better component to use. The HID++ feature ADC_MEASUREMENT=0x1F20 provides battery information for some Logitech devices, perhaps only a few devices. I have a report of this feature on a Logitech PRO X Wireless Gaming Headset, as shown by the following output from Solaar (https://github.com/pwr-Solaar/Solaar). So this information might be useful for kernel-level control and reporting on headset devices. ``` Solaar version 1.1.4 1: Logitech PRO X Wireless Gaming Headset Device path : /dev/hidraw2 USB id : 046d:0ABA Codename : PRO Headset Kind : headset Protocol : HID++ 4.2 Serial number: Model ID: 000000000ABA Unit ID: FFFFFFFF Firmware: U1 12.01.B0203 Supports 6 HID++ 2.0 features: 0: ROOT {0000} 1: FEATURE SET {0001} 2: DEVICE FW VERSION {0003} Firmware: Firmware U1 12.01.B0203 0ABA Unit ID: FFFFFFFF Model ID: 000000000ABA Transport IDs: {'btid': '0000', 'btleid': '0000'} 3: DEVICE NAME {0005} Name: PRO X Wireless Gaming Headset Kind: None 4: EQUALIZER {8310} 5: SIDETONE {8300} 6: ADC MEASUREMENT {1F20} ``` I have documentation for the feature but I can't distribute it. Here is the code in Solaar that handles the feature. The mapping from levels to remaining capacity is not based on the battery in the device so a good implementation should get the actual information from Logitech. ``` ADC_MEASUREMENT=0x1F20, # voltage to remaining charge from Logitech (for a different battery) battery_voltage_remaining = ( (4186, 100), (4067, 90), (3989, 80), (3922, 70), (3859, 60), (3811, 50), (3778, 40), (3751, 30), (3717, 20), (3671, 10), (3646, 5), (3579, 2), (3500, 0), (-1000, 0), ) def get_adc_measurement(device): try: # this feature call has been known to produce errors so be extra cautious report = feature_request(device, FEATURE.ADC_MEASUREMENT) if report is not None: return decipher_adc_measurement(report) except FeatureCallError: return None def decipher_adc_measurement(report): # partial implementation - needs mapping to levels adc, flags = _unpack('!HB', report[:3]) for level in battery_voltage_remaining: if level[0] < adc: charge_level = level[1] break if flags & 0x01: status = BATTERY_STATUS.recharging if flags & 0x02 else BATTERY_STATUS.discharging return FEATURE.ADC_MEASUREMENT, charge_level, None, status, adc ```
There's some attempts at reverse-engineering the support in: https://github.com/Sapd/HeadsetControl/blob/master/src/devices/logitech_gpro.c Which is based off: https://github.com/ashkitten/g933-utils/ Would be great to get the battery curves from Logitech though, I can't think it would be too controversial...
Support was merged upstream in: https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git/commit/?id=c361982a13c91