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

Battery level reporting? #222

Open
hmlendea opened this issue Jul 21, 2018 · 36 comments
Open

Battery level reporting? #222

hmlendea opened this issue Jul 21, 2018 · 36 comments

Comments

@hmlendea
Copy link

Hello,

Would it be possible to add battery level reporting into this app?
I currently own a Logitech G903 wireless gaming mouse and I often forget to charge it.

I'm really happy to have found this app that lets me configure the LEDs and buttons, and the only thing that's missing (for me) is the battery level feature.
It would also be nice to send notifications when the battery is very low (e.g. at 15% and 5%) - that would be insanely helpful.

@whot
Copy link
Member

whot commented Jul 23, 2018

Battery status report is probably doable though work is ongoing in GNOME to have this systemwide and integrated into the proper config panels. Likewise with notifications, I'd rather have gnome send this in a generic manner for all battery-powered devices.

@hmlendea
Copy link
Author

Thanks for the info.
Yes, it would be great if it can be integrated into GNOME and make it behave in a similar manner to other devices, that would be perfect!

Looking forward to see this, thank you.

@qidydl
Copy link

qidydl commented Jan 13, 2019

I think the system-level framework for doing this is upower, which has a daemon to communicate with (via DBUS?). It already has support for at least a few different Logitech mice, as evidenced in their udev rules. Not sure if it would be easy enough or worthwhile to pull and display the information it provides.

@whot
Copy link
Member

whot commented Jan 15, 2019

It's dbus and we already have a decent dbus wrapper with ratbagd.py. If you want to get started on that, I recommend taking the top-level class from ratbagd.py as a template for dbus objects and then hooking it up to talk to org.freedesktop.UPower. The devil's in the details as usual, with some mice only supporting a few bits for a battery state so you don't get percent but just "mostly empty, empty, full". And iirc there are mice where you can't tell the difference between "charging" and "unknown".

But either way, the piper work for this would merely be accumulating the information and displaying it, no actual per-device work is necessary, that should all go into upower/kernel.

@bentiss
Copy link
Collaborator

bentiss commented Jan 15, 2019

Just adding my 2 cents here. In recent kernels, upower doesn't do anything but relay the information provided by the kernel for Logitech devices. They used to do it in userspace (which explains why the code is still there, in case you are not running a recent enough kernel), but userspace needs polling when kernel space can just push the information when available.

I'll need to ping Logitech again regarding the recent gaming mice. They are not following any known and implemented protocol regarding their battery info. However, there are a little bit of preparatory work that needs to happen in the kernel before we can get to this point.

@whot
Copy link
Member

whot commented Jan 16, 2019

userspace needs polling when kernel space can just push the information when available.

does it? we can't subscribe to property updates on the dbus interface?

@bentiss
Copy link
Collaborator

bentiss commented Jan 16, 2019

userspace needs polling when kernel space can just push the information when available.

does it? we can't subscribe to property updates on the dbus interface?

Sorry, I was not talking at the same level:

  • if the battery processing is implemented in the kernel, the kernel pushes events to upowerd that then pushes the events to the clients (no poling)
  • if the battery processing is implemented in upowerd, upowerd needs to poll the device for the battery changes, and then pushes the changes to the client

So kernel is better, but from a client (piper) point of view, there is no differences

@Lahvuun
Copy link

Lahvuun commented Mar 24, 2019

@bentiss were you ever able to get in touch with Logitech regarding this topic? I've been looking into G703 battery readings recently and it's quite a headache without any documentation.

@bentiss
Copy link
Collaborator

bentiss commented Mar 25, 2019

Sorry, -ETIME from me (to send the email and think of it).

Last I remembered was that the battery reporting was not generic and each device had its own table of percentage/raw value associations.

@qidydl
Copy link

qidydl commented Mar 26, 2019

If you need to check things against an actual device, let me know, I have one and might be able to help. I also have a Windows laptop I can install the Logitech software on to do comparisons against.

@pedrovanzella
Copy link

I'm not even sure if I'm in the right track, but I'd like to share what I found so far:
I decided to probe all features reported by my G900 which were not known to libratbag and try to fetch battery data from them. Some errored out, while some gave meaningless values. Here's the full table, captured when the mouse was in wireless mode (thus, discharging):

| Feature | Level | Next Level | Status | Error                        |
|---------+-------+------------+--------+------------------------------|
|  0x0003 |    3% |       189% |    179 |                              |
|  0x0005 |   17% |         0% |      0 |                              |
|  0x1001 |   14% |       123% |      0 |                              |
|  0x1e00 |    0% |         0% |      0 |                              |
|  0x1e20 |       |            |        | ~ERR_INVALID_ARGUMENT (02)~  |
|  0x1eb0 |       |            |        | ~ERR_LOGITECH_INTERNAL (05)~ |
|  0x1850 |       |            |        | ~ERR_LOGITECH_INTERNAL (05)~ |
|  0x00c2 |    0% |         1% |      0 |                              |
|  0x1801 |       |            |        | ~ERR_LOGITECH_INTERNAL (05)~ |
|  0x1802 |       |            |        | ~ERR_LOGITECH_INTERNAL (05)~ |
|  0x1890 |       |            |        | ~ERR_LOGITECH_INTERNAL (05)~ |
|  0x1811 |       |            |        | ~ERR_LOGITECH_INTERNAL (05)~ |
|  0x18a1 |       |            |        | ~ERR_LOGITECH_INTERNAL~      |
|  0x1863 |       |            |        | ~ERR_LOGITECH_INTERNAL~      |
|  0x8111 |    0% |         8% |      0 |                              |
|  0x2230 |  255% |         0% |      0 |                              |
|  0x2240 |    0% |        31% |    228 |                              |

So I dropped the ones that errored out and probed the ones that did not once again with the mouse in wired mode (so, charging):

| Feature | Level | Next Level | Status | Change?                                      |
|---------+-------+------------+--------+----------------------------------------------|
|  0x0003 |    3% |       189% |    179 |                                              |
|  0x0005 |   17% |         0% |      0 |                                              |
|  0x1001 |   15% |        25% |    128 | YES. Next Level kept increasing              |
|  0x1e00 |    0% |         0% |      0 |                                              |
|  0x00c2 |    0% |         1% |      0 |                                              |
|  0x8111 |    0% |         8% |      0 |                                              |
|  0x2230 |  255% |         0% |      0 |                                              |
|  0x2240 |    0% |        31% |    228 |                                              |

Here we can see only one feature showed promise, 0x1001. The level changed to 15, while the next level kept rising (first to 25, then soon after to 46 and slowly climbing).

I did one final test by just probing feature 0x1001 with the mouse again in wireless mode. The level reported went back to 14, while next level slowly dropped (but started out at 230.

If I'm right, maybe the battery data is reported by this feature after all, only in some weird way. Maybe the byte order is different in the response (since I was reusing the battery information from hidpp20_battery_get_battery_level, it's likely I filled in the fields with the wrong data).

I also didn't look into the raw response for the features that didn't error out, so maybe the data is there, just not where I was expecting it to be.

@pedrovanzella
Copy link

I set up a windows VM and captured the data sent by the windows driver to the mouse.
Some interesting finds:
The message 10 ff 04 0a 00 00 00 is sent a few times. 04 refers to the feature with index 0x04, which is the feature 0x1001, which is the one I'm inclined to think is our battery level indicator.

When the mouse is charging, I get this response back:
11 ff 04 00 0f 29 80 00000000000000000000000000
Now, this is harder to make sense of, but it looks like our battery data is encoded in those three bytes at 0x04-0x06, with the value 0f 29 80. For reference, the mouse was at 30% charge then.

So I did a bit more probing and changed my function to send a short message instead of a long one when trying to initialize this feature. The message I ended up sending was this:
10 01 04 08 00 00 00 (This is on linux again)
To which I got the response:
11 01 04 08 0e 8a 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Again, this is harder to make sense of, but the data returned seemed to be 0e 8a 00. This looks very much like a discharging mouse, which was the case. The first two values don't make much sense in this context, but the last byte being zero would look like a "discharging" status.

Another interesting tidbit I found was when comparing the calls to the feature at 0x01 (feature 0x0001, "Feature Set"), which tells me that Feature 0x1001 is at 0x04, plus two things:
One, no flags are set, so it's not an internal nor a hidden feature. Two, the next byte is 0x02, which I have no idea what means, but no other feature seems to have it set.

For reference, this is the exchange:

ratbag raw: Init feature 0x1001 (0x1001) 
ratbag raw: hidpp write: 11 01 00 08 10 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ratbag raw: hidpp read:  11 01 00 08 04 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
ratbag raw: feature 0x1001 is at 0x04

This is the full list of features reported by libratbag:

|     ID | Index | Name                   | Flags             | Notes                                        |
|--------+-------+------------------------+-------------------+----------------------------------------------|
| 0x0000 |  0x00 | Root                   |                   |                                              |
| 0x0001 |  0x01 | Feature Set            |                   |                                              |
| 0x0003 |  0x02 | Device Info            |                   |                                              |
| 0x0005 |  0x03 | Device Name            |                   |                                              |
| 0x1001 |  0x04 |                        |                   | Offset 0x02 from response is 0x02            |
| 0x1863 |  0x05 |                        | INTERNAL + HIDDEN |                                              |
| 0x18a1 |  0x06 |                        | INTERNAL + HIDDEN |                                              |
| 0x1e00 |  0x07 |                        | HIDDEN            |                                              |
| 0x1e20 |  0x08 |                        |                   |                                              |
| 0x1eb0 |  0x09 |                        | INTERNAL + HIDDEN |                                              |
| 0x2201 |  0x0a | Adjustable DPI         |                   |                                              |
| 0x2230 |  0x0b | Angle Snapping         |                   | Feature name from Solaar                     |
| 0x2240 |  0x0c | Surface Tuning         |                   | Feature name from Solaar                     |
| 0x8060 |  0x0d | Adjustable Report Rate |                   |                                              |
| 0x8100 |  0x0e | Onboard Profiles       |                   |                                              |
| 0x8110 |  0x0f | Mouse Button Spy       |                   |                                              |
| 0x1850 |  0x10 |                        | INTERNAL + HIDDEN |                                              |
| 0x00c2 |  0x11 |                        |                   | Solaar has 0x00c0 and 0x00c1 as DFU controls |
| 0x1801 |  0x12 |                        | INTERNAL + HIDDEN |                                              |
| 0x1802 |  0x13 |                        | INTERNAL + HIDDEN |                                              |
| 0x1890 |  0x14 |                        | INTERNAL + HIDDEN |                                              |
| 0x1811 |  0x15 |                        | INTERNAL + HIDDEN |                                              |
| 0x8111 |  0x16 |                        |                   |                                              |
| 0x8070 |  0x17 | Color LED Effects      |                   |                                              |
| 0x1300 |  0x18 | LED Control            |                   | Feature name from Solaar                     |

@Lahvuun
Copy link

Lahvuun commented Apr 28, 2019

@pedrovanzella the protocol is very similar to the Unifying Receiver one, you can check out the spec for it. Battery level reporting there is at 0x1000, so that's the first hint.

Now, the Unifying Receiver battery level reporting returns a value from 0 to 100, i.e. the percentage. The "Lightspeed" receiver (at least that's how Logitech refer to it, I think) instead returns the battery's voltage, which doesn't map to the 0..100 range 1 to 1. What Logitech do is they have a hash table of battery voltages, along with the percentage. What LGHub does is take the voltage and lookup the corresponding percentage. The tables are different for charge and discharge.

I'm not sure where the hash table comes from (i.e. whether it's distributed with LGHub, fetched from Logitech servers, stored on the device, or maybe something different altogether), but you can actually access it locally. LGHub runs a web server at a certain port, which you can access from the browser to download the .xml file it uses to lookup the battery levels. LGHub is an electron application, you should be able to open DevTools with Ctrl+Shift+I. It actually logs all the requests traveling to and from your PC in the console. You should be able to find the .xml URL there. If you can't open DevTools, you may need to run LGHub in debug mode with the --debug switch.

@aouerf
Copy link

aouerf commented Apr 29, 2019

For what it's worth, Linux 5.2 will have support for Logitech wireless receivers, which will probably come with battery level reporting.

@bentiss
Copy link
Collaborator

bentiss commented Apr 29, 2019

For what it's worth, Linux 5.2 will have support for Logitech wireless receivers, which will probably come with battery level reporting.

Unfortunately no for the G900. And I guess same applies to the G403 and the other mice attached to the lightspeed receivers. @Lahvuun has a pretty good explanation :)

@Lahvuun thanks a lot for the findings about the XML file. I'll see with Logitech if and how we can use those XML files.

@Lahvuun
Copy link

Lahvuun commented Apr 29, 2019

If anyone is interested in what they look like, but doesn't want to go through the trouble, here are the manifest and battery files for my g703:
4032fa8f95b97a946002ca1d633b34cc19d40b738bf14d33861316d539814ab0.json.gz
dd936d9bcd0641e6f23bce130b7b3f675092d8b8ef0aded1a7de0e5025e60b18.bin.gz

The .bin file is actually XML.

And here's what to look for in LGHub:
lghub_debug

@pedrovanzella
Copy link

@Lahvuun thanks for the LGHub tip. I've been digging through it and found another couple of interesting things. This is the battery dump for my G900:
g900_battery.zip

I also found a response with a feature list:
img-2019-04-30-111936

Something interesting to note: Feature 4097 (0x1001, which I strongly suspect is the battery level indicator) has a version of 2, which is probably the 0x02 byte I didn't know what meant before. There are a few other features with a version other than zero, like 0x8070 (Light effects), with a version of 04.

Maybe this is useful.

@pedrovanzella
Copy link

Okay, so I figured out how the battery voltage is read, as well as most of the status bits and sent that as a PR to libratbag. I also have the xml files for all battery models, which lets me calculate percentage based on the voltage read. I figure this part is better done in piper, right?

Is there currently a battery page for any kind of device in piper? I think I might look into that over the weekend, unless someone who knows the codebase better wants to jump into it. Let me know and I can share the xml files and my notes on how all this works.

@Hjdskes
Copy link
Member

Hjdskes commented May 17, 2019

I figure this part is better done in piper, right?

No, Piper is just a frontend displaying what it reads over DBus from libratbag. This too should go into libratbag.

@qidydl
Copy link

qidydl commented May 23, 2019

A comment on the upower issues indicates that at least some of this work might actually belong in the kernel, not sure how to make that happen though. I'll try to do a little digging.

The driver for this is probably drivers/hid/hid-logitech-hidpp.c, and here's a best guess at the maintainers. Putting two and two together, one of those individuals has already commented in this thread... so they can probably do a better job offering suggestions than I.

@pedrovanzella
Copy link

I think the lower levels of this stack (the Linux kernel, maybe even libratbag) should only report battery voltage and status, as that is what all devices will always report with feature 0x1001. The higher levels (upower maybe, probably piper) can deal with converting that into a percentage and what not.

The reason for that is mostly that when a new device comes along, all we have to do is figure out the battery curve for it. So adding this new device to something like piper is easier (and it doesn’t litter the kernel with constants for different batteries, which I think they might oppose).

@bentiss
Copy link
Collaborator

bentiss commented May 23, 2019

I fully agree with @pedrovanzella
I think the kernel is capable of reporting voltage instead of capacity. So having the feature implemented in hid-logitech-hidpp.ko would be the best plan further.

@stuarthayhurst
Copy link

Apparently kernel 5.2 can relay battery levels for 2.4GHz Logitech devices now for use in desktop GUIs.

@maxdraki
Copy link

Sorry for resurrecting a fairly old thread, but this seems like the most relevant place to ask.. Now with kernel 5.3 out (at least in Ubuntu 19.10 beta) could someone help me with a cli command to get the battery percentage from my logitech g703?
thanks

@Linux-Fan
Copy link

I would like to get the battery status of G900 as well. Anyone have had any success?

@maxdraki
Copy link

There's a thread here with some more info: pwr-Solaar/Solaar#570

@macmv
Copy link

macmv commented Jan 7, 2020

I'd really like this feature to be added, even if it's just for the piper app, rather than integrating with gnome. Any progress?

@qidydl
Copy link

qidydl commented Jun 15, 2020

The Solaar issue @maxdraki referenced appears closed as of 9 days ago in pwr-Solaar/Solaar#802, for what it's worth. Piper and Solaar appear to have complementary feature sets, so if Solaar has taken up the mantle of displaying battery status, maybe Piper doesn't need to.

@samhh
Copy link

samhh commented Sep 5, 2020

@qidydl I believe ratbag supports some devices that Solaar does not.

For anyone who wants to get their current battery level, the device appears to be accessible here on Arch - note the exact name at the end of the path may differ depending upon what you have plugged in and your exact device (mine is a G305):

/sys/class/power_supply/hidpp_battery_0/

This gives me "Full" on a new battery, I think this will change to "High", "Normal", etc as it discharges:

$ cat /sys/class/power_supply/hidpp_battery_0/capacity_level

Edit: Yep, it's just changed to "Normal".

@DiegoCastroAlves
Copy link

If anyone is interested in what they look like, but doesn't want to go through the trouble, here are the manifest and battery files for my g703:
4032fa8f95b97a946002ca1d633b34cc19d40b738bf14d33861316d539814ab0.json.gz
dd936d9bcd0641e6f23bce130b7b3f675092d8b8ef0aded1a7de0e5025e60b18.bin.gz

The .bin file is actually XML.

And here's what to look for in LGHub:
lghub_debug

My mouse is a "G703 LIGHTSPEED Wireless Gaming Mouse w / HERO" and I'm not able to get the battery information. I know almost nothing about it.

Would there be any solution to this problem?
Sem título

@theRealPadster
Copy link

Is there any update to this? I am able to access the voltage of my G703 (over wireless) with cat /sys/class/power_supply/hidpp_battery_1/voltage_now, which gives me 3913000. This corresponds with the 3913mV reported by Solaar.

@omgitsaheadcrab
Copy link

Still waiting on Logitech to provide the people at Solaar with the numbers to convert voltage into a percentage, there's little point in displaying a voltage.

@maxdraki
Copy link

It's mentioned in the linux-input list = https://www.spinics.net/lists/linux-input/msg70450.html

@spstarr
Copy link

spstarr commented Feb 16, 2021

This also would be good for the G903, I see voltage 4107mv (Charging) but I don't know the % of the battery via the Wireless Charging Pad/G903

@Zenrage
Copy link

Zenrage commented Apr 6, 2022

Fell upon this recently. I tried finding the battery information n LGhub but couldnt find the XML dumps. Have they changed it ? Was looking for the G502/G915 and the Headset G933

@hadess
Copy link

hadess commented Dec 5, 2022

It's mentioned in the linux-input list = https://www.spinics.net/lists/linux-input/msg70450.html

This was finally implemented in b23cdfbddb73bad9d835baabd076ee4bfe1ab2bb by Hamza Mahfooz.

FWIW, I think that the battery reporting should be done in the kernel, and made available to user-space by upower. Then Piper is free to consume that information to display it. Reimplementing battery reporting in the desktop, or warnings should be out of scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests