Search code examples
linux-kernelkernel-moduleacpi

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


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.


Solution

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