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

razvanlupusoru picture razvanlupusoru · Feb 1, 2011 · Viewed 8.3k times · Source

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.

Answer

razvanlupusoru picture razvanlupusoru · Mar 5, 2011

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);
}