/* Return a file descriptor for the apm_bios device, or -1 if there is an * error. Is this method secure? Should we make the device in /dev * instead of /tmp? * * apenwarr 2001/05/11: just throw out the weird temporary device file stuff. * It was only for ancient kernel versions anyway. */ int apm_open(void) { int fd; apm_info i; if (access(APM_PROC, R_OK) || apm_read(&i) == 1) return -1; if (i.driver_version[0] >= '1') { if ((fd = open(APM_DEVICE, O_RDWR)) < 0) { /* Try to create it. This is reasonable * for backward compatibility. */ if (mknod(APM_DEVICE, S_IFCHR | S_IRUSR | S_IWUSR, apm_dev())) { unlink(APM_DEVICE); return -1; } fd = open(APM_DEVICE, O_RDWR); } return fd; } return -1; }
/* If APM support of the right version exists in kernel, return zero. * Otherwise, return 1 if no support exists, or 2 if it is the wrong * version. *NOTE* The sense of the return value is not intuitive. */ int apm_exists(void) { apm_info i; if (access(APM_PROC, R_OK)) return 1; return apm_read(&i); }
int apm_init(void) { struct olsr_apm_info ApmInfo; OLSR_PRINTF(3, "Initializing APM\n"); if (apm_read(&ApmInfo) < 0) return -1; apm_printinfo(&ApmInfo); return 0; }
/* * If APM support of the right version exists in kernel, return zero. * Otherwise, return 1 if no support exists, or 2 if it is the wrong * version. *NOTE* The sense of the return value is not intuitive. */ int apm_exists(void) { int fd; apm_info i; /* This will force auto-load of the apm module if necessary. */ fd = open(APM_DEVICE, O_WRONLY); if (fd >= 0) close(fd); if (access(APM_PROC, R_OK)) return 1; return apm_read(&i); }
static const char * apm_readinfo (BatteryStatus *status) { /* Code for Linux by Thomas Hood <*****@*****.**>. apm_read() will read from /proc/... instead and we do not need to open the device ourselves. */ if (DEBUG) g_print("apm_readinfo() (Linux)\n"); /* ACPI support added by Lennart Poettering <*****@*****.**> 10/27/2001 * Updated by David Moore <*****@*****.**> 5/29/2003 to poll less and * use ACPI events. */ if (using_acpi && acpiinfo.event_fd >= 0) { if (acpi_count <= 0) { /* Only call this one out of 30 calls to apm_readinfo() (every 30 seconds) * since reading the ACPI system takes CPU cycles. */ acpi_count=30; acpi_linux_read(&apminfo, &acpiinfo); } acpi_count--; } /* If we lost the file descriptor with ACPI events, try to get it back. */ else if (using_acpi) { if (acpi_linux_init(&acpiinfo)) { acpiwatch = g_io_add_watch (acpiinfo.channel, G_IO_IN | G_IO_ERR | G_IO_HUP, acpi_callback, NULL); acpi_linux_read(&apminfo, &acpiinfo); } } else apm_read(&apminfo); status->present = TRUE; status->on_ac_power = apminfo.ac_line_status ? 1 : 0; status->percent = (guint) apminfo.battery_percentage; status->charging = (apminfo.battery_flags & 0x8) ? TRUE : FALSE; status->minutes = apminfo.battery_time; return NULL; }
/* * Look up the device number of the apm_bios device. */ dev_t apm_dev(void) { FILE *str; static int cached = -1; char buf[80]; char *pt; apm_info i; if (cached >= 0) return cached; if (access(APM_PROC, R_OK) || apm_read(&i) == 1) return cached = -1; if (i.driver_version[0] == '1') return cached = makedev(10, 134); if (!(str = fopen(APM_DEV, "r"))) return -1; while (fgets(buf, sizeof(buf) - 1, str)) { buf[sizeof(buf) - 1] = '\0'; for (pt = buf; *pt && isspace(*pt); ++pt); /* skip leading spaces */ for (; *pt && !isspace(*pt); ++pt); /* find next space */ if (isspace(*pt)) { *pt++ = '\0'; pt[strlen(pt) - 1] = '\0'; /* get rid of newline */ if (!strcmp(pt, APM_NAME)) { fclose(str); return cached = makedev(atoi(buf), 0); } } } fclose(str); return cached = -1; }
void get_power_status(pm_status *power_status) { /* Is this an ACPI system? */ if (pm_type == PM_ACPI) { static ACPIinfo acpiinfo; static ACADstate acadstate; static ACPIstate acpistate; read_acpi_info(&acpiinfo, Battery - 1); read_acpi_state(&acpistate, &acpiinfo, Battery - 1); read_acad_state(&acadstate); /* Check if we are on ac power */ ac_on_line = power_status->ac_on_line = acadstate.state; /* Check to see if we are charging. */ if (acpistate.state == CHARGING) power_status->battery_charging=1; else power_status->battery_charging=0; /* Check battery time and percentage */ power_status->battery_time = acpistate.rtime; power_status->battery_percentage = acpistate.percentage; if (power_status->battery_percentage > 100) power_status->battery_percentage = 100; battery_percentage = power_status->battery_percentage; /* Check if battery is plugged in */ battery_present = power_status->battery_present = acpistate.present; /* Get temperature and fan status */ power_status->fan_status=get_fan_status(); get_temperature(&(power_status->temperature), &(power_status->temp_is_celsius)); if (fast_charge_mode && (power_status->battery_percentage == 100)) fast_battery_charge(0); /* Let's see wether we failed to get battery time */ if (battery_present && (battery_percentage < 100) && (power_status->battery_time <= 0)) { /* OK, we failed, we calculate the value ourselves */ power_status->battery_time = calculate_battery_time(battery_percentage, ac_on_line); } return; } /* Is this an APM system? */ if (pm_type == PM_APM) { struct_apm_data apm_data; if (!apm_read(&apm_data)) { fprintf(stderr, "Could not read APM info!\n"); return; } ac_on_line = power_status->ac_on_line = apm_data.ac_line_status; if ( apm_data.battery_percentage == -1) { battery_present = power_status->battery_present = 0; battery_percentage = power_status->battery_percentage = 0; } else { battery_present = power_status->battery_present = 1; power_status->battery_percentage = apm_data.battery_percentage; if (power_status->battery_percentage > 100) power_status->battery_percentage = 100; battery_percentage = power_status->battery_percentage; } if ( (int)(apm_data.battery_status) == 3) power_status->battery_charging=1; else power_status->battery_charging=0; power_status->battery_time = (apm_data.using_minutes) ? apm_data.battery_time : apm_data.battery_time / 60; power_status->fan_status=get_fan_status(); get_temperature(&(power_status->temperature), &(power_status->temp_is_celsius)); if (fast_charge_mode && (power_status->battery_percentage == 100)) fast_battery_charge(0); return; } }
static gboolean update_apm_status(t_battmon *battmon) { #ifdef __OpenBSD__ struct apm_power_info apm; #else struct apm_info apm; #endif int charge; int time_remaining; gboolean acline; gchar buffer[128]; if(battmon->method == BM_BROKEN) { /* See if ACPI or APM support has been enabled yet */ if(!detect_battery_info(battmon)) return TRUE; if(battmon->timeoutid != 0) g_source_remove(battmon->timeoutid); /* Poll only once per minute if using ACPI due to a bug */ if(battmon->method == BM_USE_ACPI) { battmon->timeoutid = g_timeout_add(60 * 1000, (GSourceFunc) update_apm_status, battmon); } else { battmon->timeoutid = g_timeout_add(2 * 1000, (GSourceFunc) update_apm_status, battmon); } } /* Show initial state if using ACPI rather than waiting a minute */ if(battmon->flag) { battmon->flag = FALSE; g_source_remove(battmon->timeoutid); battmon->timeoutid = g_timeout_add(60 * 1000, (GSourceFunc) update_apm_status, battmon); } #ifdef __FreeBSD__ /* This is how I read the information from the APM subsystem under FreeBSD. Each time this functions is called (once every second) the APM device is opened, read from and then closed. */ int fd; battmon->method = BM_BROKEN; fd = open(APMDEVICE, O_RDONLY); if (fd == -1) return TRUE; if (ioctl(fd, APMIO_GETINFO, &apm) == -1) return TRUE; close(fd); acline = apm.ai_acline ? TRUE : FALSE; time_remaining = apm.ai_batt_time; time_remaining = time_remaining / 60; /* convert from seconds to minutes */ charge = apm.ai_batt_life; #elif __OpenBSD__ /* Code for OpenBSD by Joe Ammond <*****@*****.**>. Using the same procedure as for FreeBSD. */ int fd; battmon->method = BM_BROKEN; fd = open(APMDEVICE, O_RDONLY); if (fd == -1) return TRUE; if (ioctl(fd, APM_IOC_GETPOWER, &apminfo) == -1) return TRUE; close(fd); charge = apm.battery_life; time_remaining = apm.minutes_left; acline = apm.ac_state ? TRUE : FALSE; #elif __linux__ if(battmon->method == BM_USE_ACPI) acpi_linux_read(&apm); else apm_read(&apm); /* not broken and not using ACPI, assume APM */ charge = apm.battery_percentage; if(battmon->method == BM_USE_ACPI) time_remaining = 0; /* no such info for ACPI :( */ else time_remaining = apm.battery_time; acline = apm.ac_line_status ? TRUE : FALSE; #endif if(charge < 0) charge = 0; gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(battmon->battstatus), charge / 100.0); if(battmon->options.tooltip_display_percentage && battmon->options.tooltip_display_time) { if(acline) g_snprintf(buffer, sizeof(buffer), _("%d%% (AC on-line)"), charge); else if(time_remaining > 0) g_snprintf(buffer, sizeof(buffer), _("%d%% (%d:%.2d) remaining"), charge, time_remaining / 60, time_remaining % 60); else g_snprintf(buffer, sizeof(buffer), _("%d%% (AC off-line)"), charge); add_tooltip(battmon->ebox, buffer); } else if(battmon->options.tooltip_display_percentage) { g_snprintf(buffer, sizeof(buffer), _("%d%%"), charge); add_tooltip(battmon->ebox, buffer); } else if(battmon->options.tooltip_display_time) { if(acline) g_snprintf(buffer, sizeof(buffer), _("AC on-line")); else if(time_remaining > 0) g_snprintf(buffer, sizeof(buffer), _("%d:%.2d remaining"), time_remaining / 60, time_remaining % 60); else g_snprintf(buffer, sizeof(buffer), _("AC off-line")); add_tooltip(battmon->ebox, buffer); } else add_tooltip(battmon->ebox, NULL); if(battmon->options.display_percentage) { g_snprintf(buffer, sizeof(buffer), _("%d%%"), charge); gtk_progress_bar_set_text(GTK_PROGRESS_BAR(battmon->battstatus), buffer); } else gtk_progress_bar_set_text(GTK_PROGRESS_BAR(battmon->battstatus), NULL); if(!battmon->critical && charge <= battmon->options.critical_percentage) { battmon->critical = TRUE; battmon->low = TRUE; if(battmon->options.action_on_critical == BM_MESSAGE) xfce_warn(_("WARNING: Your battery has reached critical status. You should plug in or shutdown your computer now to avoid possible data loss.")); if(battmon->options.action_on_critical == BM_COMMAND) { if(battmon->options.command_on_critical && battmon->options.command_on_critical[0]) exec_cmd(battmon->options.command_on_critical, 0, 0); } if(battmon->options.action_on_critical == BM_COMMAND_TERM) { if(battmon->options.command_on_critical && battmon->options.command_on_critical[0]) exec_cmd(battmon->options.command_on_critical, 1, 0); } } else if(battmon->critical && charge > battmon->options.critical_percentage) battmon->critical = FALSE; if(!battmon->low && charge <= battmon->options.low_percentage) { battmon->low = TRUE; if(battmon->options.action_on_low == BM_MESSAGE) xfce_warn(_("WARNING: Your battery is running low. You should consider plugging in or shutting down your computer soon to avoid possible data loss.")); if(battmon->options.action_on_low == BM_COMMAND) { if(battmon->options.command_on_low && battmon->options.command_on_low[0]) exec_cmd(battmon->options.command_on_low, 0, 0); } if(battmon->options.action_on_low == BM_COMMAND_TERM) { if(battmon->options.command_on_low && battmon->options.command_on_low[0]) exec_cmd(battmon->options.command_on_low, 1, 0); } } else if(battmon->low && charge > battmon->options.low_percentage) battmon->low = FALSE; return TRUE; }
gboolean detect_battery_info(t_battmon *battmon) { #ifdef __OpenBSD__ struct apm_power_info apm; #else struct apm_info apm; #endif #ifdef __FreeBSD__ /* This is how I read the information from the APM subsystem under FreeBSD. Each time this functions is called (once every second) the APM device is opened, read from and then closed. */ int fd; battmon->method = BM_BROKEN; fd = open(APMDEVICE, O_RDONLY); if (fd == -1) return FALSE; if (ioctl(fd, APMIO_GETINFO, &apm) == -1) return FALSE; close(fd); battmon->method = BM_USE_APM; return TRUE; #elif __OpenBSD__ /* Code for OpenBSD by Joe Ammond <*****@*****.**>. Using the same procedure as for FreeBSD. */ int fd; battmon->method = BM_BROKEN; fd = open(APMDEVICE, O_RDONLY); if (fd == -1) return FALSE; if (ioctl(fd, APM_IOC_GETPOWER, &apm) == -1) return FALSE; close(fd); battmon->method = BM_USE_APM; return TRUE; #elif __linux__ /* First check to see if ACPI is available */ if(acpi_linux_read(&apm)) { /* ACPI detected and working */ battmon->method = BM_USE_ACPI; return TRUE; } if(apm_read(&apm) == 0) { /* ACPI not detected, but APM works */ battmon->method = BM_USE_APM; return TRUE; } /* Neither ACPI or APM detected/working */ battmon->method = BM_BROKEN; return FALSE; #endif }
void main_loop (void) { int activity=0, sleep_now=0, total_unused=0; int sleep_battery=0; int prev_ac_line_status=0; time_t nowtime, oldtime=0; apm_info ai; double loadavg[1]; if (use_events) { pthread_t emthread; pthread_create(&emthread, NULL, eventMonitor, NULL); } while (1) { activity=0; if (use_events) { pthread_mutex_lock(&condition_mutex); pthread_cond_signal(&condition_cond); pthread_mutex_unlock(&condition_mutex); } if (use_acpi) { acpi_read(1, &ai); } #ifdef HAL else if (use_simplehal) { simplehal_read(1, &ai); } #endif else { apm_read(&ai); } if (min_batt != -1 && ai.ac_line_status != 1 && ai.battery_percentage < min_batt && ai.battery_status != BATTERY_STATUS_ABSENT) { sleep_battery = 1; } if (sleep_battery && ! require_unused_and_battery) { syslog(LOG_NOTICE, "battery level %d%% is below %d%%; forcing hibernation", ai.battery_percentage, min_batt); if (system(hibernate_command) != 0) syslog(LOG_ERR, "%s failed", hibernate_command); /* This counts as activity; to prevent double sleeps. */ if (debug) printf("sleepd: activity: just woke up\n"); activity=1; oldtime=0; sleep_battery=0; } /* Rest is only needed if sleeping on inactivity. */ if (! max_unused && ! ac_max_unused) { sleep(sleep_time); continue; } if (autoprobe || have_irqs) { activity=check_irqs(activity, autoprobe); } if (use_net) { activity=check_net(activity); } if ((max_loadavg != 0) && (getloadavg(loadavg, 1) == 1) && (loadavg[0] >= max_loadavg)) { /* If the load average is too high */ if (debug) printf("sleepd: activity: load average %f\n", loadavg[0]); activity=1; } if (use_utmp == 1) { total_unused=check_utmp(total_unused); } if (ai.ac_line_status != prev_ac_line_status) { /* AC plug/unplug counts as activity. */ if (debug) printf("sleepd: activity: AC status change\n"); activity=1; } prev_ac_line_status=ai.ac_line_status; sleep(sleep_time); if (use_events) { pthread_mutex_lock(&activity_mutex); if (eventData.emactivity == 1) { if (debug) printf("sleepd: activity: keyboard/mouse events\n"); activity=1; } pthread_mutex_unlock(&activity_mutex); } if (activity) { total_unused = 0; } else { total_unused += sleep_time; if (ai.ac_line_status == 1) { /* On wall power. */ if (ac_max_unused > 0) { sleep_now = total_unused >= ac_max_unused; } } else if (max_unused > 0) { sleep_now = total_unused >= max_unused; } if (sleep_now && ! no_sleep && ! require_unused_and_battery) { syslog(LOG_NOTICE, "system inactive for %ds; forcing sleep", total_unused); if (system(sleep_command) != 0) syslog(LOG_ERR, "%s failed", sleep_command); total_unused=0; oldtime=0; sleep_now=0; } else if (sleep_now && ! no_sleep && sleep_battery) { syslog(LOG_NOTICE, "system inactive for %ds and battery level %d%% is below %d%%; forcing hibernaton", total_unused, ai.battery_percentage, min_batt); if (system(hibernate_command) != 0) syslog(LOG_ERR, "%s failed", hibernate_command); total_unused=0; oldtime=0; sleep_now=0; sleep_battery=0; } } /* * Keep track of how long it's been since we were last * here. If it was much longer than sleep_time, the system * was probably suspended, or this program was, (or the * kernel is thrashing :-), so clear idle counter. */ nowtime=time(NULL); /* The 1 is a necessary fudge factor. */ if (oldtime && nowtime - sleep_time > oldtime + 1) { no_sleep=0; /* reset, since they must have put it to sleep */ writecontrol(no_sleep); syslog(LOG_NOTICE, "%i sec sleep; resetting timer", (int)(nowtime - oldtime)); total_unused=0; } oldtime=nowtime; } }