Bug 216483 - Logitech HID++ feature ADC_MEASUREMENT=0x1F20 reports battery information
Summary: Logitech HID++ feature ADC_MEASUREMENT=0x1F20 reports battery information
Status: RESOLVED CODE_FIX
Alias: None
Product: Drivers
Classification: Unclassified
Component: USB (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: Default virtual assignee for Drivers/USB
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-09-13 16:43 UTC by Peter F. Patel-Schneider
Modified: 2023-08-11 18:30 UTC (History)
1 user (show)

See Also:
Kernel Version: 5.19.7
Subsystem:
Regression: No
Bisected commit-id:


Attachments

Description Peter F. Patel-Schneider 2022-09-13 16:43:46 UTC
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

```
Comment 1 Bastien Nocera 2022-09-13 18:20:53 UTC
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...
Comment 2 Bastien Nocera 2023-08-11 18:30:04 UTC
Support was merged upstream in:
https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git/commit/?id=c361982a13c91

Note You need to log in before you can comment on or make changes to this bug.