Upower
Hacking
meson setup --prefix /tmp --libexecdir lib --sbindir bin --reconfigure build
meson compile -C build
- Mail Arvid Norlander lkml@vorpal.se if Toshiba laptops have a start limit
- wCPO Asus https://www.asus.com/us/support/FAQ/1032726/ suggests 58/60%
- LG only has 80 and 100 as end charge limit
- Toshiba only has 80 and 100 as end charge limit
- Add documentation for the LG/ASUS/Toshiba stop thresholds special cases
- Poke gnome shell PR https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3474
- Follow up charge_types support
Kernel
To be ported to charge_types
-
Ideapad -
/sys/bus/platform/devices/VPC2004:*/conservation_mode
- Ported, needs merge of power_supply extension and tested
- Panasonic - eco_mode, has non-standard undocumented sysfs entry https://lore.kernel.org/all/20200821181433.17653-9-kenneth.t.chan@gmail.com/
-
Samsung -
/sys/devices/platform/samsung/battery_life_extender
-
LG battery_care_limit
/sys/devices/platform/lg-laptop/battery_care_limit
- Ported, needs merge of power_supply extension
- Acer WMI (out of tree) - new file acer-wmi-battery.c
- Dell
Not an end threshold:
- Sony battery_care_limiter => end_threshold. Are there still sony vaio's? :)
-
Ask on Revspace
-
Ask Arch staff
-
tweakers V & A, ebay, marktplaats
Upstream / standarize
Sony vaio
Sony battery_care_limiter, converted to charge_control_end_threshold. What devices still have those? Also document the non-standard sysfs attr in Documentation/ABI/testing/sysfs-platform-sony-laptop
.
Acer WMI
-
Got told it might need a new file
acer-wmi-battery
like Dell, how does this work? But it also handles other GUID's so maybe not? ACER WMI driver does not usewmi-driver
struct so is it old? Or just put together? - WMI helpers in kernel?
- Kernel docs related to WMI
WMI resources
- LWN ACPI driver (dated)
- LWN WMI driver (dated)
- Ubuntu WMI docs
- Kernel WMI driver API
- Writing a WMI driver
- Kernel ACPI Interface
- ACPI Tables, sections of infromation provided to the Operation System by the BIOS, they contain either blocks of configuration information or, alternatively, executable code in a compile bytecode called AML.
- DSDT - Discrete System Descriptor Table, provides a set of configuration information and control methods for the system hardware. (can be found in /sys/firmware/acpi/tables/DSDT). Can be decompiled from AML bytecode to ASL (ACPI Source Language) with
iasl
from the package acpica. - acpi_evaluate_object() - asks the kernel's APCI interpeter to find a method underneath a specific area of namespace (namespace of the device we are bound too).
- acpi_evaluate_integer() - asks the kernel's ACPI interpeter to evalulate a method which is supposed to return an integer.
- Notify "keyword" - ACPI's way to signal captured events to the operation system. A kernel driver can listen to these events.
- WMI - Windows Management Instrumentation, a set of extensions to the windows Driver Model that provides operationg system interface for dealing with platform devices. WMI objects can be embedded within ACPI.
- Package lswmi? Or
wmidump
?
Battery power supply extension API
- charge types a3a8799165ff83bb764fd800c6559c3cba0ddac3
- battery extension 6037802bbae892f3ad0c7b4c4faee39b967e32b0
battery_hook_register()
Dell
- First move dell to use the battery extension
- Then test it also in drivers/power/supply/test_power.c
panasonic
static struct acpi_battery_hook battery_hook = {
.add_battery = lg_battery_add,
.remove_battery = lg_battery_remove,
.name = "Panasonic Battery Extension",
};
battery_hook_register(&battery_hook);
ideapad
- needs battery_hook_register
- need to do my own locking with a mutex?
static struct acpi_battery_hook battery_hook = {
.add_battery = lg_battery_add,
.remove_battery = lg_battery_remove,
.name = "LG Battery Extension",
};
battery_hook_register(&battery_hook);
Look at the cros_charge_control.c code
static int ideapad_psy_prop_is_writable(struct power_supply *psy,
const struct power_supply_ext *ext,
void *data,
enum power_supply_property psp)
{
return true;
}
static const struct power_supply_ext charge_types = {
.name = "ideapad-charge-types",
.properties = POWER_SUPPLY_PROP_CHARGE_TYPES
.num_properties = 1
.get_property = cros_chctl_psy_ext_get_prop, .set_property = cros_chctl_psy_ext_set_prop,
.property_is_writeable = cros_chctl_psy_prop_is_writeable
}
Gnome Settings
busctl call org.freedesktop.UPower /org/freedesktop/UPower/devices/battery_BAT0 org.freedesktop.UPower.Device EnableChargeThreshold b true
UPower Git issues
-
On startup
charge-threshold-supported
is FALSE, after I toggle a dbus setting we re-read it and it's true this should be read on startup!!! - Implement the switch functionality, setting the DBus property
- Removes lid handling 07565ef6a1aa4a115f8ce51e259e408edbaed4cc as systemd does it? What should gnome do? https://gitlab.freedesktop.org/upower/upower/-/merge_requests/5#note_540149
$ busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager LidClosed
b false
15:50:57 hansg | Hmm, mutter depend ook op upower for LID change monitoring, maar alleen via DBUS. Dus ik zou zeggen reverten met de change die LID support dropped van upower voor nu. Tot dat
| er een alternatief is. (alternatief is waarschijnlijk LID-switch support toevoegen aan libinput en dan mutter dat laten gebruiken en gnome-control-center het aan mutter laten
| vragen ..,)
- Unrelated, but we could easily implement a Linger property changed Just emit here?
static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- Handle get_devices changes => REVERT
- How do we get the current charge levels into the translated text label?
GTK tutorial/intro
Follow up
- framework charge_control settings
- multiple USB keyboard's with backlight laptop + USB
- Dell privacy screen switch state to libinput to mutter (ask Hans for hardware)
- USB re-pluggable usb keyboard backlight support in upower (ask Hans for hardware)
- Steam Deck enhancements? https://gitlab.freedesktop.org/upower/upower/-/issues/245
meson warnings
Build targets in project: 36
NOTICE: Future-deprecated features used:
* 1.1.0: {'"boolean option" keyword argument "value" of type str'}
Battery charge limit
New idea, use hwdb for profiles
Match if /sys/class/power_supply/*
/etc/udev/rules.d/60-battery.rules
ACTION=="remove", GOTO="battery_end"
# sensor:<model_name>:dmi:<dmi pattern>
SUBSYSTEM=="power_supply", KERNEL=="BAT*", \
IMPORT{builtin}="hwdb 'battery:$attr{model_name}:$attr{[dmi/id]modalias}'", \
GOTO="battery_end"
LABEL="battery_end"
/etc/udev/hwdb.d/60-battery.rules
battery:*:dmi:*
CHARGE_LIMIT=docked;20;60
battery:*:dmi:*T14s*
CHARGE_LIMIT=docked;50;80
Like /usr/lib/udev/hwdb.d/60-sensor.hwdb
Testing is done with udevadm
udevadm test /sys/class/power_supply/BAT0
Hard loading
sudo systemd-hwdb update --strict || echo 'could not parse succesfully'
sudo udevadm trigger -v -p /sys/class/power_supply/BAT0
udevadm info -q all /sys/class/power_supply/BAT0
- multi battery laptop, we should also allow match on "BAT*"
- systemd PR for hwdb.d/parse_hwdb.py ?!
To add local entries, create a new file /etc/udev/hwdb.d/61-battery-local.hwdb
systemd-hwdb update
udevadm trigger -v -p DEVNAME=/dev/iio:deviceXXX
[docked]
start=50
stop=80
[travel]
start=100
end=100
[conservative]
start=20
end=60
/etc/upower/battery.d/20-lenovo
[docked]
start=30
end=90
dmi=T14sGen1 & T14S
Multiple batteries
[lenovo-bat0]
start=30
end=90
dmi=Lenovo
battery=BAT0
[lenovo-bat1]
start=50
end=90
dmi=Lenovo
battery=BAT1
Where dmi
is a glob match on /sys/class/dmi/id/modalias
so *T14sGen1*
battery
is an entry in /sys/class/power_supply
DBus API
a{s}
of battery limit profiles
- Enable()
- Supported Property?
- Start Property
- End Property
Caveats
- Not all laptops/hardware supports the same settings so setting on 80 might be 90.
Enum
To not show too many profiles at once we should maybe just support an Enum of modes and every profile has a mode entry and in theory we could "extend" this in the future.
- low power
- docked
- travel
- conservative?
Steamdeck
https://0x0.st/HGAi.sh
Supports it through a non-standard knob max_battery_charge_level
, kernel source and driver code.
- how do I write a proper driver which uses charge_control_end_threshold
- how do other drivers do this?
- how does this get to power_supply?
- how is the power_supply class created?
Mainline OpenRazer power bits so upower works out of the box
A user made a bug report to support openrazer's sysfs attributes for charging/battery readout. This driver sadly exports custom sysfs attributes while it should implement a power_supply such as the logitech hid-logitech-hidpp.c
driver which upower can automatically pick up
- Obtain hardware with an USB dongle, bluetooth might work out of the box?
- How does one implement a power_supply driver?
- Contact upstream about mainlining, note that the driver exposes far more stuff over sysfs which likely can't be mainlined nor do I have interest in.
Battery Calibration
After Charge limits we should consider working on battery calibration. To inhibit the system, we can use a systemd dbus call just like cc-color-calibrate
does in gnome-control-center
.
UPower instead should probably talk to systemd to to inhibit and it works as following:
UPower adds:
- BAT0->Calibrate()
- BAT0->IsCalibrating = bool
User calls BAT0->Calibrate() We set IsCalibrating = true We inhibit the current session https://www.freedesktop.org/wiki/Software/systemd/inhibit/ We disallow changing the charge limits We disable charge limits We 'full-discharge' to /sys/class/power_supply/BAT0/charge_behaviour We keep track of where we are, so discharge X% => 0% and then 0% => 100% is a full calibration We restore charge limits if set Once completed we set isCalibrating to False.
Short schema:
sequenceDiagram User->>UPower: BAT0->Calibrate() UPower->>UPower: IsCalibrating = true; UPower->>UPower: Inhibit desktop session UPower->>UPower: Disallow changing charge limits UPower->>UPower: Disable charge limits UPower->>UPower: Set `full-discharge` to `charge_behaviour` UPower->>UPower: Keep track of dischargin and charging to 100% UPower->>UPower: Restore charge limits UPower->>UPower: IsCalibrating = false; UPower->>User: Done
Questions
- do we want to inhibit?
- systemd support has to be optional?
- do we want a new "icon-name" when calibrating?
- "Not charging" -> should become "Calibrating" in gnome
- User should see an indication of "changes", is that energy/energy-full?