/* reads values for thermal_zone num, return 0 on success, negative values on error */ int read_acpi_zone(const int num, global_t *globals){ char *buf = NULL; char *tmp = NULL; thermal_t *info = &thermals[num]; if(num > MAX_ITEMS) return ITEM_EXCEED; /* scan state file */ if((buf = get_acpi_content(info->state_file)) == NULL) info->therm_state = T_ERR; if(buf && (tmp = scan_acpi_value(buf, "state:"))) thermal_state(tmp, info); free(tmp); free(buf); /* scan temperature file */ if((buf = get_acpi_content(info->temp_file)) == NULL) info->temperature = NOT_SUPPORTED; if(buf && (tmp = scan_acpi_value(buf, "temperature:"))){ info->temperature = strtol(tmp, NULL, 10); /* if we just have one big thermal zone, this will be the global temperature */ if(globals->thermal_count == 1) globals->temperature = info->temperature; } free(tmp); free(buf); /* scan cooling mode file */ if((buf = get_acpi_content(info->cooling_file)) == NULL) info->therm_mode = CO_ERR; if(buf && (tmp = scan_acpi_value(buf, "cooling mode:"))) fill_cooling_mode(tmp, info); else info->therm_mode = CO_ERR; free(tmp); free(buf); /* scan polling_frequencies file */ if((buf = get_acpi_content(info->freq_file)) == NULL) info->frequency = DISABLED; if(buf && (tmp = scan_acpi_value(buf, "polling frequency:"))) info->frequency = strtol(tmp, NULL, 10); else info->frequency = DISABLED; free(tmp); free(buf); /* TODO: IMPLEMENT TRIP POINTS FILE */ return SUCCESS; }
/* returns the acpi version or NOT_SUPPORTED(negative value) on failure */ static int get_acpi_version(void){ long ret = -1; char *tmp = get_acpi_content(PROC_ACPI "info"); char *version = NULL; if(!tmp) { tmp = get_acpi_content("/sys/module/acpi/parameters/acpica_version"); if (tmp) { long ret = strtol(tmp, NULL, 10); free(tmp); return ret; } else { return NOT_SUPPORTED; } } if((version = scan_acpi_value(tmp, "version:")) == NULL){ free(tmp); return NOT_SUPPORTED; } ret = strtol(version, NULL, 10); free(tmp); free(version); return ret; }
/* read alarm capacity, return 0 on success, negative values on error */ static int read_acpi_battalarm(const int num, const int sysstyle){ char *buf = NULL; char *tmp = NULL; battery_t *info = &batteries[num]; if((buf = get_acpi_content(info->alarm_file)) == NULL) return NOT_SUPPORTED; if(sysstyle) { if(!strcmp(buf, "0")) info->alarm = 0; else if(!strcmp(buf, "1")) info->alarm = 1; else info->alarm = NOT_SUPPORTED; } else { if((tmp = scan_acpi_value(buf, "alarm:")) && tmp[0] != 'u') info->alarm = strtol(tmp, NULL, 10); else info->alarm = NOT_SUPPORTED; } free(buf); free(tmp); return SUCCESS; }
/* reads the acpi state and writes it into the globals structure, void */ void read_acpi_acstate(global_t *globals){ adapter_t *ac = &globals->adapt; char *buf = NULL; char *tmp = NULL; if(ac->state_file && (buf = get_acpi_content(ac->state_file)) == NULL){ ac->ac_state = P_ERR; return; } if(globals->sysstyle) { if(!strcmp(buf, "1")) ac->ac_state = P_AC; else if(!strcmp(buf, "0")) ac->ac_state = P_BATT; else ac->ac_state = P_ERR; } else { if((tmp = scan_acpi_value(buf, "state:")) && !strncmp(tmp, "on-line", 7)) ac->ac_state = P_AC; else if(tmp && !strncmp(tmp, "off-line", 8)) ac->ac_state = P_BATT; else ac->ac_state = P_ERR; } free(buf); free(tmp); }
/* read acpi information for fan num, returns 0 on success and negative values on errors */ int read_acpi_fan(const int num){ char *buf = NULL; char *tmp = NULL; fan_t *info = &fans[num]; if(num > MAX_ITEMS) return ITEM_EXCEED; /* scan state file */ if((buf = get_acpi_content(info->state_file)) == NULL) info->fan_state = F_ERR; if(!buf || (tmp = scan_acpi_value(buf, "status:")) == NULL){ info->fan_state = F_ERR; return NOT_SUPPORTED; } if (tmp[0] == 'o' && tmp[1] == 'n') info->fan_state = F_ON; else if(tmp[0] == 'o' && tmp[1] == 'f') info->fan_state = F_OFF; else info->fan_state = F_ERR; free(buf); free(tmp); return SUCCESS; }
/* reads static values for a battery (info file), returns SUCCESS */ static int read_acpi_battinfo(const int num, const int sysstyle){ char *buf = NULL; char *tmp = NULL; battery_t *info = &batteries[num]; int i = 0; char sysfile[MAX_NAME]; if(sysstyle) { snprintf(sysfile, MAX_NAME, "%s/present", info->info_file); if((buf = get_acpi_content(sysfile)) == NULL) return NOT_SUPPORTED; if(!strcmp(buf, "1")) { info->present = 1; } else { info->present = 0; return NOT_PRESENT; } free(buf); snprintf(sysfile, MAX_NAME, "%s/charge_full_design", info->info_file); if((buf = get_acpi_content(sysfile)) == NULL) return NOT_SUPPORTED; info->design_cap = strtol(buf, NULL, 10); free(buf); snprintf(sysfile, MAX_NAME, "%s/charge_full", info->info_file); if((buf = get_acpi_content(sysfile)) == NULL) return NOT_SUPPORTED; info->last_full_cap = strtol(buf, NULL, 10); free(buf); snprintf(sysfile, MAX_NAME, "%s/charge_now", info->info_file); if((buf = get_acpi_content(sysfile)) == NULL) return NOT_SUPPORTED; info->remaining_cap = strtol(buf, NULL, 10); free(buf); snprintf(sysfile, MAX_NAME, "%s/voltage_min_design", info->info_file); if((buf = get_acpi_content(sysfile)) == NULL) return NOT_SUPPORTED; info->design_voltage = strtol(buf, NULL, 10); free(buf); snprintf(sysfile, MAX_NAME, "%s/voltage_now", info->info_file); if((buf = get_acpi_content(sysfile)) == NULL) return NOT_SUPPORTED; info->present_voltage = strtol(buf, NULL, 10); free(buf); /* FIXME: is rate == current here? */ snprintf(sysfile, MAX_NAME, "%s/current_now", info->info_file); if((buf = get_acpi_content(sysfile)) == NULL) return NOT_SUPPORTED; info->present_rate = strtol(buf, NULL, 10); free(buf); return SUCCESS; } if((buf = get_acpi_content(info->info_file)) == NULL) return NOT_SUPPORTED; /* you have to read the present value always since a battery can be taken away while * refreshing the data */ if((tmp = scan_acpi_value(buf, "present:")) && !strncmp(tmp, "yes", 3)) { free(tmp); info->present = 1; } else { info->present = 0; free(buf); return NOT_PRESENT; } if((tmp = scan_acpi_value(buf, "design capacity:")) && tmp[0] != 'u'){ info->design_cap = strtol(tmp, NULL, 10); /* workaround ACPI's broken way of reporting no battery */ if(info->design_cap == 655350) info->design_cap = NOT_SUPPORTED; free(tmp); } else info->design_cap = NOT_SUPPORTED; for (;battinfo_values[i].value; i++) { if ((tmp = scan_acpi_value(buf, battinfo_values[i].value)) && tmp[0] != 'u') { *((int *)(((char *)info) + battinfo_values[i].offset)) = strtol(tmp, NULL, 10); free(tmp); } else { *((int *)(((char *)info) + battinfo_values[i].offset)) = NOT_SUPPORTED; } } /* TODO remove debug */ /* printf("%s\n", buf); */ free(buf); return SUCCESS; }
/* Read ACPI info on a given power adapter and battery, and fill the passed * apm_info struct. */ int acpi_read (int battery, apm_info *info) { char *buf, *state; if (acpi_batt_count == 0) { info->battery_percentage = 0; info->battery_time = 0; info->battery_status = BATTERY_STATUS_ABSENT; acpi_batt_capacity[battery] = 0; /* Where else would the power come from, eh? ;-) */ info->ac_line_status = 1; return 0; } /* Internally it's zero indexed. */ battery--; buf = get_acpi_file(acpi_batt_info[battery]); if (buf == NULL) { fprintf(stderr, "unable to read %s\n", acpi_batt_info[battery]); perror("read"); exit(1); } info->ac_line_status = 0; info->battery_flags = 0; info->using_minutes = 1; /* Work out if the battery is present, and what percentage of full * it is and how much time is left. */ if (strcmp(scan_acpi_value(buf, acpi_labels[label_present]), "1") == 0) { int pcap = scan_acpi_num(buf, acpi_labels[label_remaining_capacity]); int rate = scan_acpi_num(buf, acpi_labels[label_present_rate]); if (rate) { /* time remaining = (current_capacity / discharge rate) */ info->battery_time = (float) pcap / (float) rate * 60; } else { char *rate_s = scan_acpi_value(buf, acpi_labels[label_present_rate]); if (! rate_s) { /* Time remaining unknown. */ info->battery_time = 0; } else { /* a zero or unknown in the file; time * unknown so use a negative one to * indicate this */ info->battery_time = -1; } } state = scan_acpi_value(buf, acpi_labels[label_charging_state]); if (state) { if (state[0] == 'D') { /* discharging */ info->battery_status = BATTERY_STATUS_CHARGING; /* Expensive ac power check used here * because AC power might be on even if a * battery is discharging in some cases. */ info->ac_line_status = on_ac_power(); } else if (state[0] == 'C' && state[1] == 'h') { /* charging */ info->battery_status = BATTERY_STATUS_CHARGING; info->ac_line_status = 1; info->battery_flags = info->battery_flags | BATTERY_FLAGS_CHARGING; if (rate) info->battery_time = -1 * (float) (acpi_batt_capacity[battery] - pcap) / (float) rate * 60; else info->battery_time = 0; if (abs(info->battery_time) < 0.5) info->battery_time = 0; } else if (state[0] == 'F') { /* full */ /* charged, on ac power */ info->battery_status = BATTERY_STATUS_HIGH; info->ac_line_status = 1; } else if (state[0] == 'C') { /* not charging, so must be critical */ info->battery_status = BATTERY_STATUS_CRITICAL; /* Expensive ac power check used here * because AC power might be on even if a * battery is critical in some cases. */ info->ac_line_status = on_ac_power(); } else if (state[0] == 'U') { /* unknown */ info->ac_line_status = on_ac_power(); int current = scan_acpi_num(buf, acpi_labels[label_present_rate]); if (info->ac_line_status) { if (current == 0) info->battery_status = BATTERY_STATUS_HIGH; else info->battery_status = BATTERY_STATUS_CHARGING; } else { info->battery_status = BATTERY_STATUS_CHARGING; } } else { fprintf(stderr, "unknown battery state: %s\n", state); } } else { /* Battery state unknown. */ info->battery_status = BATTERY_STATUS_ABSENT; } if (acpi_batt_capacity[battery] == 0) { /* The battery was absent, and now is present. * Well, it might be a different battery. So * re-probe the battery. */ /* NOTE that this invalidates buf. No accesses of * buf below this point! */ acpi_batt_capacity[battery] = get_acpi_batt_capacity(battery); } else if (pcap > acpi_batt_capacity[battery]) { /* Battery is somehow charged to greater than max * capacity. Rescan for a new max capacity. */ find_batteries(); } if (pcap && acpi_batt_capacity[battery]) { info->battery_percentage = (long) 100 * pcap / acpi_batt_capacity[battery]; if (info->battery_percentage > 100) info->battery_percentage = 100; } else { info->battery_percentage = -1; } } else { info->battery_percentage = 0; info->battery_time = 0; info->battery_status = BATTERY_STATUS_ABSENT; acpi_batt_capacity[battery] = 0; if (acpi_batt_count == 0) { /* Where else would the power come from, eh? ;-) */ info->ac_line_status = 1; } else { /* Expensive ac power check. */ info->ac_line_status = on_ac_power(); } } return 0; }
/* Read an ACPI proc file, pull out the requested piece of information, and * return it (statically allocated string). Returns NULL on error, This is * the slow, dumb way, fine for initialization or if only one value is needed * from a file, slow if called many times. */ char *get_acpi_value (const char *file, const char *key) { char *buf = get_acpi_file(file); if (! buf) return NULL; return scan_acpi_value(buf, key); }