static int read_sysfs_callback (char const *dir, /* {{{ */ char const *power_supply, void *user_data) { int *battery_index = user_data; char const *plugin_instance; char buffer[32]; gauge_t v = NAN; _Bool discharging = 0; int status; /* Ignore non-battery directories, such as AC power. */ status = sysfs_file_to_buffer (dir, power_supply, "type", buffer, sizeof (buffer)); if (status != 0) return (0); if (strcasecmp ("Battery", buffer) != 0) return (0); (void) sysfs_file_to_buffer (dir, power_supply, "status", buffer, sizeof (buffer)); if (strcasecmp ("Discharging", buffer) == 0) discharging = 1; /* FIXME: This is a dirty hack for backwards compatibility: The battery * plugin, for a very long time, has had the plugin_instance * hard-coded to "0". So, to keep backwards compatibility, we'll use * "0" for the first battery we find and the power_supply name for all * following. This should be reverted in a future major version. */ plugin_instance = (*battery_index == 0) ? "0" : power_supply; (*battery_index)++; if (sysfs_file_to_gauge (dir, power_supply, "energy_now", &v) == 0) battery_submit (plugin_instance, "charge", v / 1000000.0); if (sysfs_file_to_gauge (dir, power_supply, "power_now", &v) == 0) { if (discharging) battery_submit (plugin_instance, "power", v / -1000000.0); else battery_submit (plugin_instance, "power", v / 1000000.0); } if (sysfs_file_to_gauge (dir, power_supply, "voltage_now", &v) == 0) battery_submit (plugin_instance, "voltage", v / 1000000.0); #if 0 if (sysfs_file_to_gauge (dir, power_supply, "energy_full_design", &v) == 0) battery_submit (plugin_instance, "charge", v / 1000000.0); if (sysfs_file_to_gauge (dir, power_supply, "energy_full", &v) == 0) battery_submit (plugin_instance, "charge", v / 1000000.0); if (sysfs_file_to_gauge (dir, power_supply, "voltage_min_design", &v) == 0) battery_submit (plugin_instance, "voltage", v / 1000000.0); #endif return (0); } /* }}} int read_sysfs_callback */
static void submit_capacity (char const *plugin_instance, /* {{{ */ gauge_t capacity_charged, gauge_t capacity_full, gauge_t capacity_design) { if (report_percent && (capacity_charged > capacity_full)) return; if (report_degraded && (capacity_full > capacity_design)) return; if (report_percent) { gauge_t capacity_max; if (report_degraded) capacity_max = capacity_design; else capacity_max = capacity_full; battery_submit2 (plugin_instance, "percent", "charged", 100.0 * capacity_charged / capacity_max); battery_submit2 (plugin_instance, "percent", "discharged", 100.0 * (capacity_full - capacity_charged) / capacity_max); if (report_degraded) battery_submit2 (plugin_instance, "percent", "degraded", 100.0 * (capacity_design - capacity_full) / capacity_max); } else if (report_degraded) /* && !report_percent */ { battery_submit2 (plugin_instance, "capacity", "charged", capacity_charged); battery_submit2 (plugin_instance, "capacity", "discharged", (capacity_full - capacity_charged)); battery_submit2 (plugin_instance, "capacity", "degraded", (capacity_design - capacity_full)); } else /* !report_percent && !report_degraded */ { battery_submit (plugin_instance, "capacity", capacity_charged); } } /* }}} void submit_capacity */
static int read_pmu (void) /* {{{ */ { int i; /* The upper limit here is just a safeguard. If there is a system with * more than 100 batteries, this can easily be increased. */ for (i = 0; i < 100; i++) { FILE *fh; char buffer[1024]; char filename[PATH_MAX]; char plugin_instance[DATA_MAX_NAME_LEN]; gauge_t current = NAN; gauge_t voltage = NAN; gauge_t charge = NAN; ssnprintf (filename, sizeof (filename), PROC_PMU_PATH_FORMAT, i); if (access (filename, R_OK) != 0) break; ssnprintf (plugin_instance, sizeof (plugin_instance), "%i", i); fh = fopen (filename, "r"); if (fh == NULL) { if (errno == ENOENT) break; else if ((errno == EAGAIN) || (errno == EINTR)) continue; else return (errno); } while (fgets (buffer, sizeof (buffer), fh) != NULL) { char *fields[8]; int numfields; numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields)); if (numfields < 3) continue; if (strcmp ("current", fields[0]) == 0) strtogauge (fields[2], ¤t); else if (strcmp ("voltage", fields[0]) == 0) strtogauge (fields[2], &voltage); else if (strcmp ("charge", fields[0]) == 0) strtogauge (fields[2], &charge); } fclose (fh); fh = NULL; battery_submit (plugin_instance, "charge", charge / 1000.0); battery_submit (plugin_instance, "current", current / 1000.0); battery_submit (plugin_instance, "voltage", voltage / 1000.0); } if (i == 0) return (ENOENT); return (0); } /* }}} int read_pmu */
static int read_acpi_callback (char const *dir, /* {{{ */ char const *power_supply, void *user_data) { int *battery_index = user_data; gauge_t current = NAN; gauge_t voltage = NAN; gauge_t charge = NAN; _Bool charging = 0; char const *plugin_instance; char filename[PATH_MAX]; char buffer[1024]; FILE *fh; ssnprintf (filename, sizeof (filename), "%s/%s/state", dir, power_supply); fh = fopen (filename, "r"); if ((fh = fopen (filename, "r")) == NULL) { if ((errno == EAGAIN) || (errno == EINTR) || (errno == ENOENT)) return (0); else return (errno); } /* * [11:00] <@tokkee> $ cat /proc/acpi/battery/BAT1/state * [11:00] <@tokkee> present: yes * [11:00] <@tokkee> capacity state: ok * [11:00] <@tokkee> charging state: charging * [11:00] <@tokkee> present rate: 1724 mA * [11:00] <@tokkee> remaining capacity: 4136 mAh * [11:00] <@tokkee> present voltage: 12428 mV */ while (fgets (buffer, sizeof (buffer), fh) != NULL) { char *fields[8]; int numfields; numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields)); if (numfields < 3) continue; if ((strcmp (fields[0], "charging") == 0) && (strcmp (fields[1], "state:") == 0)) { if (strcmp (fields[2], "charging") == 0) charging = 1; else charging = 0; continue; } /* FIXME: The unit of "present rate" depends on the battery. * Modern batteries export watts, not amperes, i.e. it's not a * current anymore. We should check if the fourth column * contains "mA" and only use a current then. Otherwise, export * a power. */ if ((strcmp (fields[0], "present") == 0) && (strcmp (fields[1], "rate:") == 0)) strtogauge (fields[2], ¤t); else if ((strcmp (fields[0], "remaining") == 0) && (strcmp (fields[1], "capacity:") == 0)) strtogauge (fields[2], &charge); else if ((strcmp (fields[0], "present") == 0) && (strcmp (fields[1], "voltage:") == 0)) strtogauge (fields[2], &voltage); } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */ fclose (fh); if (!charging) current *= -1.0; /* FIXME: This is a dirty hack for backwards compatibility: The battery * plugin, for a very long time, has had the plugin_instance * hard-coded to "0". So, to keep backwards compatibility, we'll use * "0" for the first battery we find and the power_supply name for all * following. This should be reverted in a future major version. */ plugin_instance = (*battery_index == 0) ? "0" : power_supply; (*battery_index)++; battery_submit (plugin_instance, "charge", charge / 1000.0); battery_submit (plugin_instance, "current", current / 1000.0); battery_submit (plugin_instance, "voltage", voltage / 1000.0); return 0; } /* }}} int read_acpi_callback */
static int read_acpi_callback(char const *dir, /* {{{ */ char const *power_supply, void *user_data) { int *battery_index = user_data; gauge_t power = NAN; gauge_t voltage = NAN; gauge_t capacity_charged = NAN; gauge_t capacity_full = NAN; gauge_t capacity_design = NAN; _Bool charging = 0; _Bool is_current = 0; char const *plugin_instance; char filename[PATH_MAX]; char buffer[1024]; FILE *fh; ssnprintf(filename, sizeof(filename), "%s/%s/state", dir, power_supply); fh = fopen(filename, "r"); if (fh == NULL) { if ((errno == EAGAIN) || (errno == EINTR) || (errno == ENOENT)) return (0); else return (errno); } /* * [11:00] <@tokkee> $ cat /proc/acpi/battery/BAT1/state * [11:00] <@tokkee> present: yes * [11:00] <@tokkee> capacity state: ok * [11:00] <@tokkee> charging state: charging * [11:00] <@tokkee> present rate: 1724 mA * [11:00] <@tokkee> remaining capacity: 4136 mAh * [11:00] <@tokkee> present voltage: 12428 mV */ while (fgets(buffer, sizeof(buffer), fh) != NULL) { char *fields[8]; int numfields; numfields = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields)); if (numfields < 3) continue; if ((strcmp(fields[0], "charging") == 0) && (strcmp(fields[1], "state:") == 0)) { if (strcmp(fields[2], "charging") == 0) charging = 1; else charging = 0; continue; } /* The unit of "present rate" depends on the battery. Modern * batteries export power (watts), older batteries (used to) * export current (amperes). We check the fourth column and try * to find old batteries this way. */ if ((strcmp(fields[0], "present") == 0) && (strcmp(fields[1], "rate:") == 0)) { strtogauge(fields[2], &power); if ((numfields >= 4) && (strcmp("mA", fields[3]) == 0)) is_current = 1; } else if ((strcmp(fields[0], "remaining") == 0) && (strcmp(fields[1], "capacity:") == 0)) strtogauge(fields[2], &capacity_charged); else if ((strcmp(fields[0], "present") == 0) && (strcmp(fields[1], "voltage:") == 0)) strtogauge(fields[2], &voltage); } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */ fclose(fh); if (!charging) power *= -1.0; /* FIXME: This is a dirty hack for backwards compatibility: The battery * plugin, for a very long time, has had the plugin_instance * hard-coded to "0". So, to keep backwards compatibility, we'll use * "0" for the first battery we find and the power_supply name for all * following. This should be reverted in a future major version. */ plugin_instance = (*battery_index == 0) ? "0" : power_supply; (*battery_index)++; read_acpi_full_capacity(dir, power_supply, &capacity_full, &capacity_design); submit_capacity(plugin_instance, capacity_charged * PROC_ACPI_FACTOR, capacity_full * PROC_ACPI_FACTOR, capacity_design * PROC_ACPI_FACTOR); battery_submit(plugin_instance, is_current ? "current" : "power", power * PROC_ACPI_FACTOR); battery_submit(plugin_instance, "voltage", voltage * PROC_ACPI_FACTOR); return 0; } /* }}} int read_acpi_callback */