#include "batman.h" #include #include #if defined(__OpenBSD__) || defined(__NetBSD__) # include # include #endif EINTERN extern Eina_List *batman_device_batteries; EINTERN extern Eina_List *batman_device_ac_adapters; #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) static Eina_Bool _batman_sysctl_battery_update_poll(void *data); static int _batman_sysctl_battery_update(Instance *inst); #endif int _batman_sysctl_start(Instance *inst) { #if defined(__OpenBSD__) || defined(__NetBSD__) int mib[] = {CTL_HW, HW_SENSORS, 0, 0, 0}; int devn, i = 0; struct sensordev snsrdev; size_t sdlen = sizeof(struct sensordev); char name[256]; #elif defined(__FreeBSD__) || defined(__DragonFly__) size_t len; #endif #if defined(__OpenBSD__) || defined(__NetBSD__) for (devn = 0;; devn++) { mib[2] = devn; if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) { if (errno == ENXIO) continue; if (errno == ENOENT) break; } snprintf(name, sizeof(name), "acpibat%d", i); if (!strcmp(name, snsrdev.xname)) { Battery *bat = E_NEW(Battery, 1); if (!bat) return 0; bat->inst = inst; bat->udi = eina_stringshare_add(name), bat->mib = malloc(sizeof(int) * 5); if (!bat->mib) return 0; bat->mib[0] = mib[0]; bat->mib[1] = mib[1]; bat->mib[2] = mib[2]; bat->technology = eina_stringshare_add("Unknown"); bat->model = eina_stringshare_add("Unknown"); bat->last_update = ecore_time_get(); bat->vendor = eina_stringshare_add("Unknown"); bat->poll = ecore_poller_add(ECORE_POLLER_CORE, inst->cfg->batman.poll_interval, _batman_sysctl_battery_update_poll, inst); batman_device_batteries = eina_list_append(batman_device_batteries, bat); ++i; } if (!strcmp("acpiac0", snsrdev.xname)) { Ac_Adapter *ac = E_NEW(Ac_Adapter, 1); if (!ac) return 0; ac->inst = inst; ac->udi = eina_stringshare_add("acpiac0"); ac->mib = malloc(sizeof(int) * 5); if (!ac->mib) return 0; ac->mib[0] = mib[0]; ac->mib[1] = mib[1]; ac->mib[2] = mib[2]; batman_device_ac_adapters = eina_list_append(batman_device_ac_adapters, ac); } } #elif defined(__FreeBSD__) || defined(__DragonFly__) if ((sysctlbyname("hw.acpi.battery.life", NULL, &len, NULL, 0)) != -1) { Battery *bat = E_NEW(Battery, 1); if (!bat) return 0; bat->inst = inst; bat->mib = malloc(sizeof(int) * 4); if (!bat->mib) return 0; sysctlnametomib("hw.acpi.battery.life", bat->mib, &len); bat->mib_state = malloc(sizeof(int) * 4); if (!bat->mib_state) return 0; sysctlnametomib("hw.acpi.battery.state", bat->mib_state, &len); bat->mib_time = malloc(sizeof(int) * 4); if (!bat->mib_time) return 0; sysctlnametomib("hw.acpi.battery.time", bat->mib_time, &len); bat->mib_units = malloc(sizeof(int) * 4); if(!bat->mib_units) return 0; sysctlnametomib("hw.acpi.battery.units", bat->mib_units, &len); bat->last_update = ecore_time_get(); bat->udi = eina_stringshare_add("hw.acpi.battery"); bat->technology = eina_stringshare_add("Unknown"); bat->model = eina_stringshare_add("Unknown"); bat->vendor = eina_stringshare_add("Unknown"); bat->poll = ecore_poller_add(ECORE_POLLER_CORE, inst->cfg->batman.poll_interval, _batman_sysctl_battery_update_poll, inst); batman_device_batteries = eina_list_append(batman_device_batteries, bat); } if ((sysctlbyname("hw.acpi.acline", NULL, &len, NULL, 0)) != -1) { Ac_Adapter *ac = E_NEW(Ac_Adapter, 1); if (!ac) return 0; ac->inst = inst; ac->mib = malloc(sizeof(int) * 3); if (!ac->mib) return 0; len = sizeof(ac->mib); sysctlnametomib("hw.acpi.acline", ac->mib, &len); ac->udi = eina_stringshare_add("hw.acpi.acline"); batman_device_ac_adapters = eina_list_append(batman_device_ac_adapters, ac); } #endif _batman_sysctl_battery_update(inst); return 1; } void _batman_sysctl_stop(void) { Battery *bat; Ac_Adapter *ac; EINA_LIST_FREE(batman_device_ac_adapters, ac) { E_FREE_FUNC(ac->udi, eina_stringshare_del); E_FREE(ac->mib); E_FREE(ac); } EINA_LIST_FREE(batman_device_batteries, bat) { E_FREE_FUNC(bat->udi, eina_stringshare_del); E_FREE_FUNC(bat->technology, eina_stringshare_del); E_FREE_FUNC(bat->model, eina_stringshare_del); E_FREE_FUNC(bat->vendor, eina_stringshare_del); E_FREE_FUNC(bat->poll, ecore_poller_del); #if defined(__FreeBSD__) || defined(__DragonFly__) E_FREE(bat->mib_state); E_FREE(bat->mib_time); E_FREE(bat->mib_units); #endif E_FREE(bat->mib); E_FREE(bat); } } #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) static Eina_Bool _batman_sysctl_battery_update_poll(void *data) { Instance *inst = data; _batman_sysctl_battery_update(inst); return EINA_TRUE; } #endif static int _batman_sysctl_battery_update(Instance *inst) { Battery *bat; Ac_Adapter *ac; Eina_List *l; #if defined(__OpenBSD__) || defined(__NetBSD__) double _time, charge; struct sensor s; size_t slen = sizeof(struct sensor); #elif defined(__FreeBSD__) || defined(__DragonFly__) double _time; int value; size_t len; #endif EINA_LIST_FOREACH(batman_device_batteries, l, bat) { /* update the poller interval */ ecore_poller_poller_interval_set(bat->poll, inst->cfg->batman.poll_interval); #if defined(__OpenBSD__) || defined(__NetBSD__) /* last full capacity */ bat->mib[3] = 7; bat->mib[4] = 0; if (sysctl(bat->mib, 5, &s, &slen, NULL, 0) != -1) { bat->last_full_charge = (double)s.value; } /* remaining capacity */ bat->mib[3] = 7; bat->mib[4] = 3; if (sysctl(bat->mib, 5, &s, &slen, NULL, 0) != -1) { charge = (double)s.value; } /* This is a workaround because there's an ACPI bug */ if ((EINA_FLT_EQ(charge, 0.0)) || (EINA_FLT_EQ(bat->last_full_charge, 0.0))) { /* last full capacity */ bat->mib[3] = 8; bat->mib[4] = 0; if (sysctl(bat->mib, 5, &s, &slen, NULL, 0) != -1) { bat->last_full_charge = (double)s.value; if (bat->last_full_charge < 0) return EINA_TRUE; } /* remaining capacity */ bat->mib[3] = 8; bat->mib[4] = 3; if (sysctl(bat->mib, 5, &s, &slen, NULL, 0) != -1) { charge = (double)s.value; } } bat->got_prop = 1; _time = ecore_time_get(); if ((bat->got_prop) && (!EINA_FLT_EQ(charge, bat->current_charge))) bat->charge_rate = ((charge - bat->current_charge) / (_time - bat->last_update)); bat->last_update = _time; bat->current_charge = charge; bat->percent = 100 * (bat->current_charge / bat->last_full_charge); if (bat->current_charge >= bat->last_full_charge) bat->percent = 100; if (bat->got_prop) { if (bat->charge_rate > 0) { if (inst->cfg->batman.fuzzy && (++inst->cfg->batman.fuzzcount <= 10) && (bat->time_full > 0)) bat->time_full = (((bat->last_full_charge - bat->current_charge) / bat->charge_rate) + bat->time_full) / 2; else bat->time_full = (bat->last_full_charge - bat->current_charge) / bat->charge_rate; bat->time_left = -1; } else { if (inst->cfg->batman.fuzzy && (inst->cfg->batman.fuzzcount <= 10) && (bat->time_left > 0)) bat->time_left = (((0 - bat->current_charge) / bat->charge_rate) + bat->time_left) / 2; else bat->time_left = (0 - bat->current_charge) / bat->charge_rate; bat->time_full = -1; } } else { bat->time_full = -1; bat->time_left = -1; } /* battery state 1: discharge, 2: charge */ bat->mib[3] = 10; bat->mib[4] = 0; if (sysctl(bat->mib, 5, &s, &slen, NULL, 0) == -1) { if (s.value == 2) bat->charging = 1; else bat->charging = 0; } _batman_device_update(bat->inst); #elif defined(__FreeBSD__) || defined(__DragonFly__) len = sizeof(value); if ((sysctl(bat->mib, 4, &value, &len, NULL, 0)) == -1) { return EINA_FALSE; } bat->percent = value; _time = ecore_time_get(); bat->last_update = _time; len = sizeof(value); if ((sysctl(bat->mib_state, 4, &value, &len, NULL, 0)) == -1) { return EINA_FALSE; } bat->charging = !value; bat->got_prop = 1; bat->time_full = -1; bat->time_left = -1; len = sizeof(bat->time_min); if ((sysctl(bat->mib_time, 4, &bat->time_min, &len, NULL, 0)) == -1) { bat->time_min = -1; } len = sizeof(bat->batteries); if ((sysctl(bat->mib_units, 4, &bat->batteries, &len, NULL, 0)) == -1) { bat->batteries = 1; } if (bat->time_min >= 0) bat->time_left = bat->time_min * 60; if (bat->batteries == 1) bat->time_left = -1; _batman_device_update(inst); #endif } EINA_LIST_FOREACH(batman_device_ac_adapters, l, ac) { #if defined(__OpenBSD__) || defined(__NetBSD__) /* AC State */ ac->mib[3] = 9; ac->mib[4] = 0; if (sysctl(ac->mib, 5, &s, &slen, NULL, 0) != -1) { if (s.value) ac->present = 1; else ac->present = 0; } #elif defined(__FreeBSD__) || defined(__DragonFly__) len = sizeof(value); if ((sysctl(ac->mib, 3, &value, &len, NULL, 0)) != -1) { ac->present = value; } #endif } return EINA_TRUE; }