How can I obtain battery level inside a Linux kernel module?

9.7k views Asked by At

I am trying to get the battery level inside a Linux kernel module (the module is inserted via modprobe). I would ideally like to use a kernel API call to get the battery information. I have searched on the web for solutions, and I have also explored Linux kernel source and the source of program "acpi" by Michael Meskes for ideas.

These are some of the techniques I think I can use:

  1. Read and parse /proc/acpi/battery/BAT0/state and /proc/acpi/battery/BAT0/info
  2. Read from /sys/class/power_supply/BAT0/charge_now and charge_full with no parsing involved.
  3. I could try using the calls from Linux kernel source drivers/acpi/battery.c if I could figure out how to expose the interface. I would probably need the methods acpi_battery_get_status and acpi_battery_get_info
  4. I also noticed that inside drivers/acpi/sbs.c there's a method acpi_battery_read and right above it there is a comment saying "Driver Interface". This might be another way if anyone knows how to use this.

I assume that it is probably a bad idea to read files while inside a kernel module, but I am not exactly sure how those files map to kernel function calls, so it might be okay.

So, can you guys give me some suggestions/recommendations?

Edit: I included my solution in an answer below.

3

There are 3 answers

1
razvanlupusoru On BEST ANSWER

I have found a solution that works for me. First of all make sure to #include < linux/power_supply.h >

Assuming you know the name of the battery, this code gives an example of how to get current battery capacity.

char name[]= "BAT0";
int result = 0;
struct power_supply *psy = power_supply_get_by_name(name);
union power_supply_propval chargenow, chargefull;
result = psy->get_property(psy,POWER_SUPPLY_PROP_CHARGE_NOW,&chargenow);
if(!result) {
    printk(KERN_INFO "The charge level is %d\n",chargenow.intval);
}
result = psy->get_property(psy,POWER_SUPPLY_PROP_CHARGE_FULL,&chargefull);
if(!result) {
    printk(KERN_INFO "The charge level is %d\n",chargefull.intval);
}
1
TheCottonSilk On

Looking at the battery.c, sbs.c, I think you can call the interface API (acpi_battery_read, acpi_battery_get_state) in your LKM directly.
Did you try that so far?

0
none On

I have the same dilemma! :-\ If this is a hardware specific thing you'r doing, you could see if on your particular laptop you can detect the smart battery on the SMBus link or not. If you can, then you can just do i2c/SMBus calls from within your LKM. Most new systems (except some Fujitsu laptops) talk to an embedded controller instead, which ends up configuring the battery (through SMBus i suppose).... Try installing "lm-sensors" and see if it detects your smart battery. If so you should be able to talk directly to the battery (usually at i2c address 0xb).

If this isn't a hardware specific thing you're doing, then ignore what i said :)