2241<@jupet�kellari��> 1.16 1.2 0x03 0x00 0x00 0x01 99% -1 ? monitori p��ll� mutta ilman verkkovirtaa
*/
+/* Kapil Hari Paranjape <kapil@imsc.res.in>
+ Linux 2.6.24 onwards battery info is in
+ /sys/class/power_supply/BAT0/
+ On my system I get the following.
+ /sys/class/power_supply/BAT0/uevent:
+ PHYSDEVPATH=/devices/LNXSYSTM:00/device:00/PNP0A03:00/device:01/PNP0C09:00/PNP0C0A:00
+ PHYSDEVBUS=acpi
+ PHYSDEVDRIVER=battery
+ POWER_SUPPLY_NAME=BAT0
+ POWER_SUPPLY_TYPE=Battery
+ POWER_SUPPLY_STATUS=Discharging
+ POWER_SUPPLY_PRESENT=1
+ POWER_SUPPLY_TECHNOLOGY=Li-ion
+ POWER_SUPPLY_VOLTAGE_MIN_DESIGN=10800000
+ POWER_SUPPLY_VOLTAGE_NOW=10780000
+ POWER_SUPPLY_CURRENT_NOW=13970000
+ POWER_SUPPLY_ENERGY_FULL_DESIGN=47510000
+ POWER_SUPPLY_ENERGY_FULL=27370000
+ POWER_SUPPLY_ENERGY_NOW=11810000
+ POWER_SUPPLY_MODEL_NAME=IBM-92P1060
+ POWER_SUPPLY_MANUFACTURER=Panasonic
+ On some systems POWER_SUPPLY_ENERGY_* is replaced by POWER_SUPPLY_CHARGE_*
+*/
+
+#define SYSFS_BATTERY_BASE_PATH "/sys/class/power_supply"
#define ACPI_BATTERY_BASE_PATH "/proc/acpi/battery"
#define APM_PATH "/proc/apm"
#define MAX_BATTERY_COUNT 4
+static FILE *sysfs_bat_fp[MAX_BATTERY_COUNT];
static FILE *acpi_bat_fp[MAX_BATTERY_COUNT];
static FILE *apm_bat_fp[MAX_BATTERY_COUNT];
char acpi_path[128];
snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
+ char sysfs_path[128];
+ snprintf(sysfs_path, 127, SYSFS_BATTERY_BASE_PATH "/%s/uevent", bat);
init_batteries();
memset(last_battery_str[idx], 0, sizeof(last_battery_str[idx]));
memset(last_battery_time_str[idx], 0, sizeof(last_battery_time_str[idx]));
- /* first try ACPI */
-
- if (acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL) {
- acpi_bat_fp[idx] = open_file(acpi_path, &rep);
- }
-
- if (acpi_bat_fp[idx] != NULL) {
+ /* first try SYSFS if that fails try ACPI */
+
+ if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL)
+ sysfs_bat_fp[idx] = open_file(sysfs_path, &rep);
+
+ if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL)
+ acpi_bat_fp[idx] = open_file(acpi_path, &rep);
+
+ if (sysfs_bat_fp[idx] != NULL) {
+ /* SYSFS */
+ int present_rate = -1;
+ int remaining_capacity = -1;
+ char charging_state[64];
+ char present[4];
+
+ strcpy(charging_state, "Unknown");
+
+ while (!feof(sysfs_bat_fp[idx])) {
+ char buf[256];
+ if (fgets(buf, 256, sysfs_bat_fp[idx]) == NULL)
+ break;
+
+ /* let's just hope units are ok */
+ if (strncmp (buf, "POWER_SUPPLY_PRESENT=1", 22) == 0)
+ strcpy(present, "Yes");
+ else if (strncmp (buf, "POWER_SUPPLY_PRESENT=0", 22) == 0)
+ strcpy(present, "No");
+ else if (strncmp (buf, "POWER_SUPPLY_STATUS=", 20) == 0)
+ sscanf(buf, "POWER_SUPPLY_STATUS=%63s", charging_state);
+ /* present_rate is not the same as the
+ current flowing now but it is the same value
+ which was used in the past. so we continue
+ the tradition! */
+ else if (strncmp(buf, "POWER_SUPPLY_CURRENT_NOW=", 25) == 0)
+ sscanf(buf, "POWER_SUPPLY_CURRENT_NOW=%d", &present_rate);
+ else if (strncmp(buf, "POWER_SUPPLY_ENERGY_NOW=", 24) == 0)
+ sscanf(buf, "POWER_SUPPLY_ENERGY_NOW=%d", &remaining_capacity);
+ else if (strncmp(buf, "POWER_SUPPLY_ENERGY_FULL=", 25) == 0)
+ sscanf(buf, "POWER_SUPPLY_ENERGY_FULL=%d", &acpi_last_full[idx]);
+ else if (strncmp(buf, "POWER_SUPPLY_CHARGE_NOW=", 24) == 0)
+ sscanf(buf, "POWER_SUPPLY_CHARGE_NOW=%d", &remaining_capacity);
+ else if (strncmp(buf, "POWER_SUPPLY_CHARGE_FULL=", 25) == 0)
+ sscanf(buf, "POWER_SUPPLY_CHARGE_FULL=%d", &acpi_last_full[idx]);
+ }
+
+ fclose(sysfs_bat_fp[idx]);
+ sysfs_bat_fp[idx] = NULL;
+
+ /* Hellf[i]re notes that remaining capacity can exceed acpi_last_full */
+ if (remaining_capacity > acpi_last_full[idx])
+ acpi_last_full[idx] = remaining_capacity; /* normalize to 100% */
+
+ /* not present */
+ if (strcmp(present, "No") == 0) {
+ strncpy(last_battery_str[idx], "not present", 64);
+ }
+ /* charging */
+ else if (strcmp(charging_state, "Charging") == 0) {
+ if (acpi_last_full[idx] != 0 && present_rate > 0) {
+ /* e.g. charging 75% */
+ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1, "Charging %i%%",
+ (int) (((float) remaining_capacity / acpi_last_full[idx]) * 100 ));
+ /* e.g. 2h 37m */
+ format_seconds(last_battery_time_str[idx], sizeof(last_battery_time_str[idx])-1,
+ (long) (((float)(acpi_last_full[idx] - remaining_capacity) / present_rate) * 3600));
+ } else if (acpi_last_full[idx] != 0 && present_rate <= 0) {
+ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1, "Charging %d%%",
+ (int) (((float)remaining_capacity / acpi_last_full[idx]) * 100));
+ } else {
+ strncpy(last_battery_str[idx], "Charging", sizeof(last_battery_str[idx])-1);
+ }
+ }
+ /* discharging */
+ else if (strncmp(charging_state, "Discharging", 64) == 0) {
+ if (present_rate > 0) {
+ /* e.g. discharging 35% */
+ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1, "Discharging %i%%",
+ (int) (((float) remaining_capacity / acpi_last_full[idx]) * 100 ));
+ /* e.g. 1h 12m */
+ format_seconds(last_battery_time_str[idx], sizeof(last_battery_time_str[idx])-1,
+ (long) (((float)(acpi_last_full[idx] - remaining_capacity) / present_rate) * 3600));
+ } else if (present_rate == 0) { /* Thanks to Nexox for this one */
+ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1, "Full");
+ } else {
+ snprintf(last_battery_str[idx], sizeof(last_battery_str[idx])-1,
+ "Discharging %d%%",
+ (int) (((float)remaining_capacity / acpi_last_full[idx]) * 100));
+ }
+ }
+ /* charged */
+ /* thanks to Lukas Zapletal <lzap@seznam.cz> */
+ else if (strncmp(charging_state, "Charged", 64) == 0) {
+ /* Below happens with the second battery on my X40,
+ * when the second one is empty and the first one
+ * being charged. */
+ if (remaining_capacity == 0)
+ strcpy(last_battery_str[idx], "Empty");
+ else
+ strcpy(last_battery_str[idx], "Charged");
+ }
+ /* unknown, probably full / AC */
+ else {
+ if (acpi_last_full[idx] != 0
+ && remaining_capacity != acpi_last_full[idx])
+ snprintf(last_battery_str[idx], 64, "Unknown %d%%",
+ (int) (((float)remaining_capacity / acpi_last_full[idx]) * 100));
+ else
+ strncpy(last_battery_str[idx], "AC", 64);
+ }
+ } else if (acpi_bat_fp[idx] != NULL) {
+ /* ACPI */
int present_rate = -1;
int remaining_capacity = -1;
char charging_state[64];
char acpi_path[128];
snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
+ char sysfs_path[128];
+ snprintf(sysfs_path, 127, SYSFS_BATTERY_BASE_PATH "/%s/uevent", bat);
init_batteries();
}
last_battery_perct_time[idx] = current_update_time;
- /* Only check for ACPI */
+ /* Only check for SYSFS or ACPI */
+
+ if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL)
+ sysfs_bat_fp[idx] = open_file(sysfs_path, &rep);
- if (acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL) {
+ if (sysfs_bat_fp[idx] == NULL && acpi_bat_fp[idx] == NULL && apm_bat_fp[idx] == NULL)
acpi_bat_fp[idx] = open_file(acpi_path, &rep);
- }
int remaining_capacity = -1;
- if (acpi_bat_fp[idx] != NULL) {
+ if (sysfs_bat_fp[idx] != NULL) {
+ /* SYSFS */
+ while (!feof(sysfs_bat_fp[idx])) {
+ char buf[256];
+ if (fgets(buf, 256, sysfs_bat_fp[idx]) == NULL)
+ break;
+
+ if (strncmp(buf, "POWER_SUPPLY_CHARGE_NOW=", 24) == 0)
+ sscanf(buf, "POWER_SUPPLY_CHARGE_NOW=%d", &remaining_capacity);
+ else if (strncmp(buf, "POWER_SUPPLY_CHARGE_FULL=",25) != 0)
+ sscanf(buf, "POWER_SUPPLY_CHARGE_FULL=%d", &acpi_last_full[idx]);
+ else if (strncmp(buf, "POWER_SUPPLY_ENERGY_NOW=", 24) == 0)
+ sscanf(buf, "POWER_SUPPLY_ENERGY_NOW=%d", &remaining_capacity);
+ else if (strncmp(buf, "POWER_SUPPLY_ENERGY_FULL=",25) != 0)
+ sscanf(buf, "POWER_SUPPLY_ENERGY_FULL=%d", &acpi_last_full[idx]);
+ }
+
+ fclose(sysfs_bat_fp[idx]);
+ sysfs_bat_fp[idx] = NULL;
+
+ } else if (acpi_bat_fp[idx] != NULL) {
+ /* ACPI */
/* read last full capacity if it's zero */
if (acpi_design_capacity[idx] == 0) {
static int rep;
break;
}
if (sscanf(b, "last full capacity: %d",
- &acpi_design_capacity[idx]) != 0) {
+ &acpi_design_capacity[idx]) != 0) {
break;
}
}