Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No Battery Indicator (Steam and KDE Desktop) #21

Closed
atar-axis opened this issue Mar 7, 2018 · 29 comments
Closed

No Battery Indicator (Steam and KDE Desktop) #21

atar-axis opened this issue Mar 7, 2018 · 29 comments

Comments

@atar-axis
Copy link
Owner

The driver is now registering a power_supply for the gamepad (#14) at startup of the device.
You can access it's current state in /sys/bus/hid/devices/<gamepad>/power_supply/.

Unfortunately the battery is now visible in Steam, we don't know why yet.

@kakra, at #16 you wrote:

It also works for the Xbox controller if binding the controller to hid-microsoft. But it only reports 50% with a warning that batteries are almost depleted and, then it may (I cannot remember) to 25%, shortly after it turns off.

Are you talking about bluetooth or usb? Can you explain me how exactly you did that and how I can reproduce that? I will inspect the differences then and may find what steam expects and is missing.

@atar-axis atar-axis modified the milestones: Steam compatible out of the box , Steam compatibility out of the box Mar 7, 2018
@kakra
Copy link
Collaborator

kakra commented Mar 7, 2018

Please check my patches at https://github.com/kakra/linux/tree/rebase-4.14/xbox-one-s-controller which bind the controller to hid-microsoft instead of hid-general (xpadneo not included). This works for bluetooth, never tried usb.

With the hid-microsoft driver, the battery indicator shows up in the KDE systray in the battery and energy saving category.

I didn't have time yet to try your latest xpadneo driver.

@kakra
Copy link
Collaborator

kakra commented Mar 8, 2018

BTW: As with identify rumble, battery indicator in Steam only works with the Steam controller for me, it didn't work with hid-microsoft. But KDE desktop notifications worked for that driver (but Steam controller doesn't show up there). So, in Steam it seems to be implemented differently. Since I had a working desktop notification from KDE, this was no problem. I'm currently integrating your latest hid-xpadneo updates into my kernel patches.

@atar-axis
Copy link
Owner Author

With the hid-microsoft driver, the battery indicator shows up in the KDE systray in the battery and energy saving category.

Strange, since there is no special handling (not even a single line) for any power supply in hid-microsoft. Has to be something generic, maybe it is in another stacked driver.

As with identify rumble, battery indicator in Steam only works with the Steam controller for me, it didn't work with hid-microsoft. But KDE desktop notifications worked for that driver (but Steam controller doesn't show up there).

Ah! Okay I misunderstood that - do you know by any chance which driver is loaded for the Steam gamepad?

Thanks!

@kakra
Copy link
Collaborator

kakra commented Mar 8, 2018

I also think this comes from a stacked driver.

Do you mean the original Steam controller gamepad? That one with the trackpads?

It has no special hid driver, it works as a generic input device. It's totally useless, evtest doesn't see it as an input device, until you load the Steam client. The Steam client then attaches a uinput hid driver running in user space. This is used to map the serveral behaviors onto a controller. You'll then see dynamically created input devices. It can emulate Xbox 360 controllers for games, it can emulate a mouse/trackpad for desktop usage, you can virtually map any button/axis/pointer to the gamepad that you could ever think of.

@kakra
Copy link
Collaborator

kakra commented Mar 9, 2018

I now see the Xbox battery in KDE but it is shown as "Unknown" while with the hid-microsoft driver it shows up as "Xbox Controller":
image

@kakra
Copy link
Collaborator

kakra commented Mar 9, 2018

It looks like simply "manufacturer" and "model_name" may be missing:

hidpp_battery_0/:
capacity_level  device  manufacturer  model_name  online  power  powers  scope  serial_number  status  subsystem  type  uevent

'xpadneo_batt_3a:61:31:3a:30:30/':
capacity_level  device  power  powers  present  scope  status  subsystem  type  uevent

@atar-axis
Copy link
Owner Author

Perfect but somehow strange because I still do not see it here (despite thw fact that I am using KDE too) - anyway, will add those missing attributes in the evening.

@atar-axis
Copy link
Owner Author

atar-axis commented Mar 9, 2018

I also think this comes from a stacked driver.

The underlying part on the driver-stack was or rather is hid-input itself, which has a builtin generic HID_BATTERY_STRENGTH support (see here and here).

The problem you observed (empty on half battery) - is because the generic part need some information about what values represents the minimum and which maximum capacity. It tries to evaluate the logical minimum / logical maximum fields from the HID report. Unfortunately those are faulty in our case as the whole report descriptor.

The good news is: We/I can learn from the hid-input implementation for ours ;) I will not use the builtin (generic) solution since the whole thing is a bit more complicated in our case (battery pack and disposable batteries result in different values, both are influences by the charging cable, and so on)


Linking #22 and #14 for documentation

@atar-axis
Copy link
Owner Author

atar-axis commented Mar 10, 2018

It looks like simply "manufacturer" and "model_name" may be missing

@kakra: added, hope it works - I still don't see any peripheral batteries, but that's not a problem related to xpadneo.

@kakra
Copy link
Collaborator

kakra commented Mar 10, 2018

I think you need powerdevil in KDE for it to work.

@kakra
Copy link
Collaborator

kakra commented Mar 10, 2018

Looks good now in KDE:
image

@atar-axis
Copy link
Owner Author

atar-axis commented Mar 10, 2018

Thanks! I will keep it open until I fixed my problem too, or at least as long as I am not totally sure that this is not a problem which is caused by the driver. I have powerdevil installed, but the problem is that it's internal hasPeripheralBattery is set to false somehow - I am debugging at the moment.

I also would like to rethink some Properties (Online, Present) before closing - missing code documentation is sometimes really a problem in linux kernel code 👎, therefore I am not totally sure if those properties mean what I think they mean.

Anyhow - I am glad it works for you 😄

@atar-axis
Copy link
Owner Author

atar-axis commented Mar 10, 2018

The underlying Problem is, that Solid does not recognize the battery as an Solid::Battery - I don't know why yet

Update

It is recognized as Solid::DeviceInterface::GenericInterface somehow - strange, really

#include <QTextStream>

#include <QCoreApplication>
#include <Solid/Device>
#include <Solid/DeviceInterface>
#include <Solid/Battery>
//#include <Solid/PowerManagement>

#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    bool hasPowerSupplyBattery = false;
    bool hasPeripheralBattery = false;


    qDebug() << "All:";
    foreach( Solid::Device device, Solid::Device::allDevices() )
    {
        //print the name of device
        qDebug() << "Battery: " << device.isDeviceInterface(Solid::DeviceInterface::Battery) << " - " << device.udi() << endl << device.description();
    }


    qDebug() << "Generics:";
    foreach (Solid::Device device, Solid::Device::listFromType(Solid::DeviceInterface::GenericInterface, QString()))
    {
       qDebug() << device.udi().toLatin1().constData();
    }


    qDebug() << "Batteries:";
    Q_FOREACH (const Solid::Device &device, Solid::Device::listFromType(Solid::DeviceInterface::Battery, QString())) {

        qDebug() << device.udi(); // Prints only the main battery

        const Solid::Battery *b = qobject_cast<const Solid::Battery*> (device.asDeviceInterface(Solid::DeviceInterface::Battery));

        if (b->isPowerSupply()) {
            hasPowerSupplyBattery = true;
        } else {
            hasPeripheralBattery = true;
        }

    }

    if (hasPeripheralBattery) {
        qDebug() << "hasPeripheralBattery";
    } else {
        qDebug() << "!hasPeripheralBattery";
    }


    return a.exec();
}

@atar-axis
Copy link
Owner Author

atar-axis commented Mar 10, 2018

@kakra Can you do me a favor and give me the output of the following command on your system
upower --dump

@kakra
Copy link
Collaborator

kakra commented Mar 10, 2018

Here you go:

$ upower --dump
Device: /org/freedesktop/UPower/devices/keyboard_hidpp_battery_0
  native-path:          hidpp_battery_0
  model:                Wireless Keyboard K360
  serial:               4004-ad-e8-6b-cb
  power supply:         no
  updated:              Sa 10 Mär 2018 15:23:05 CET (93 seconds ago)
  has history:          yes
  has statistics:       yes
  keyboard
    present:             yes
    rechargeable:        yes
    state:               discharging
    warning-level:       none
    battery-level:       normal
    percentage:          55%
    icon-name:          'battery-good-symbolic'

Device: /org/freedesktop/UPower/devices/keyboard_xpadneo_batt_3ao61o31o3ao30o30
  native-path:          xpadneo_batt_3a:61:31:3a:30:30
  model:                Xbox Wireless Controller
  power supply:         no
  updated:              Sa 10 Mär 2018 15:24:31 CET (7 seconds ago)
  has history:          yes
  has statistics:       yes
  keyboard
    present:             yes
    rechargeable:        yes
    state:               discharging
    warning-level:       none
    battery-level:       high
    percentage:          70%
    icon-name:          'battery-full-symbolic'

Device: /org/freedesktop/UPower/devices/DisplayDevice
  power supply:         no
  updated:              Do 08 Mär 2018 07:19:00 CET (201938 seconds ago)
  has history:          no
  has statistics:       no
  unknown
    warning-level:       none
    icon-name:          'battery-missing-symbolic'

Daemon:
  daemon-version:  0.99.5
  on-battery:      no
  lid-is-closed:   no
  lid-is-present:  no
  critical-action: HybridSleep

@atar-axis
Copy link
Owner Author

atar-axis commented Mar 10, 2018

Thanks, but... strange. Can you please give me the following too, please (and sorry) 😄

1 solid-hardware list
2 solid-hardware nonportableinfo /org/freedesktop/UPower/devices/<xbox battery, see at list>
3 solid-hardware query 'IS BatteryInterface'

@kakra
Copy link
Collaborator

kakra commented Mar 10, 2018

Here it is, tho I only have solid-hardware5, and query is actually empty:
https://gist.github.com/d8c427b8f35f358375e891a6f6f0cabc

@atar-axis
Copy link
Owner Author

atar-axis commented Mar 11, 2018

Thank you very much, I still don't know exactly why but this helps a lot. The last command was indeed wrong, btw:
3 solid-hardware query 'IS Battery'

@kakra
Copy link
Collaborator

kakra commented Mar 11, 2018

Here you go:

$ solid-hardware5 query 'IS Battery'
udi = '/org/freedesktop/UPower/devices/keyboard_hidpp_battery_0'
udi = '/org/freedesktop/UPower/devices/mouse_hidpp_battery_1'
udi = '/org/freedesktop/UPower/devices/keyboard_xpadneo_batt_3ao61o31o3ao30o30'

@kakra
Copy link
Collaborator

kakra commented Mar 11, 2018

BTW: The Steam controller does not show up here. So it has its own means of reporting battery. The Steam client doesn't seem to use standard interfaces here.

@atar-axis atar-axis changed the title Steam: No Battery Indicator No Battery Indicator (Steam and KDE Desktop) Mar 12, 2018
@atar-axis
Copy link
Owner Author

atar-axis commented Mar 12, 2018

screenshot_20180312_114619

I finally found the underlying problem...

The KDE battery notification is based on Powerdevil.
Powerdevil is base on Solid and Solid has Backends to e.g. Upower.

In upowerdevice.cpp you can see the following

bool UPowerDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &type) const
{
    const uint uptype = prop("Type").toUInt();
    switch (type) {
    case Solid::DeviceInterface::GenericInterface:
        return true;
    case Solid::DeviceInterface::Battery:
        return (uptype == 2 || uptype == 3 || uptype == 5 || uptype == 6 || uptype == 7 || uptype == 8);
    default:
        return false;
    }
}

As you can see, a device is only recognized as a battery if the Type Property equals of those values (2, 3, 5, 6, 7 and 8).

In your case @kakra the gamepad was registered as an keyboard (type = 6), but in my case it was an gaming-input (type = 12).

typedef enum {
	UP_DEVICE_KIND_UNKNOWN,
	UP_DEVICE_KIND_LINE_POWER,
	UP_DEVICE_KIND_BATTERY,
	UP_DEVICE_KIND_UPS,
	UP_DEVICE_KIND_MONITOR,
	UP_DEVICE_KIND_MOUSE,
	UP_DEVICE_KIND_KEYBOARD,
	UP_DEVICE_KIND_PDA,
	UP_DEVICE_KIND_PHONE,
	UP_DEVICE_KIND_MEDIA_PLAYER,
	UP_DEVICE_KIND_TABLET,
	UP_DEVICE_KIND_COMPUTER,
	UP_DEVICE_KIND_GAMING_INPUT,
	UP_DEVICE_KIND_LAST
} UpDeviceKind;

Therefore, changing the function above to the following does fix the problem:

bool UPowerDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &type) const
{
    const uint uptype = prop("Type").toUInt();
    switch (type) {
    case Solid::DeviceInterface::GenericInterface:
        return true;
    case Solid::DeviceInterface::Battery:
        /* Every Device which is handled by Upower and which is not
         * UP_DEVICE_KIND_UNKNOWN (0) or UP_DEVICE_KIND_LINE_POWER (1) is a Battery
         * TODO: UP_DEVICE_KIND_MONITOR (4) was excluded too, is there any good reason for it?
         */
        return (uptype != 0 && uptype != 1);
    default:
        return false;
    }
}

You have to recompile the library and replace it in /usr/lib for sure.

@atar-axis
Copy link
Owner Author

atar-axis commented Mar 12, 2018

I consider closing this issue, the driver is working as expected - the problems are caused by Solid (the bug above) and Steam (missing implementation of the power_supply system). We may think about an Steam emulation mode for this and the other Steam related issues (missing FF to identify the controllers and mapping) in the future.

@atar-axis
Copy link
Owner Author

Closed, thanks @kakra for your help in finding the problem!

@kakra
Copy link
Collaborator

kakra commented Mar 12, 2018

I'd prefer if Valve would bring this up to Linux standard interfaces...

@atar-axis
Copy link
Owner Author

Yeah me too :)

@atar-axis
Copy link
Owner Author

@kakra
Copy link
Collaborator

kakra commented Mar 14, 2018

I wonder why Gentoo Linux correctly shows it as battery despite missing such a patch. Maybe because UPower identifies the device as keyboard for me?

@atar-axis
Copy link
Owner Author

atar-axis commented Mar 14, 2018

Yep that's why I guess - but the question is why... is your UPower version older than 6 months? They changed it at Version .99.6 from keyboard to gaming_input

@kakra
Copy link
Collaborator

kakra commented Mar 14, 2018

I'm still at:

$ equery l upower
 * Searching for upower ...
[IP-] [  ] sys-power/upower-0.99.5:0/3

kdesysadmin pushed a commit to KDE/solid that referenced this issue Mar 22, 2018
automatically add new types like gaming_input, as discussed here:
https://forum.kde.org/viewtopic.php?f=204&t=151433&p=395938#p395938

especially necessary for:
atar-axis/xpadneo#21

Differential Revision: https://phabricator.kde.org/D11331
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants