Enlightenment: Sysinfo gadget supporting files

This commit is contained in:
Stephen 'Okra' Houston 2017-01-06 16:15:30 -06:00
parent cd24662e9f
commit b51b591171
24 changed files with 5872 additions and 0 deletions

View File

@ -0,0 +1,561 @@
#include "batman.h"
Eina_Bool upower;
Eina_List *batman_device_batteries;
Eina_List *batman_device_ac_adapters;
double batman_init_time;
static Eina_Bool _batman_cb_warning_popup_timeout(void *data);
static void _batman_cb_warning_popup_hide(void *data, Evas *e, Evas_Object *obj, void *event);
static void _batman_warning_popup_destroy(Instance *inst);
static void _batman_warning_popup(Instance *inst, int time, double percent);
Battery *
_batman_battery_find(const char *udi)
{
Eina_List *l;
Battery *bat;
EINA_LIST_FOREACH(batman_device_batteries, l, bat)
{ /* these are always stringshared */
if (udi == bat->udi) return bat;
}
return NULL;
}
Ac_Adapter *
_batman_ac_adapter_find(const char *udi)
{
Eina_List *l;
Ac_Adapter *ac;
EINA_LIST_FOREACH(batman_device_ac_adapters, l, ac)
{ /* these are always stringshared */
if (udi == ac->udi) return ac;
}
return NULL;
}
static void
_batman_face_level_set(Evas_Object *battery, double level)
{
Edje_Message_Float msg;
char buf[256];
snprintf(buf, sizeof(buf), "%i", (int)(level * 100.0));
elm_layout_text_set(battery, "e.text.reading", buf);
if (level < 0.0) level = 0.0;
else if (level > 1.0)
level = 1.0;
msg.val = level;
edje_object_message_send(elm_layout_edje_get(battery), EDJE_MESSAGE_FLOAT, 1, &msg);
}
static void
_batman_face_time_set(Evas_Object *battery, int t)
{
char buf[256];
int hrs, mins;
if (t < 0) return;
hrs = (t / 3600);
mins = ((t) / 60 - (hrs * 60));
if (mins < 0) mins = 0;
snprintf(buf, sizeof(buf), "%i:%02i", hrs, mins);
elm_layout_text_set(battery, "e.text.time", buf);
}
void
_batman_update(Instance *inst, int full, int time_left, int time_full, Eina_Bool have_battery, Eina_Bool have_power)
{
static double debounce_time = 0.0;
if (!inst) return;
if (inst->cfg->esm != E_SYSINFO_MODULE_BATMAN && inst->cfg->esm != E_SYSINFO_MODULE_SYSINFO) return;
if (!inst->cfg) return;
if (have_power != inst->cfg->batman.have_power)
{
if (have_power && (full < 100))
elm_layout_signal_emit(inst->cfg->batman.o_gadget,
"e,state,charging",
"e");
else
{
elm_layout_signal_emit(inst->cfg->batman.o_gadget,
"e,state,discharging",
"e");
if (inst->popup_battery)
elm_layout_signal_emit(inst->popup_battery,
"e,state,discharging", "e");
}
}
if (have_battery)
{
if (inst->cfg->batman.full != full)
{
double val;
if (full >= 100) val = 1.0;
else val = (double)full / 100.0;
_batman_face_level_set(inst->cfg->batman.o_gadget, val);
if (inst->popup_battery)
_batman_face_level_set(inst->popup_battery, val);
}
}
else
{
_batman_face_level_set(inst->cfg->batman.o_gadget, 0.0);
elm_layout_text_set(inst->cfg->batman.o_gadget,
"e.text.reading",
_("N/A"));
}
if ((time_full < 0) && (time_left != inst->cfg->batman.time_left))
{
_batman_face_time_set(inst->cfg->batman.o_gadget, time_left);
if (inst->popup_battery)
_batman_face_time_set(inst->popup_battery,
time_left);
}
else if ((time_left < 0) && (time_full != inst->cfg->batman.time_full))
{
_batman_face_time_set(inst->cfg->batman.o_gadget, time_full);
if (inst->popup_battery)
_batman_face_time_set(inst->popup_battery,
time_full);
}
if (have_battery &&
(!have_power) &&
(full < 100) &&
(
(
(time_left > 0) &&
inst->cfg->batman.alert &&
((time_left / 60) <= inst->cfg->batman.alert)
) ||
(
inst->cfg->batman.alert_p &&
(full <= inst->cfg->batman.alert_p)
)
)
)
{
double t;
printf("-------------------------------------- bat warn .. why below\n");
printf("have_battery = %i\n", (int)have_battery);
printf("have_power = %i\n", (int)have_power);
printf("full = %i\n", (int)full);
printf("time_left = %i\n", (int)time_left);
printf("inst->cfg->batman.alert = %i\n", (int)inst->cfg->batman.alert);
printf("inst->cfg->batman.alert_p = %i\n", (int)inst->cfg->batman.alert_p);
t = ecore_time_get();
if ((t - debounce_time) > 30.0)
{
printf("t-debounce = %3.3f\n", (t - debounce_time));
debounce_time = t;
if ((t - batman_init_time) > 5.0)
_batman_warning_popup(inst, time_left, (double)full / 100.0);
}
}
else if (have_power || ((time_left / 60) > inst->cfg->batman.alert))
_batman_warning_popup_destroy(inst);
if ((have_battery) && (!have_power) && (full >= 0) &&
(inst->cfg->batman.suspend_below > 0) &&
(full < inst->cfg->batman.suspend_below))
{
if (inst->cfg->batman.suspend_method == SUSPEND)
e_sys_action_do(E_SYS_SUSPEND, NULL);
else if (inst->cfg->batman.suspend_method == HIBERNATE)
e_sys_action_do(E_SYS_HIBERNATE, NULL);
else if (inst->cfg->batman.suspend_method == SHUTDOWN)
e_sys_action_do(E_SYS_HALT, NULL);
}
inst->cfg->batman.full = full;
inst->cfg->batman.time_left = time_left;
inst->cfg->batman.have_battery = have_battery;
inst->cfg->batman.have_power = have_power;
if (!have_battery)
e_powersave_mode_set(E_POWERSAVE_MODE_LOW);
else
{
if (have_power)
e_powersave_mode_set(E_POWERSAVE_MODE_LOW);
else if (full > 95)
e_powersave_mode_set(E_POWERSAVE_MODE_MEDIUM);
else if (full > 30)
e_powersave_mode_set(E_POWERSAVE_MODE_HIGH);
else
e_powersave_mode_set(E_POWERSAVE_MODE_EXTREME);
}
}
void
_batman_device_update(Instance *inst)
{
Eina_List *l;
Battery *bat;
Ac_Adapter *ac;
int full = -1;
int time_left = -1;
int time_full = -1;
int have_battery = 0;
int have_power = 0;
int charging = 0;
int batnum = 0;
int acnum = 0;
EINA_LIST_FOREACH(batman_device_ac_adapters, l, ac)
if (ac->present) acnum++;
EINA_LIST_FOREACH(batman_device_batteries, l, bat)
{
if (!bat->got_prop)
continue;
have_battery = 1;
batnum++;
if (bat->charging == 1) have_power = 1;
if (full == -1) full = 0;
if (bat->percent >= 0)
full += bat->percent;
else if (bat->last_full_charge > 0)
full += (bat->current_charge * 100) / bat->last_full_charge;
else if (bat->design_charge > 0)
full += (bat->current_charge * 100) / bat->design_charge;
if (bat->time_left > 0)
{
if (time_left < 0) time_left = bat->time_left;
else time_left += bat->time_left;
}
if (bat->time_full > 0)
{
if (time_full < 0) time_full = bat->time_full;
else time_full += bat->time_full;
}
charging += bat->charging;
}
if ((batman_device_batteries) && (batnum == 0))
return; /* not ready yet, no properties received for any battery */
if (batnum > 0) full /= batnum;
if ((full == 100) && have_power)
{
time_left = -1;
time_full = -1;
}
if (time_left < 1) time_left = -1;
if (time_full < 1) time_full = -1;
_batman_update(inst, full, time_left, time_full, have_battery, have_power);
}
void
_batman_config_updated(Instance *inst)
{
int ok = 0;
if (!inst->cfg) return;
if ((inst->cfg->batman.force_mode == UNKNOWN) ||
(inst->cfg->batman.force_mode == SUBSYSTEM))
{
#ifdef HAVE_EEZE
ok = _batman_udev_start(inst);
#elif defined __OpenBSD__ || defined __DragonFly__ || defined __FreeBSD__ || defined __NetBSD__
ok = _batman_sysctl_start(inst);
#else
ok = _batman_upower_start();
if (ok)
upower = EINA_TRUE;
#endif
}
if (ok) return;
if ((inst->cfg->batman.force_mode == UNKNOWN) ||
(inst->cfg->batman.force_mode == NOSUBSYSTEM))
{
ok = _batman_fallback_start(inst);
}
}
static void _warning_popup_dismissed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Instance *inst = data;
E_FREE_FUNC(inst->popup_battery, evas_object_del);
E_FREE_FUNC(inst->warning, evas_object_del);
}
static Eina_Bool
_batman_cb_warning_popup_timeout(void *data)
{
Instance *inst;
inst = data;
elm_ctxpopup_dismiss(inst->warning);
inst->cfg->batman.alert_timer = NULL;
return ECORE_CALLBACK_CANCEL;
}
static void
_batman_cb_warning_popup_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
Instance *inst = NULL;
inst = (Instance *)data;
if ((!inst) || (!inst->warning)) return;
elm_ctxpopup_dismiss(inst->warning);
}
static void
_batman_warning_popup_destroy(Instance *inst)
{
if (inst->cfg->batman.alert_timer)
{
ecore_timer_del(inst->cfg->batman.alert_timer);
inst->cfg->batman.alert_timer = NULL;
}
if ((!inst) || (!inst->warning)) return;
elm_ctxpopup_dismiss(inst->warning);
}
static void
_batman_warning_popup_cb(void *data, unsigned int id)
{
Instance *inst = data;
inst->notification_id = id;
}
static void
_batman_warning_popup(Instance *inst, int t, double percent)
{
Evas_Object *popup_bg = NULL;
int x, y, w, h;
if ((!inst) || (inst->warning)) return;
if (inst->cfg->batman.desktop_notifications)
{
E_Notification_Notify n;
memset(&n, 0, sizeof(E_Notification_Notify));
n.app_name = _("Battery");
n.replaces_id = 0;
n.icon.icon = "battery-low";
n.summary = _("Your battery is low!");
n.body = _("AC power is recommended.");
n.timeout = inst->cfg->batman.alert_timeout * 1000;
e_notification_client_send(&n, _batman_warning_popup_cb, inst);
return;
}
inst->warning = elm_ctxpopup_add(e_comp->elm);
elm_object_style_set(inst->warning, "noblock");
evas_object_smart_callback_add(inst->warning, "dismissed", _warning_popup_dismissed, inst);
if (!inst->warning) return;
popup_bg = elm_layout_add(inst->warning);
inst->popup_battery = elm_layout_add(popup_bg);
if ((!popup_bg) || (!inst->popup_battery))
{
elm_ctxpopup_dismiss(inst->warning);
inst->warning = NULL;
return;
}
e_theme_edje_object_set(popup_bg, "base/theme/modules/battery/popup",
"e/modules/battery/popup");
e_theme_edje_object_set(inst->popup_battery, "base/theme/modules/battery",
"e/modules/battery/main");
if (edje_object_part_exists(elm_layout_edje_get(popup_bg), "e.swallow.battery"))
elm_layout_content_set(popup_bg, "e.swallow.battery", inst->popup_battery);
else
elm_layout_content_set(popup_bg, "battery", inst->popup_battery);
elm_layout_text_set(popup_bg, "e.text.title",
_("Your battery is low!"));
elm_layout_text_set(popup_bg, "e.text.label",
_("AC power is recommended."));
evas_object_show(inst->popup_battery);
evas_object_show(popup_bg);
elm_object_content_set(inst->warning, popup_bg);
e_gadget_util_ctxpopup_place(inst->o_main, inst->warning, inst->cfg->batman.o_gadget);
evas_object_layer_set(inst->warning, E_LAYER_POPUP);
evas_object_show(inst->warning);
evas_object_geometry_get(inst->warning, &x, &y, &w, &h);
evas_object_event_callback_add(inst->warning, EVAS_CALLBACK_MOUSE_DOWN,
_batman_cb_warning_popup_hide, inst);
_batman_face_time_set(inst->popup_battery, t);
_batman_face_level_set(inst->popup_battery, percent);
edje_object_signal_emit(inst->popup_battery, "e,state,discharging", "e");
if ((inst->cfg->batman.alert_timeout > 0) &&
(!inst->cfg->batman.alert_timer))
{
inst->cfg->batman.alert_timer =
ecore_timer_add(inst->cfg->batman.alert_timeout,
_batman_cb_warning_popup_timeout, inst);
}
}
static void
_batman_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
{
Instance *inst = data;
if (inst->o_main != event_data) return;
#ifdef HAVE_EEZE
_batman_udev_stop(inst);
#elif defined __OpenBSD__ || defined __DragonFly__ || defined __FreeBSD__ || defined __NetBSD__
_batman_sysctl_stop();
#elif upower
_batman_upower_stop();
#else
_batman_fallback_stop();
#endif
#ifdef HAVE_EEZE
eeze_shutdown();
#endif
sysinfo_config->items = eina_list_remove(sysinfo_config->items, inst->cfg);
E_FREE(inst->cfg);
}
void
sysinfo_batman_remove(Instance *inst)
{
#ifdef HAVE_EEZE
_batman_udev_stop(inst);
#elif defined __OpenBSD__ || defined __DragonFly__ || defined __FreeBSD__ || defined __NetBSD__
_batman_sysctl_stop();
#elif upower
_batman_upower_stop();
#else
_batman_fallback_stop();
#endif
#ifdef HAVE_EEZE
eeze_shutdown();
#endif
}
static void
_batman_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
{
Instance *inst = data;
inst->cfg->batman.full = -2;
inst->cfg->batman.time_left = -2;
inst->cfg->batman.time_full = -2;
inst->cfg->batman.have_battery = -2;
inst->cfg->batman.have_power = -2;
inst->cfg->batman.o_gadget = elm_layout_add(inst->o_main);
e_theme_edje_object_set(inst->cfg->batman.o_gadget, "base/theme/modules/battery",
"e/modules/battery/main");
E_EXPAND(inst->cfg->batman.o_gadget);
E_FILL(inst->cfg->batman.o_gadget);
elm_box_pack_end(inst->o_main, inst->cfg->batman.o_gadget);
evas_object_show(inst->cfg->batman.o_gadget);
evas_object_smart_callback_del_full(obj, "gadget_created", _batman_created_cb, data);
_batman_config_updated(inst);
}
Evas_Object *
sysinfo_batman_create(Evas_Object *parent, Instance *inst)
{
inst->cfg->batman.full = -2;
inst->cfg->batman.time_left = -2;
inst->cfg->batman.time_full = -2;
inst->cfg->batman.have_battery = -2;
inst->cfg->batman.have_power = -2;
inst->cfg->batman.o_gadget = elm_layout_add(parent);
e_theme_edje_object_set(inst->cfg->batman.o_gadget, "base/theme/modules/battery",
"e/modules/battery/main");
E_EXPAND(inst->cfg->batman.o_gadget);
E_FILL(inst->cfg->batman.o_gadget);
evas_object_show(inst->cfg->batman.o_gadget);
_batman_config_updated(inst);
return inst->cfg->batman.o_gadget;
}
static Config_Item *
_conf_item_get(int *id)
{
Config_Item *ci;
Eina_List *l;
if (*id > 0)
{
EINA_LIST_FOREACH(sysinfo_config->items, l, ci)
if (*id == ci->id && ci->esm == E_SYSINFO_MODULE_BATMAN) return ci;
}
ci = E_NEW(Config_Item, 1);
if (*id != -1)
ci->id = eina_list_count(sysinfo_config->items)+1;
else
ci->id = -1;
ci->esm = E_SYSINFO_MODULE_BATMAN;
ci->batman.poll_interval = 512;
ci->batman.alert = 30;
ci->batman.alert_p = 10;
ci->batman.alert_timeout = 0;
ci->batman.suspend_below = 0;
ci->batman.force_mode = 0;
ci->batman.full = -2;
ci->batman.time_left = -2;
ci->batman.time_full = -2;
ci->batman.have_battery = -2;
ci->batman.have_power = -2;
#if defined HAVE_EEZE || defined __OpenBSD__ || defined __NetBSD__
ci->batman.fuzzy = 0;
#endif
ci->batman.desktop_notifications = 0;
sysinfo_config->items = eina_list_append(sysinfo_config->items, ci);
return ci;
}
Evas_Object *
batman_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient EINA_UNUSED)
{
Instance *inst;
inst = E_NEW(Instance, 1);
inst->cfg = _conf_item_get(id);
*id = inst->cfg->id;
inst->o_main = elm_box_add(parent);
E_EXPAND(inst->o_main);
evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
evas_object_smart_callback_add(parent, "gadget_created", _batman_created_cb, inst);
evas_object_smart_callback_add(parent, "gadget_removed", _batman_removed_cb, inst);
evas_object_show(inst->o_main);
#ifdef HAVE_EEZE
eeze_init();
#endif
if (inst->cfg->id < 0) return inst->o_main;
sysinfo_instances =
eina_list_append(sysinfo_instances, inst);
return inst->o_main;
}

View File

@ -0,0 +1,107 @@
#ifndef BATMAN_H
#define BATMAN_H
#include "../sysinfo.h"
#define CHECK_NONE 0
#define CHECK_ACPI 1
#define CHECK_APM 2
#define CHECK_PMU 3
#define CHECK_SYS_ACPI 4
#define UNKNOWN 0
#define NOSUBSYSTEM 1
#define SUBSYSTEM 2
#define SUSPEND 0
#define HIBERNATE 1
#define SHUTDOWN 2
#define POPUP_DEBOUNCE_CYCLES 2
typedef struct _Battery Battery;
typedef struct _Ac_Adapter Ac_Adapter;
typedef struct _Battery_Config Battery_Config;
struct _Battery
{
Instance *inst;
const char *udi;
#if defined HAVE_EEZE || defined __OpenBSD__ || defined __DragonFly__ || defined __FreeBSD__ || defined __NetBSD__
Ecore_Poller *poll;
#endif
Eina_Bool present:1;
Eina_Bool charging:1;
#if defined HAVE_EEZE || defined __OpenBSD__ || defined __DragonFly__ || defined __FreeBSD__ || defined __NetBSD__
double last_update;
double percent;
double current_charge;
double design_charge;
double last_full_charge;
double charge_rate;
double time_full;
double time_left;
#else
int percent;
int current_charge;
int design_charge;
int last_full_charge;
int charge_rate;
int time_full;
int time_left;
const char *type;
const char *charge_units;
#endif
const char *technology;
const char *model;
const char *vendor;
Eina_Bool got_prop:1;
Eldbus_Proxy *proxy;
int * mib;
#if defined(__FreeBSD__) || defined(__DragonFly__)
int * mib_state;
int * mib_units;
int * mib_time;
int batteries;
int time_min;
#endif
};
struct _Ac_Adapter
{
Instance *inst;
const char *udi;
Eina_Bool present:1;
const char *product;
Eldbus_Proxy *proxy;
int * mib;
};
Battery *_batman_battery_find(const char *udi);
Ac_Adapter *_batman_ac_adapter_find(const char *udi);
void _batman_update(Instance *inst, int full, int time_left, int time_full, Eina_Bool have_battery, Eina_Bool have_power);
void _batman_device_update(Instance *inst);
/* in batman_fallback.c */
int _batman_fallback_start(Instance *inst);
void _batman_fallback_stop(void);
/* end batman_fallback.c */
#ifdef HAVE_EEZE
/* in batman_udev.c */
int _batman_udev_start(Instance *inst);
void _batman_udev_stop(Instance *inst);
/* end batman_udev.c */
#elif !defined __OpenBSD__ && !defined __DragonFly__ && !defined __FreeBSD__ && !defined __NetBSD__
/* in batman_upower.c */
int _batman_upower_start(Instance *inst);
void _batman_upower_stop(void);
/* end batman_upower.c */
#else
/* in batman_sysctl.c */
int _batman_sysctl_start(Instance *inst);
void _batman_sysctl_stop(void);
/* end batman_sysctl.c */
#endif
void _batman_config_updated(Instance *inst);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,347 @@
#include <err.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#if defined(__OpenBSD__) || defined(__NetBSD__)
#include <sys/param.h>
#include <sys/sensors.h>
#endif
#include "batman.h"
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
static Eina_Bool _batman_sysctl_battery_update_poll(void *data);
#endif
static int _batman_sysctl_battery_update(Instance *inst);
extern Eina_List *batman_device_batteries;
extern Eina_List *batman_device_ac_adapters;
extern double batman_init_time;
Ac_Adapter *ac = NULL;
Battery *bat = NULL;
int
_batman_sysctl_start(Instance *inst)
{
#if defined(__OpenBSD__) || defined(__NetBSD__)
int mib[] = {CTL_HW, HW_SENSORS, 0, 0, 0};
int devn;
struct sensordev snsrdev;
size_t sdlen = sizeof(struct sensordev);
#elif defined(__FreeBSD__) || defined(__DragonFly__)
int result;
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;
}
if (!strcmp("acpibat0", snsrdev.xname))
{
if (!(bat = E_NEW(Battery, 1)))
return 0;
bat->inst = inst;
bat->udi = eina_stringshare_add("acpibat0"),
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->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);
}
else if (!strcmp("acpiac0", snsrdev.xname))
{
if (!(ac = E_NEW(Ac_Adapter, 1)))
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)
{
if (!(bat = E_NEW(Battery, 1)))
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->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)
{
if (!(ac = E_NEW(Ac_Adapter, 1)))
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);
bat->last_update = ecore_time_get();
return 1;
}
void
_batman_sysctl_stop(void)
{
if (ac)
{
E_FREE_FUNC(ac->udi, eina_stringshare_del);
E_FREE_FUNC(ac->mib, free);
E_FREE_FUNC(ac, free);
}
if (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_FUNC(bat->mib_state, free);
E_FREE_FUNC(bat->mib_time, free);
E_FREE_FUNC(bat->mib_units, free);
#endif
E_FREE_FUNC(bat->mib, free);
E_FREE_FUNC(bat, free);
}
}
#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)
{
#if defined(__OpenBSD__) || defined(__NetBSD__)
double _time, charge;
struct sensor s;
size_t slen = sizeof(struct sensor);
#elif defined(__FreeBSD__) || defined(__DragonFly__)
double _time, charge;
int value;
size_t len;
#endif
if (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 (charge == 0 || bat->last_full_charge == 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;
}
/* remaining capacity */
bat->mib[3] = 8;
bat->mib[4] = 3;
if (sysctl(bat->mib, 5, &s, &slen, NULL, 0) != -1)
{
charge = (double)s.value;
}
}
_time = ecore_time_get();
if ((bat->got_prop) && (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;
}
#elif defined(__FreeBSD__) || defined(__DragonFly__)
len = sizeof(value);
if ((sysctl(bat->mib, 4, &value, &len, NULL, 0)) == -1)
{
return 0;
}
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 0;
}
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;
#endif
}
if (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
}
if (bat)
{
if (bat->got_prop)
_batman_device_update(bat->inst);
bat->got_prop = 1;
}
return 0;
}

View File

@ -0,0 +1,320 @@
#include "batman.h"
static void _batman_udev_event_battery(const char *syspath, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch);
static void _batman_udev_event_ac(const char *syspath, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch);
static void _batman_udev_battery_add(const char *syspath, Instance *inst);
static void _batman_udev_ac_add(const char *syspath, Instance *inst);
static void _batman_udev_battery_del(const char *syspath);
static void _batman_udev_ac_del(const char *syspath);
static Eina_Bool _batman_udev_battery_update_poll(void *data);
static void _batman_udev_battery_update(const char *syspath, Battery *bat, Instance *inst);
static void _batman_udev_ac_update(const char *syspath, Ac_Adapter *ac, Instance *inst);
extern Eina_List *batman_device_batteries;
extern Eina_List *batman_device_ac_adapters;
extern double batman_init_time;
int
_batman_udev_start(Instance *inst)
{
Eina_List *devices;
const char *dev;
devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_POWER_BAT, NULL);
EINA_LIST_FREE(devices, dev)
_batman_udev_battery_add(dev, inst);
devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_POWER_AC, NULL);
EINA_LIST_FREE(devices, dev)
_batman_udev_ac_add(dev, inst);
if (!inst->cfg->batman.batwatch)
inst->cfg->batman.batwatch = eeze_udev_watch_add(EEZE_UDEV_TYPE_POWER_BAT, EEZE_UDEV_EVENT_NONE, _batman_udev_event_battery, inst);
if (!inst->cfg->batman.acwatch)
inst->cfg->batman.acwatch = eeze_udev_watch_add(EEZE_UDEV_TYPE_POWER_AC, EEZE_UDEV_EVENT_NONE, _batman_udev_event_ac, inst);
batman_init_time = ecore_time_get();
return 1;
}
void
_batman_udev_stop(Instance *inst)
{
Ac_Adapter *ac;
Battery *bat;
if (inst->cfg->batman.batwatch)
E_FREE_FUNC(inst->cfg->batman.batwatch, eeze_udev_watch_del);
if (inst->cfg->batman.acwatch)
E_FREE_FUNC(inst->cfg->batman.acwatch, eeze_udev_watch_del);
EINA_LIST_FREE(batman_device_ac_adapters, ac)
{
E_FREE_FUNC(ac, free);
}
EINA_LIST_FREE(batman_device_batteries, bat)
{
eina_stringshare_del(bat->udi);
eina_stringshare_del(bat->technology);
eina_stringshare_del(bat->model);
eina_stringshare_del(bat->vendor);
E_FREE_FUNC(bat->poll, ecore_poller_del);
E_FREE_FUNC(bat, free);
}
}
static void
_batman_udev_event_battery(const char *syspath, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch EINA_UNUSED)
{
Instance *inst = data;
if ((event & EEZE_UDEV_EVENT_ADD) ||
(event & EEZE_UDEV_EVENT_ONLINE))
_batman_udev_battery_add(syspath, inst);
else if ((event & EEZE_UDEV_EVENT_REMOVE) ||
(event & EEZE_UDEV_EVENT_OFFLINE))
_batman_udev_battery_del(syspath);
else /* must be change */
_batman_udev_battery_update(syspath, NULL, inst);
}
static void
_batman_udev_event_ac(const char *syspath, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch EINA_UNUSED)
{
Instance *inst = data;
if ((event & EEZE_UDEV_EVENT_ADD) ||
(event & EEZE_UDEV_EVENT_ONLINE))
_batman_udev_ac_add(syspath, inst);
else if ((event & EEZE_UDEV_EVENT_REMOVE) ||
(event & EEZE_UDEV_EVENT_OFFLINE))
_batman_udev_ac_del(syspath);
else /* must be change */
_batman_udev_ac_update(syspath, NULL, inst);
}
static void
_batman_udev_battery_add(const char *syspath, Instance *inst)
{
Battery *bat;
if ((bat = _batman_battery_find(syspath)))
{
eina_stringshare_del(syspath);
bat->inst = inst;
_batman_udev_battery_update(NULL, bat, inst);
return;
}
if (!(bat = E_NEW(Battery, 1)))
{
eina_stringshare_del(syspath);
return;
}
bat->inst = inst;
bat->last_update = ecore_time_get();
bat->udi = eina_stringshare_add(syspath);
bat->poll = ecore_poller_add(ECORE_POLLER_CORE,
bat->inst->cfg->batman.poll_interval,
_batman_udev_battery_update_poll, bat);
batman_device_batteries = eina_list_append(batman_device_batteries, bat);
_batman_udev_battery_update(syspath, bat, inst);
}
static void
_batman_udev_ac_add(const char *syspath, Instance *inst)
{
Ac_Adapter *ac;
if ((ac = _batman_ac_adapter_find(syspath)))
{
eina_stringshare_del(syspath);
_batman_udev_ac_update(NULL, ac, inst);
return;
}
if (!(ac = E_NEW(Ac_Adapter, 1)))
{
eina_stringshare_del(syspath);
return;
}
ac->inst = inst;
ac->udi = eina_stringshare_add(syspath);
batman_device_ac_adapters = eina_list_append(batman_device_ac_adapters, ac);
_batman_udev_ac_update(syspath, ac, inst);
}
static void
_batman_udev_battery_del(const char *syspath)
{
Battery *bat;
if (!(bat = _batman_battery_find(syspath)))
{
eina_stringshare_del(syspath);
return;
}
batman_device_batteries = eina_list_remove(batman_device_batteries, bat);
eina_stringshare_del(bat->udi);
eina_stringshare_del(bat->technology);
eina_stringshare_del(bat->model);
eina_stringshare_del(bat->vendor);
E_FREE_FUNC(bat->poll, ecore_poller_del);
E_FREE_FUNC(bat, free);
}
static void
_batman_udev_ac_del(const char *syspath)
{
Ac_Adapter *ac;
if (!(ac = _batman_ac_adapter_find(syspath)))
{
eina_stringshare_del(syspath);
_batman_device_update(ac->inst);
return;
}
batman_device_ac_adapters = eina_list_remove(batman_device_ac_adapters, ac);
eina_stringshare_del(ac->udi);
E_FREE_FUNC(ac, free);
}
static Eina_Bool
_batman_udev_battery_update_poll(void *data)
{
Battery *bat = data;
_batman_udev_battery_update(NULL, bat, bat->inst);
return EINA_TRUE;
}
#define GET_NUM(TYPE, VALUE, PROP) \
do \
{ \
test = eeze_udev_syspath_get_property(TYPE->udi, #PROP); \
if (test) \
{ \
TYPE->VALUE = strtod(test, NULL); \
eina_stringshare_del(test); \
} \
} \
while (0)
#define GET_STR(TYPE, VALUE, PROP) TYPE->VALUE = eeze_udev_syspath_get_property(TYPE->udi, #PROP)
static void
_batman_udev_battery_update(const char *syspath, Battery *bat, Instance *inst)
{
const char *test;
double t, charge;
if (!bat)
{
if (!(bat = _batman_battery_find(syspath)))
{
_batman_udev_battery_add(syspath, inst);
return;
}
}
/* update the poller interval */
ecore_poller_poller_interval_set(bat->poll, bat->inst->cfg->batman.poll_interval);
GET_NUM(bat, present, POWER_SUPPLY_PRESENT);
if (!bat->got_prop) /* only need to get these once */
{
GET_STR(bat, technology, POWER_SUPPLY_TECHNOLOGY);
GET_STR(bat, model, POWER_SUPPLY_MODEL_NAME);
GET_STR(bat, vendor, POWER_SUPPLY_MANUFACTURER);
GET_NUM(bat, design_charge, POWER_SUPPLY_ENERGY_FULL_DESIGN);
if (!bat->design_charge)
GET_NUM(bat, design_charge, POWER_SUPPLY_CHARGE_FULL_DESIGN);
}
GET_NUM(bat, last_full_charge, POWER_SUPPLY_ENERGY_FULL);
if (!bat->last_full_charge)
GET_NUM(bat, last_full_charge, POWER_SUPPLY_CHARGE_FULL);
test = eeze_udev_syspath_get_property(bat->udi, "POWER_SUPPLY_ENERGY_NOW");
if (!test)
test = eeze_udev_syspath_get_property(bat->udi, "POWER_SUPPLY_CHARGE_NOW");
if (test)
{
double charge_rate = 0;
charge = strtod(test, NULL);
eina_stringshare_del(test);
t = ecore_time_get();
if ((bat->got_prop) && (charge != bat->current_charge) && bat->current_charge != 0)
charge_rate = ((charge - bat->current_charge) / (t - bat->last_update));
if (charge_rate != 0 || bat->last_update == 0 || bat->current_charge == 0)
{
bat->last_update = t;
bat->current_charge = charge;
bat->charge_rate = charge_rate;
}
bat->percent = 100 * (bat->current_charge / bat->last_full_charge);
if (bat->got_prop)
{
if (bat->charge_rate > 0)
{
if (bat->inst->cfg->batman.fuzzy && (++bat->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 (bat->inst->cfg->batman.fuzzy && (bat->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;
}
}
if (bat->inst->cfg->batman.fuzzcount > 10) bat->inst->cfg->batman.fuzzcount = 0;
test = eeze_udev_syspath_get_property(bat->udi, "POWER_SUPPLY_STATUS");
if (test)
{
if (!strcmp(test, "Charging"))
bat->charging = 1;
else if ((!strcmp(test, "Unknown")) && (bat->charge_rate > 0))
bat->charging = 1;
else
bat->charging = 0;
eina_stringshare_del(test);
}
else
bat->charging = 0;
if (bat->got_prop)
_batman_device_update(bat->inst);
bat->got_prop = 1;
}
static void
_batman_udev_ac_update(const char *syspath, Ac_Adapter *ac, Instance *inst)
{
const char *test;
if (!ac)
{
if (!(ac = _batman_ac_adapter_find(syspath)))
{
_batman_udev_ac_add(syspath, inst);
return;
}
}
GET_NUM(ac, present, POWER_SUPPLY_ONLINE);
/* yes, it's really that simple. */
_batman_device_update(inst);
}

View File

@ -0,0 +1,376 @@
#include "batman.h"
#define BUS "org.freedesktop.UPower"
#define PATH "/org/freedesktop/UPower"
#define IFACE "org.freedesktop.UPower"
extern Eina_List *batman_device_batteries;
extern Eina_List *batman_device_ac_adapters;
extern double batman_init_time;
static Eldbus_Connection *conn;
static Eldbus_Proxy *upower_proxy;
typedef struct _Upower_Data Upower_Data;
struct _Upower_Data
{
Eldbus_Proxy *proxy;
Instance *inst;
};
static void
_battery_free(Battery *bat)
{
Eldbus_Object *obj = eldbus_proxy_object_get(bat->proxy);
eldbus_proxy_unref(bat->proxy);
eldbus_object_unref(obj);
batman_device_batteries = eina_list_remove(batman_device_batteries, bat);
eina_stringshare_del(bat->udi);
if (bat->model)
eina_stringshare_del(bat->model);
if (bat->vendor)
eina_stringshare_del(bat->vendor);
free(bat);
}
static void
_ac_free(Ac_Adapter *ac)
{
Eldbus_Object *obj = eldbus_proxy_object_get(ac->proxy);
eldbus_proxy_unref(ac->proxy);
eldbus_object_unref(obj);
batman_device_ac_adapters = eina_list_remove(batman_device_ac_adapters, ac);
eina_stringshare_del(ac->udi);
free(ac);
}
static void
_ac_get_all_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
Ac_Adapter *ac = data;
Eldbus_Message_Iter *array, *dict, *variant;
if (!eldbus_message_arguments_get(msg, "a{sv}", &array))
return;
while (eldbus_message_iter_get_and_next(array, 'e', &dict))
{
const char *key;
if (!eldbus_message_iter_arguments_get(dict, "sv", &key, &variant))
continue;
if (!strcmp(key, "Online"))
{
Eina_Bool b;
eldbus_message_iter_arguments_get(variant, "b", &b);
ac->present = b;
break;
}
}
_batman_device_update(ac->inst);
}
static void
_ac_changed_cb(void *data, const Eldbus_Message *msg EINA_UNUSED)
{
Ac_Adapter *ac = data;
eldbus_proxy_property_get_all(ac->proxy, _ac_get_all_cb, ac);
}
static void
_process_ac(Eldbus_Proxy *proxy, Instance *inst)
{
Ac_Adapter *ac;
ac = E_NEW(Ac_Adapter, 1);
if (!ac) goto error;
ac->inst = inst;
ac->proxy = proxy;
ac->udi = eina_stringshare_add(eldbus_object_path_get(eldbus_proxy_object_get(proxy)));
eldbus_proxy_property_get_all(proxy, _ac_get_all_cb, ac);
eldbus_proxy_signal_handler_add(proxy, "Changed", _ac_changed_cb, ac);
batman_device_ac_adapters = eina_list_append(batman_device_ac_adapters, ac);
return;
error:
eldbus_object_unref(eldbus_proxy_object_get(proxy));
eldbus_proxy_unref(proxy);
return;
}
static const char *bat_techologies[] = {
"Unknown",
"Lithium ion",
"Lithium polymer",
"Lithium iron phosphate",
"Lead acid",
"Nickel cadmium",
"Nickel metal hydride"
};
static void
_bat_get_all_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
Battery *bat = data;
Eldbus_Message_Iter *array, *dict, *variant;
bat->got_prop = EINA_TRUE;
if (!eldbus_message_arguments_get(msg, "a{sv}", &array))
return;
while (eldbus_message_iter_get_and_next(array, 'e', &dict))
{
const char *key;
union
{
Eina_Bool b;
int64_t i64;
unsigned u;
double d;
const char *s;
} val;
if (!eldbus_message_iter_arguments_get(dict, "sv", &key, &variant))
continue;
if (!strcmp(key, "IsPresent"))
{
eldbus_message_iter_arguments_get(variant, "b", &val.b);
bat->present = val.b;
}
else if (!strcmp(key, "TimeToEmpty"))
{
eldbus_message_iter_arguments_get(variant, "x", &val.i64);
bat->time_left = (int) val.i64;
if (bat->time_left > 0)
bat->charging = EINA_FALSE;
else
bat->charging = EINA_TRUE;
}
else if (!strcmp(key, "Percentage"))
{
eldbus_message_iter_arguments_get(variant, "d", &val.d);
bat->percent = (int) val.d;
}
else if (!strcmp(key, "Energy"))
{
eldbus_message_iter_arguments_get(variant, "d", &val.d);
bat->current_charge = (int) val.d;
}
else if (!strcmp(key, "EnergyFullDesign"))
{
eldbus_message_iter_arguments_get(variant, "d", &val.d);
bat->design_charge = (int) val.d;
}
else if (!strcmp(key, "EnergyFull"))
{
eldbus_message_iter_arguments_get(variant, "d", &val.d);
bat->last_full_charge = (int) val.d;
}
else if (!strcmp(key, "TimeToFull"))
{
eldbus_message_iter_arguments_get(variant, "x", &val.i64);
bat->time_full = (int) val.i64;
}
else if (!strcmp(key, "Technology"))
{
eldbus_message_iter_arguments_get(variant, "u", &val.u);
if (val.u > EINA_C_ARRAY_LENGTH(bat_techologies))
val.u = 0;
bat->technology = bat_techologies[val.u];
}
else if (!strcmp(key, "Model"))
{
if (!eldbus_message_iter_arguments_get(variant, "s", &val.s))
continue;
eina_stringshare_replace(&bat->model, val.s);
}
else if (!strcmp(key, "Vendor"))
{
if (!eldbus_message_iter_arguments_get(variant, "s", &val.s))
continue;
if (bat->vendor)
eina_stringshare_del(bat->vendor);
bat->vendor = eina_stringshare_add(val.s);
}
}
_batman_device_update(bat->inst);
}
static void
_bat_changed_cb(void *data, const Eldbus_Message *msg EINA_UNUSED)
{
Battery *bat = data;
eldbus_proxy_property_get_all(bat->proxy, _bat_get_all_cb, bat);
}
static void
_process_battery(Eldbus_Proxy *proxy, Instance *inst)
{
Battery *bat;
bat = E_NEW(Battery, 1);
if (!bat)
{
eldbus_object_unref(eldbus_proxy_object_get(proxy));
eldbus_proxy_unref(proxy);
return;
}
bat->inst = inst;
bat->proxy = proxy;
bat->udi = eina_stringshare_add(eldbus_object_path_get(eldbus_proxy_object_get(proxy)));
eldbus_proxy_property_get_all(proxy, _bat_get_all_cb, bat);
eldbus_proxy_signal_handler_add(proxy, "Changed", _bat_changed_cb, bat);
batman_device_batteries = eina_list_append(batman_device_batteries, bat);
_batman_device_update(bat->inst);
}
static void
_device_type_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
Upower_Data *ud = data;
Eldbus_Message_Iter *variant;
Eldbus_Object *obj;
unsigned int type;
if (!eldbus_message_arguments_get(msg, "v", &variant))
goto error;
eldbus_message_iter_arguments_get(variant, "u", &type);
if (type == 1)
_process_ac(ud->proxy, ud->inst);
else if (type == 2)
_process_battery(ud->proxy, ud->inst);
else
goto error;
free(ud);
return;
error:
obj = eldbus_proxy_object_get(ud->proxy);
eldbus_proxy_unref(ud->proxy);
eldbus_object_unref(obj);
free(ud);
return;
}
static void
_process_enumerate_path(const char *path, Instance *inst)
{
Eldbus_Object *obj;
Eldbus_Proxy *proxy;
Upower_Data *ud;
obj = eldbus_object_get(conn, BUS, path);
EINA_SAFETY_ON_FALSE_RETURN(obj);
proxy = eldbus_proxy_get(obj, "org.freedesktop.UPower.Device");
ud = E_NEW(Upower_Data, 1);
if (!ud)
{
eldbus_object_unref(eldbus_proxy_object_get(proxy));
eldbus_proxy_unref(proxy);
return;
}
ud->proxy = proxy;
ud->inst = inst;
eldbus_proxy_property_get(proxy, "Type", _device_type_cb, ud);
}
static void
_enumerate_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
Instance *inst = data;
const char *path;
Eldbus_Message_Iter *array;
if (!eldbus_message_arguments_get(msg, "ao", &array))
return;
while (eldbus_message_iter_get_and_next(array, 'o', &path))
_process_enumerate_path(path, inst);
}
static void
_device_added_cb(void *data, const Eldbus_Message *msg)
{
const char *path;
Instance *inst = data;
if (!eldbus_message_arguments_get(msg, "o", &path))
return;
_process_enumerate_path(path, inst);
}
static void
_device_removed_cb(void *data EINA_UNUSED, const Eldbus_Message *msg)
{
Battery *bat;
Ac_Adapter *ac;
const char *path;
Instance *inst;
if (!eldbus_message_arguments_get(msg, "o", &path))
return;
bat = _batman_battery_find(path);
if (bat)
{
inst = bat->inst;
_battery_free(bat);
_batman_device_update(inst);
return;
}
ac = _batman_ac_adapter_find(path);
if (ac)
{
inst = ac->inst;
_ac_free(ac);
_batman_device_update(inst);
}
}
int
_batman_upower_start(Instance *inst)
{
Eldbus_Object *obj;
conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, 0);
obj = eldbus_object_get(conn, BUS, PATH);
EINA_SAFETY_ON_NULL_GOTO(obj, obj_error);
upower_proxy = eldbus_proxy_get(obj, IFACE);
EINA_SAFETY_ON_NULL_GOTO(upower_proxy, proxy_error);
eldbus_proxy_call(upower_proxy, "EnumerateDevices", _enumerate_cb, inst, -1, "");
eldbus_proxy_signal_handler_add(upower_proxy, "DeviceAdded", _device_added_cb, inst);
eldbus_proxy_signal_handler_add(upower_proxy, "DeviceRemoved", _device_removed_cb, NULL);
return 1;
proxy_error:
eldbus_object_unref(obj);
obj_error:
eldbus_connection_unref(conn);
return 0;
}
void
_batman_upower_stop(void)
{
Eina_List *list, *list2;
Battery *bat;
Ac_Adapter *ac;
Eldbus_Object *obj;
EINA_LIST_FOREACH_SAFE(batman_device_batteries, list, list2, bat)
E_FREE_FUNC(bat, _battery_free);
EINA_LIST_FOREACH_SAFE(batman_device_ac_adapters, list, list2, ac)
E_FREE_FUNC(ac, _ac_free);
obj = eldbus_proxy_object_get(upower_proxy);
E_FREE_FUNC(upower_proxy, eldbus_proxy_unref);
E_FREE_FUNC(obj, eldbus_object_unref);
E_FREE_FUNC(conn, eldbus_connection_unref);
}

View File

@ -0,0 +1,913 @@
#include "cpuclock.h"
typedef struct _Thread_Config Thread_Config;
struct _Thread_Config
{
int interval;
Instance *inst;
};
typedef struct _Pstate_Config Pstate_Config;
struct _Pstate_Config
{
Instance *inst;
int min;
int max;
int turbo;
};
static Cpu_Status *
_cpuclock_status_new(void)
{
Cpu_Status *s;
s = E_NEW(Cpu_Status, 1);
if (!s) return NULL;
s->active = -1;
return s;
}
static void
_cpuclock_status_free(Cpu_Status *s)
{
Eina_List *l;
if (s->frequencies) eina_list_free(s->frequencies);
if (s->governors)
{
for (l = s->governors; l; l = l->next)
E_FREE_FUNC(l->data, free);
eina_list_free(s->governors);
}
E_FREE_FUNC(s->cur_governor, free);
if (s->orig_governor) eina_stringshare_del(s->orig_governor);
E_FREE_FUNC(s, free);
}
static int
_cpuclock_cb_sort(const void *item1, const void *item2)
{
int a, b;
a = (long)item1;
b = (long)item2;
if (a < b) return -1;
else if (a > b)
return 1;
return 0;
}
static void
_cpuclock_set_thread_governor(void *data, Ecore_Thread *th EINA_UNUSED)
{
const char *governor = data;
_cpuclock_sysfs_setall("scaling_governor", governor);
if (!strcmp(governor, "ondemand"))
_cpuclock_sysfs_set("ondemand/ignore_nice_load", "0");
else if (!strcmp(governor, "conservative"))
_cpuclock_sysfs_set("conservative/ignore_nice_load", "0");
}
static void
_cpuclock_set_thread_frequency(void *data, Ecore_Thread *th EINA_UNUSED)
{
const char *freq = data;
#if defined __FreeBSD__ || defined __OpenBSD__
_cpuclock_sysctl_set("frequency", freq);
return;
#endif
_cpuclock_sysfs_setall("scaling_setspeed", freq);
}
static void
_cpuclock_set_thread_pstate(void *data, Ecore_Thread *th EINA_UNUSED)
{
Pstate_Config *pc = data;
_cpuclock_sysfs_pstate(pc->min, pc->max, pc->turbo);
}
static void
_cpuclock_set_thread_done(void *data EINA_UNUSED, Ecore_Thread *th EINA_UNUSED)
{
return;
}
static void
_cpuclock_set_thread_pstate_done(void *data, Ecore_Thread *th EINA_UNUSED)
{
Pstate_Config *pc = data;
E_FREE_FUNC(pc, free);
return;
}
void
_cpuclock_set_governor(const char *governor)
{
#if defined __FreeBSD__ || defined __OpenBSD__
return;
#endif
ecore_thread_run(_cpuclock_set_thread_governor, _cpuclock_set_thread_done, NULL, governor);
}
static void
_cpuclock_set_frequency(int frequency)
{
char buf[4096];
const char *freq;
#ifdef __FreeBSD__
frequency /= 1000;
#endif
snprintf(buf, sizeof(buf), "%i", frequency);
freq = eina_stringshare_add(buf);
ecore_thread_run(_cpuclock_set_thread_frequency, _cpuclock_set_thread_done, NULL, freq);
}
void
_cpuclock_set_pstate(int min, int max, int turbo)
{
#if defined __FreeBSD__ || defined __OpenBSD__
return;
#endif
Pstate_Config *pc;
pc = E_NEW(Pstate_Config, 1);
if (!pc) return;
pc->turbo = turbo;
pc->min = min;
pc->max = max;
ecore_thread_run(_cpuclock_set_thread_pstate, _cpuclock_set_thread_pstate_done, NULL, pc);
}
static void
_cpuclock_face_cb_set_frequency(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *src EINA_UNUSED)
{
Eina_List *l;
int next_frequency = 0;
Instance *inst = data;
for (l = inst->cfg->cpuclock.status->frequencies; l; l = l->next)
{
if (inst->cfg->cpuclock.status->cur_frequency == (long)l->data)
{
if (!strcmp(emission, "e,action,frequency,increase"))
{
if (l->next) next_frequency = (long)l->next->data;
break;
}
else if (!strcmp(emission, "e,action,frequency,decrease"))
{
if (l->prev) next_frequency = (long)l->prev->data;
break;
}
else
break;
}
}
if (inst->cfg->cpuclock.status->can_set_frequency && next_frequency)
_cpuclock_set_frequency(next_frequency);
}
static void
_cpuclock_face_cb_set_governor(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *src EINA_UNUSED)
{
Eina_List *l;
char *next_governor = NULL;
Instance *inst = data;
for (l = inst->cfg->cpuclock.status->governors; l; l = l->next)
{
if (!strcmp(l->data, inst->cfg->cpuclock.status->cur_governor))
{
if (l->next)
next_governor = l->next->data;
else
next_governor = inst->cfg->cpuclock.status->governors->data;
break;
}
}
if (next_governor) _cpuclock_set_governor(next_governor);
}
static Eina_Bool
_cpuclock_event_cb_powersave(void *data, int type, void *event)
{
Instance *inst = data;
E_Event_Powersave_Update *ev;
Eina_List *l;
Eina_Bool has_powersave = EINA_FALSE;
Eina_Bool has_conservative = EINA_FALSE;
if (type != E_EVENT_POWERSAVE_UPDATE) return ECORE_CALLBACK_PASS_ON;
if (!inst->cfg->cpuclock.auto_powersave) return ECORE_CALLBACK_PASS_ON;
ev = event;
if (!inst->cfg->cpuclock.status->orig_governor)
inst->cfg->cpuclock.status->orig_governor = eina_stringshare_add(inst->cfg->cpuclock.status->cur_governor);
for (l = inst->cfg->cpuclock.status->governors; l; l = l->next)
{
if (!strcmp(l->data, "conservative"))
has_conservative = EINA_TRUE;
else if (!strcmp(l->data, "powersave"))
has_powersave = EINA_TRUE;
else if (!strcmp(l->data, "interactive"))
has_powersave = EINA_TRUE;
}
switch (ev->mode)
{
case E_POWERSAVE_MODE_NONE:
case E_POWERSAVE_MODE_LOW:
_cpuclock_set_governor(inst->cfg->cpuclock.status->orig_governor);
eina_stringshare_del(inst->cfg->cpuclock.status->orig_governor);
inst->cfg->cpuclock.status->orig_governor = NULL;
break;
case E_POWERSAVE_MODE_MEDIUM:
case E_POWERSAVE_MODE_HIGH:
if ((inst->cfg->cpuclock.powersave_governor) || (has_conservative))
{
if (inst->cfg->cpuclock.powersave_governor)
_cpuclock_set_governor(inst->cfg->cpuclock.powersave_governor);
else
_cpuclock_set_governor("conservative");
break;
}
case E_POWERSAVE_MODE_EXTREME:
if (has_powersave)
_cpuclock_set_governor("powersave");
break;
}
return ECORE_CALLBACK_PASS_ON;
}
void
_cpuclock_config_updated(Instance *inst)
{
Edje_Message_Int_Set *frequency_msg;
Edje_Message_String_Set *governor_msg;
Eina_List *l;
int i;
unsigned int count;
if (inst->cfg->cpuclock.status->frequencies)
{
count = eina_list_count(inst->cfg->cpuclock.status->frequencies);
frequency_msg = malloc(sizeof(Edje_Message_Int_Set) + (count - 1) * sizeof(int));
EINA_SAFETY_ON_NULL_RETURN(frequency_msg);
frequency_msg->count = count;
for (l = inst->cfg->cpuclock.status->frequencies, i = 0; l; l = l->next, i++)
frequency_msg->val[i] = (long)l->data;
edje_object_message_send(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), EDJE_MESSAGE_INT_SET, 1, frequency_msg);
free(frequency_msg);
}
if (inst->cfg->cpuclock.status->governors)
{
count = eina_list_count(inst->cfg->cpuclock.status->governors);
governor_msg = malloc(sizeof(Edje_Message_String_Set) + (count - 1) * sizeof(char *));
governor_msg->count = count;
for (l = inst->cfg->cpuclock.status->governors, i = 0; l; l = l->next, i++)
governor_msg->str[i] = (char *)l->data;
edje_object_message_send(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), EDJE_MESSAGE_STRING_SET, 2, governor_msg);
free(governor_msg);
}
}
static void
_cpuclock_face_update_current(Instance *inst)
{
Edje_Message_Int_Set *frequency_msg;
Edje_Message_String governor_msg;
frequency_msg = malloc(sizeof(Edje_Message_Int_Set) + (sizeof(int) * 4));
EINA_SAFETY_ON_NULL_RETURN(frequency_msg);
frequency_msg->count = 5;
frequency_msg->val[0] = inst->cfg->cpuclock.status->cur_frequency;
frequency_msg->val[1] = inst->cfg->cpuclock.status->can_set_frequency;
frequency_msg->val[2] = inst->cfg->cpuclock.status->cur_min_frequency;
frequency_msg->val[3] = inst->cfg->cpuclock.status->cur_max_frequency;
frequency_msg->val[4] = 0; // pad
edje_object_message_send(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), EDJE_MESSAGE_INT_SET, 3,
frequency_msg);
free(frequency_msg);
/* BSD crashes here without the if-condition
* since it has no governors (yet) */
if (inst->cfg->cpuclock.status->cur_governor)
{
governor_msg.str = inst->cfg->cpuclock.status->cur_governor;
edje_object_message_send(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), EDJE_MESSAGE_STRING, 4,
&governor_msg);
}
}
static void
_cpuclock_status_check_available(Cpu_Status *s)
{
char buf[4096];
Eina_List *l;
// FIXME: this assumes all cores accept the same freqs/ might be wrong
#if defined (__OpenBSD__)
int p;
if (s->frequencies)
{
eina_list_free(s->frequencies);
s->frequencies = NULL;
}
/* storing percents */
p = 100;
s->frequencies = eina_list_append(s->frequencies, (void *)p);
p = 75;
s->frequencies = eina_list_append(s->frequencies, (void *)p);
p = 50;
s->frequencies = eina_list_append(s->frequencies, (void *)p);
p = 25;
s->frequencies = eina_list_append(s->frequencies, (void *)p);
#elif defined (__FreeBSD__)
int freq;
size_t len = sizeof(buf);
char *pos, *q;
/* read freq_levels sysctl and store it in freq */
if (sysctlbyname("dev.cpu.0.freq_levels", buf, &len, NULL, 0) == 0)
{
/* sysctl returns 0 on success */
if (s->frequencies)
{
eina_list_free(s->frequencies);
s->frequencies = NULL;
}
/* parse freqs and store the frequencies in s->frequencies */
pos = buf;
while (pos)
{
q = strchr(pos, '/');
if (!q) break;
*q = '\0';
freq = atoi(pos);
freq *= 1000;
s->frequencies = eina_list_append(s->frequencies, (void *)freq);
pos = q + 1;
pos = strchr(pos, ' ');
}
}
/* sort is not necessary because freq_levels is already sorted */
/* freebsd doesn't have governors */
if (s->governors)
{
for (l = s->governors; l; l = l->next)
free(l->data);
eina_list_free(s->governors);
s->governors = NULL;
}
#else
FILE *f;
f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies", "r");
if (f)
{
char *freq;
if (s->frequencies)
{
eina_list_free(s->frequencies);
s->frequencies = NULL;
}
if (fgets(buf, sizeof(buf), f) == NULL)
{
fclose(f);
return;
}
fclose(f);
freq = strtok(buf, " ");
do
{
if (atoi(freq) != 0)
{
s->frequencies = eina_list_append(s->frequencies,
(void *)(long)atoi(freq));
}
freq = strtok(NULL, " ");
}
while (freq);
s->frequencies = eina_list_sort(s->frequencies,
eina_list_count(s->frequencies),
_cpuclock_cb_sort);
}
else
do
{
#define CPUFREQ_SYSFSDIR "/sys/devices/system/cpu/cpu0/cpufreq"
f = fopen(CPUFREQ_SYSFSDIR "/scaling_cur_freq", "r");
if (!f) break;
fclose(f);
f = fopen(CPUFREQ_SYSFSDIR "/scaling_driver", "r");
if (!f) break;
if (fgets(buf, sizeof(buf), f) == NULL)
{
fclose(f);
break;
}
fclose(f);
if (strcmp(buf, "intel_pstate\n")) break;
if (s->frequencies)
{
eina_list_free(s->frequencies);
s->frequencies = NULL;
}
#define CPUFREQ_ADDF(filename) \
f = fopen(CPUFREQ_SYSFSDIR filename, "r"); \
if (f) \
{ \
if (fgets(buf, sizeof(buf), f) != NULL) \
s->frequencies = eina_list_append(s->frequencies, \
(void *)(long)(atoi(buf))); \
fclose(f); \
}
CPUFREQ_ADDF("/cpuinfo_min_freq");
CPUFREQ_ADDF("/cpuinfo_max_freq");
}
while (0);
f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors", "r");
if (f)
{
char *gov;
int len;
if (s->governors)
{
for (l = s->governors; l; l = l->next)
free(l->data);
eina_list_free(s->governors);
s->governors = NULL;
}
if (fgets(buf, sizeof(buf), f) == NULL)
{
fclose(f);
return;
}
fclose(f);
len = strlen(buf);
if (len > 0)
{
gov = buf + len - 1;
while ((gov > buf) && (isspace(*gov)))
{
*gov = 0;
gov--;
}
}
gov = strtok(buf, " ");
do
{
while ((*gov) && (isspace(*gov)))
gov++;
if (strlen(gov) != 0)
s->governors = eina_list_append(s->governors, strdup(gov));
gov = strtok(NULL, " ");
}
while (gov);
s->governors =
eina_list_sort(s->governors, eina_list_count(s->governors),
(int (*)(const void *, const void *))strcmp);
}
#endif
}
static int
_cpuclock_status_check_current(Cpu_Status *s)
{
int ret = 0;
int frequency = 0;
#if defined (__OpenBSD__)
size_t len = sizeof(frequency);
int percent, mib[] = {CTL_HW, HW_CPUSPEED};
s->active = 0;
_cpuclock_status_check_available(s);
if (sysctl(mib, 2, &frequency, &len, NULL, 0) == 0)
{
frequency *= 1000;
if (frequency != s->cur_frequency) ret = 1;
s->cur_frequency = frequency;
s->active = 1;
}
mib[1] = HW_SETPERF;
if (sysctl(mib, 2, &percent, &len, NULL, 0) == 0)
{
s->cur_percent = percent;
}
s->can_set_frequency = 1;
s->cur_governor = NULL;
#elif defined (__FreeBSD__)
size_t len = sizeof(frequency);
s->active = 0;
/* frequency is stored in dev.cpu.0.freq */
if (sysctlbyname("dev.cpu.0.freq", &frequency, &len, NULL, 0) == 0)
{
frequency *= 1000;
if (frequency != s->cur_frequency) ret = 1;
s->cur_frequency = frequency;
s->active = 1;
}
/* hardcoded for testing */
s->can_set_frequency = 1;
s->cur_governor = NULL;
#else
char buf[4096];
FILE *f;
int frequency_min = 0x7fffffff;
int frequency_max = 0;
int freqtot = 0;
int i;
s->active = 0;
_cpuclock_status_check_available(s);
// average out frequencies of all cores
for (i = 0; i < 64; i++)
{
snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%i/cpufreq/scaling_cur_freq", i);
f = fopen(buf, "r");
if (f)
{
if (fgets(buf, sizeof(buf), f) == NULL)
{
fclose(f);
continue;
}
fclose(f);
frequency = atoi(buf);
if (frequency > frequency_max) frequency_max = frequency;
if (frequency < frequency_min) frequency_min = frequency;
freqtot += frequency;
s->active = 1;
}
else
break;
}
if (i < 1) i = 1;
frequency = freqtot / i;
if (frequency != s->cur_frequency) ret = 1;
if (frequency_min != s->cur_min_frequency) ret = 1;
if (frequency_max != s->cur_max_frequency) ret = 1;
s->cur_frequency = frequency;
s->cur_min_frequency = frequency_min;
s->cur_max_frequency = frequency_max;
// printf("%i | %i %i\n", frequency, frequency_min, frequency_max);
// FIXME: this assumes all cores are on the same governor
f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed", "r");
if (f)
{
s->can_set_frequency = 1;
fclose(f);
}
else
{
s->can_set_frequency = 0;
}
f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r");
if (f)
{
char *p;
if (fgets(buf, sizeof(buf), f) == NULL)
{
fclose(f);
return ret;
}
fclose(f);
for (p = buf; (*p != 0) && (isalnum(*p)); p++) ;
*p = 0;
if ((!s->cur_governor) || (strcmp(buf, s->cur_governor)))
{
ret = 1;
free(s->cur_governor);
s->cur_governor = strdup(buf);
for (i = strlen(s->cur_governor) - 1; i >= 0; i--)
{
if (isspace(s->cur_governor[i]))
s->cur_governor[i] = 0;
else
break;
}
}
}
f = fopen("/sys/devices/system/cpu/intel_pstate/min_perf_pct", "r");
if (f)
{
if (fgets(buf, sizeof(buf), f) != NULL)
{
s->pstate_min = atoi(buf);
s->pstate = 1;
}
fclose(f);
}
f = fopen("/sys/devices/system/cpu/intel_pstate/max_perf_pct", "r");
if (f)
{
if (fgets(buf, sizeof(buf), f) != NULL)
{
s->pstate_max = atoi(buf);
s->pstate = 1;
}
fclose(f);
}
f = fopen("/sys/devices/system/cpu/intel_pstate/no_turbo", "r");
if (f)
{
if (fgets(buf, sizeof(buf), f) != NULL)
{
s->pstate_turbo = atoi(buf);
if (s->pstate_turbo) s->pstate_turbo = 0;
else s->pstate_turbo = 1;
s->pstate = 1;
}
fclose(f);
}
#endif
return ret;
}
static void
_cpuclock_cb_frequency_check_main(void *data, Ecore_Thread *th)
{
Thread_Config *thc = data;
for (;;)
{
Cpu_Status *status;
if (ecore_thread_check(th)) break;
status = _cpuclock_status_new();
if (_cpuclock_status_check_current(status))
ecore_thread_feedback(th, status);
else
_cpuclock_status_free(status);
if (ecore_thread_check(th)) break;
usleep((1000000.0 / 8.0) * (double)thc->interval);
}
E_FREE_FUNC(thc, free);
}
static void
_cpuclock_cb_frequency_check_notify(void *data,
Ecore_Thread *th EINA_UNUSED,
void *msg)
{
Cpu_Status *status = msg;
Eina_Bool freq_changed = EINA_FALSE;
Thread_Config *thc = data;
Instance *inst = thc->inst;
if (inst->cfg->esm != E_SYSINFO_MODULE_CPUCLOCK && inst->cfg->esm != E_SYSINFO_MODULE_SYSINFO) return;
if (!inst->cfg) return;
if ((inst->cfg->cpuclock.status) && (status) &&
(
#ifdef __OpenBSD__
(status->cur_percent != inst->cfg->cpuclock.status->cur_percent ) ||
#endif
(status->cur_frequency != inst->cfg->cpuclock.status->cur_frequency ) ||
(status->cur_min_frequency != inst->cfg->cpuclock.status->cur_min_frequency) ||
(status->cur_max_frequency != inst->cfg->cpuclock.status->cur_max_frequency) ||
(status->can_set_frequency != inst->cfg->cpuclock.status->can_set_frequency)))
freq_changed = EINA_TRUE;
_cpuclock_status_free(inst->cfg->cpuclock.status);
inst->cfg->cpuclock.status = status;
if (freq_changed)
{
_cpuclock_face_update_current(inst);
}
if (inst->cfg->cpuclock.status->active == 0)
elm_layout_signal_emit(inst->cfg->cpuclock.o_gadget, "e,state,disabled", "e");
else if (inst->cfg->cpuclock.status->active == 1)
elm_layout_signal_emit(inst->cfg->cpuclock.o_gadget, "e,state,enabled", "e");
_cpuclock_set_pstate(inst->cfg->cpuclock.pstate_min - 1,
inst->cfg->cpuclock.pstate_max - 1, inst->cfg->cpuclock.status->pstate_turbo);
}
void
_cpuclock_poll_interval_update(Instance *inst)
{
Thread_Config *thc;
if (inst->cfg->cpuclock.frequency_check_thread)
{
ecore_thread_cancel(inst->cfg->cpuclock.frequency_check_thread);
inst->cfg->cpuclock.frequency_check_thread = NULL;
}
thc = E_NEW(Thread_Config, 1);
if (thc)
{
thc->inst = inst;
thc->interval = inst->cfg->cpuclock.poll_interval;
inst->cfg->cpuclock.frequency_check_thread =
ecore_thread_feedback_run(_cpuclock_cb_frequency_check_main,
_cpuclock_cb_frequency_check_notify,
NULL, NULL, thc, EINA_TRUE);
}
e_config_save_queue();
}
static void
_cpuclock_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
{
Instance *inst = data;
if (inst->o_main != event_data) return;
if (inst->cfg->cpuclock.handler)
ecore_event_handler_del(inst->cfg->cpuclock.handler);
if (inst->cfg->cpuclock.frequency_check_thread)
{
ecore_thread_cancel(inst->cfg->cpuclock.frequency_check_thread);
inst->cfg->cpuclock.frequency_check_thread = NULL;
}
if (inst->cfg->cpuclock.governor)
eina_stringshare_del(inst->cfg->cpuclock.governor);
if (inst->cfg->cpuclock.status) _cpuclock_status_free(inst->cfg->cpuclock.status);
sysinfo_config->items = eina_list_remove(sysinfo_config->items, inst->cfg);
E_FREE(inst->cfg);
}
void
sysinfo_cpuclock_remove(Instance *inst)
{
if (inst->cfg->cpuclock.handler)
ecore_event_handler_del(inst->cfg->cpuclock.handler);
if (inst->cfg->cpuclock.frequency_check_thread)
{
ecore_thread_cancel(inst->cfg->cpuclock.frequency_check_thread);
inst->cfg->cpuclock.frequency_check_thread = NULL;
}
if (inst->cfg->cpuclock.governor)
eina_stringshare_del(inst->cfg->cpuclock.governor);
if (inst->cfg->cpuclock.status) _cpuclock_status_free(inst->cfg->cpuclock.status);
}
static void
_cpuclock_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
{
Instance *inst = data;
if (inst->cfg->cpuclock.pstate_min == 0) inst->cfg->cpuclock.pstate_min = 1;
if (inst->cfg->cpuclock.pstate_max == 0) inst->cfg->cpuclock.pstate_max = 101;
inst->cfg->cpuclock.o_gadget = elm_layout_add(inst->o_main);
e_theme_edje_object_set(inst->cfg->cpuclock.o_gadget, "base/theme/modules/cpufreq",
"e/modules/cpufreq/main");
E_EXPAND(inst->cfg->cpuclock.o_gadget);
E_FILL(inst->cfg->cpuclock.o_gadget);
edje_object_signal_callback_add(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), "e,action,governor,next", "*",
_cpuclock_face_cb_set_governor, inst);
edje_object_signal_callback_add(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), "e,action,frequency,increase", "*",
_cpuclock_face_cb_set_frequency, inst);
edje_object_signal_callback_add(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), "e,action,frequency,decrease", "*",
_cpuclock_face_cb_set_frequency, inst);
elm_box_pack_end(inst->o_main, inst->cfg->cpuclock.o_gadget);
evas_object_show(inst->cfg->cpuclock.o_gadget);
evas_object_smart_callback_del_full(obj, "gadget_created", _cpuclock_created_cb, data);
inst->cfg->cpuclock.status = _cpuclock_status_new();
_cpuclock_status_check_available(inst->cfg->cpuclock.status);
_cpuclock_poll_interval_update(inst);
inst->cfg->cpuclock.handler = ecore_event_handler_add(E_EVENT_POWERSAVE_UPDATE,
_cpuclock_event_cb_powersave, inst);
_cpuclock_config_updated(inst);
}
Evas_Object *
sysinfo_cpuclock_create(Evas_Object *parent, Instance *inst)
{
if (inst->cfg->cpuclock.pstate_min == 0) inst->cfg->cpuclock.pstate_min = 1;
if (inst->cfg->cpuclock.pstate_max == 0) inst->cfg->cpuclock.pstate_max = 101;
inst->cfg->cpuclock.o_gadget = elm_layout_add(parent);
e_theme_edje_object_set(inst->cfg->cpuclock.o_gadget, "base/theme/modules/cpufreq",
"e/modules/cpufreq/main");
E_EXPAND(inst->cfg->cpuclock.o_gadget);
E_FILL(inst->cfg->cpuclock.o_gadget);
edje_object_signal_callback_add(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), "e,action,governor,next", "*",
_cpuclock_face_cb_set_governor, inst);
edje_object_signal_callback_add(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), "e,action,frequency,increase", "*",
_cpuclock_face_cb_set_frequency, inst);
edje_object_signal_callback_add(elm_layout_edje_get(inst->cfg->cpuclock.o_gadget), "e,action,frequency,decrease", "*",
_cpuclock_face_cb_set_frequency, inst);
evas_object_show(inst->cfg->cpuclock.o_gadget);
inst->cfg->cpuclock.status = _cpuclock_status_new();
_cpuclock_status_check_available(inst->cfg->cpuclock.status);
_cpuclock_poll_interval_update(inst);
inst->cfg->cpuclock.handler = ecore_event_handler_add(E_EVENT_POWERSAVE_UPDATE,
_cpuclock_event_cb_powersave, inst);
_cpuclock_config_updated(inst);
return inst->cfg->cpuclock.o_gadget;
}
static Config_Item *
_conf_item_get(int *id)
{
Config_Item *ci;
Eina_List *l;
if (*id > 0)
{
EINA_LIST_FOREACH(sysinfo_config->items, l, ci)
if (*id == ci->id && ci->esm == E_SYSINFO_MODULE_CPUCLOCK) return ci;
}
ci = E_NEW(Config_Item, 1);
if (*id != -1)
ci->id = eina_list_count(sysinfo_config->items)+1;
else
ci->id = -1;
ci->esm = E_SYSINFO_MODULE_CPUCLOCK;
ci->cpuclock.poll_interval = 32;
ci->cpuclock.restore_governor = 0;
ci->cpuclock.auto_powersave = 1;
ci->cpuclock.powersave_governor = NULL;
ci->cpuclock.governor = NULL;
ci->cpuclock.pstate_min = 1;
ci->cpuclock.pstate_max = 101;
sysinfo_config->items = eina_list_append(sysinfo_config->items, ci);
return ci;
}
Evas_Object *
cpuclock_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient EINA_UNUSED)
{
Instance *inst;
inst = E_NEW(Instance, 1);
inst->cfg = _conf_item_get(id);
*id = inst->cfg->id;
inst->o_main = elm_box_add(parent);
E_EXPAND(inst->o_main);
evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
evas_object_smart_callback_add(parent, "gadget_created", _cpuclock_created_cb, inst);
evas_object_smart_callback_add(parent, "gadget_removed", _cpuclock_removed_cb, inst);
evas_object_show(inst->o_main);
if (inst->cfg->id < 0) return inst->o_main;
sysinfo_instances =
eina_list_append(sysinfo_instances, inst);
return inst->o_main;
}

View File

@ -0,0 +1,14 @@
#ifndef CPUCLOCK_H
#define CPUCLOCK_H
#include "../sysinfo.h"
void _cpuclock_config_updated(Instance *inst);
int _cpuclock_sysfs_setall(const char *control, const char *value);
int _cpuclock_sysfs_set(const char *control, const char *value);
int _cpuclock_sysfs_pstate(int min, int max, int turbo);
#if defined __OpenBSD__ || defined __FreeBSD__
int _cpuclock_sysctl_frequency(int new_perf)
#endif
#endif

View File

@ -0,0 +1,34 @@
#include "cpuclock.h"
#ifdef __FreeBSD__
# include <sys/sysctl.h>
#endif
#ifdef __OpenBSD__
# include <sys/param.h>
# include <sys/resource.h>
# include <sys/sysctl.h>
#endif
#if defined __OpenBSD__
int
_cpuclock_sysctl_frequency(int new_perf)
{
int mib[] = {CTL_HW, HW_SETPERF};
size_t len = sizeof(new_perf);
if (sysctl(mib, 2, NULL, 0, &new_perf, len) == -1)
return 1;
else
return 0;
}
#elif defined __FreeBSD__
int
_cpuclock_sysctl_frequency(int new_perf)
{
if (sysctlbyname("dev.cpu.0.freq", NULL, NULL, &new_perf, sizeof(new_perf)) == -1)
return 1;
else
return 0;
}
#endif

View File

@ -0,0 +1,72 @@
#include "cpuclock.h"
int
_cpuclock_sysfs_setall(const char *control, const char *value)
{
int num = 0;
char filename[4096];
FILE *f;
while (1)
{
snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/%s", num, control);
f = fopen(filename, "w");
if (!f)
{
return num;
}
fprintf(f, "%s\n", value);
fclose(f);
num++;
}
return 1;
}
int
_cpuclock_sysfs_set(const char *control, const char *value)
{
char filename[4096];
FILE *f;
snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpufreq/%s", control);
f = fopen(filename, "w");
if (!f)
{
if (_cpuclock_sysfs_setall(control, value) > 0)
return 1;
else
return 0;
}
fprintf(f, "%s\n", value);
fclose(f);
return 1;
}
int
_cpuclock_sysfs_pstate(int min, int max, int turbo)
{
FILE *f;
f = fopen("/sys/devices/system/cpu/intel_pstate/min_perf_pct", "w");
if (!f) return 0;
fprintf(f, "%i\n", min);
fclose(f);
f = fopen("/sys/devices/system/cpu/intel_pstate/max_perf_pct", "w");
if (!f) return 0;
fprintf(f, "%i\n", max);
fclose(f);
f = fopen("/sys/devices/system/cpu/intel_pstate/no_turbo", "w");
if (!f) return 0;
fprintf(f, "%i\n", turbo ? 0 : 1);
fclose(f);
return 1;
}

View File

@ -0,0 +1,187 @@
#include "cpumonitor.h"
typedef struct _Thread_Config Thread_Config;
struct _Thread_Config
{
int interval;
Instance *inst;
int status;
};
static void
_cpumonitor_face_update(Instance *inst, int status)
{
Edje_Message_Int_Set *usage_msg;
usage_msg = malloc(sizeof(Edje_Message_Int_Set) + 1 * sizeof(int));
EINA_SAFETY_ON_NULL_RETURN(usage_msg);
usage_msg->count = 1;
usage_msg->val[0] = status;
edje_object_message_send(elm_layout_edje_get(inst->cfg->cpumonitor.o_gadget), EDJE_MESSAGE_INT_SET, 1,
usage_msg);
}
static void
_cpumonitor_cb_usage_check_main(void *data, Ecore_Thread *th)
{
Thread_Config *thc = data;
for (;;)
{
if (ecore_thread_check(th)) break;
thc->status = _cpumonitor_proc_getusage(thc->inst);
ecore_thread_feedback(th, NULL);
if (ecore_thread_check(th)) break;
usleep((1000000.0 / 8.0) * (double)thc->interval);
}
E_FREE_FUNC(thc, free);
}
static void
_cpumonitor_cb_usage_check_notify(void *data,
Ecore_Thread *th EINA_UNUSED,
void *msg EINA_UNUSED)
{
Thread_Config *thc = data;
Instance *inst = thc->inst;
if (inst->cfg->esm != E_SYSINFO_MODULE_CPUMONITOR && inst->cfg->esm != E_SYSINFO_MODULE_SYSINFO) return;
if (!inst->cfg) return;
_cpumonitor_face_update(inst, thc->status);
}
void
_cpumonitor_config_updated(Instance *inst)
{
Thread_Config *thc;
if (inst->cfg->cpumonitor.usage_check_thread)
{
ecore_thread_cancel(inst->cfg->cpumonitor.usage_check_thread);
inst->cfg->cpumonitor.usage_check_thread = NULL;
}
thc = E_NEW(Thread_Config, 1);
if (thc)
{
thc->inst = inst;
thc->interval = inst->cfg->cpumonitor.poll_interval;
thc->status = 0;
inst->cfg->cpumonitor.usage_check_thread =
ecore_thread_feedback_run(_cpumonitor_cb_usage_check_main,
_cpumonitor_cb_usage_check_notify,
NULL, NULL, thc, EINA_TRUE);
}
e_config_save_queue();
}
static void
_cpumonitor_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
{
Instance *inst = data;
if (inst->o_main != event_data) return;
if (inst->cfg->cpumonitor.usage_check_thread)
{
ecore_thread_cancel(inst->cfg->cpumonitor.usage_check_thread);
inst->cfg->cpumonitor.usage_check_thread = NULL;
}
sysinfo_config->items = eina_list_remove(sysinfo_config->items, inst->cfg);
E_FREE(inst->cfg);
}
void
sysinfo_cpumonitor_remove(Instance *inst)
{
if (inst->cfg->cpumonitor.usage_check_thread)
{
ecore_thread_cancel(inst->cfg->cpumonitor.usage_check_thread);
inst->cfg->cpumonitor.usage_check_thread = NULL;
}
}
static void
_cpumonitor_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
{
Instance *inst = data;
inst->cfg->cpumonitor.o_gadget = elm_layout_add(inst->o_main);
e_theme_edje_object_set(inst->cfg->cpumonitor.o_gadget, "base/theme/modules/cpumonitor",
"e/modules/cpumonitor/main");
E_EXPAND(inst->cfg->cpumonitor.o_gadget);
E_FILL(inst->cfg->cpumonitor.o_gadget);
elm_box_pack_end(inst->o_main, inst->cfg->cpumonitor.o_gadget);
evas_object_show(inst->cfg->cpumonitor.o_gadget);
evas_object_smart_callback_del_full(obj, "gadget_created", _cpumonitor_created_cb, data);
_cpumonitor_config_updated(inst);
}
Evas_Object *
sysinfo_cpumonitor_create(Evas_Object *parent, Instance *inst)
{
inst->cfg->cpumonitor.o_gadget = elm_layout_add(parent);
e_theme_edje_object_set(inst->cfg->cpumonitor.o_gadget, "base/theme/modules/cpumonitor",
"e/modules/cpumonitor/main");
E_EXPAND(inst->cfg->cpumonitor.o_gadget);
E_FILL(inst->cfg->cpumonitor.o_gadget);
evas_object_show(inst->cfg->cpumonitor.o_gadget);
_cpumonitor_config_updated(inst);
return inst->cfg->cpumonitor.o_gadget;
}
static Config_Item *
_conf_item_get(int *id)
{
Config_Item *ci;
Eina_List *l;
if (*id > 0)
{
EINA_LIST_FOREACH(sysinfo_config->items, l, ci)
if (*id == ci->id && ci->esm == E_SYSINFO_MODULE_CPUMONITOR) return ci;
}
ci = E_NEW(Config_Item, 1);
if (*id != -1)
ci->id = eina_list_count(sysinfo_config->items)+1;
else
ci->id = -1;
ci->esm = E_SYSINFO_MODULE_CPUMONITOR;
ci->cpumonitor.poll_interval = 32;
ci->cpumonitor.total = 0;
ci->cpumonitor.idle = 0;
sysinfo_config->items = eina_list_append(sysinfo_config->items, ci);
return ci;
}
Evas_Object *
cpumonitor_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient EINA_UNUSED)
{
Instance *inst;
inst = E_NEW(Instance, 1);
inst->cfg = _conf_item_get(id);
*id = inst->cfg->id;
inst->cfg->cpumonitor.total = 0;
inst->cfg->cpumonitor.idle = 0;
inst->o_main = elm_box_add(parent);
E_EXPAND(inst->o_main);
evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
evas_object_smart_callback_add(parent, "gadget_created", _cpumonitor_created_cb, inst);
evas_object_smart_callback_add(parent, "gadget_removed", _cpumonitor_removed_cb, inst);
evas_object_show(inst->o_main);
if (inst->cfg->id < 0) return inst->o_main;
sysinfo_instances =
eina_list_append(sysinfo_instances, inst);
return inst->o_main;
}

View File

@ -0,0 +1,9 @@
#ifndef CPUMONITOR_H
#define CPUMONITOR_H
#include "../sysinfo.h"
void _cpuclock_config_updated(Instance *inst);
int _cpumonitor_proc_getusage(Instance *inst);
#endif

View File

@ -0,0 +1,42 @@
#include "cpumonitor.h"
int _cpumonitor_proc_getusage(Instance *inst)
{
long total = 0, i = 0, idle = 0, use, total_change, idle_change;
int percent = 0;
char buf[4096], *line, *tok;
FILE *f;
f = fopen("/proc/stat", "r");
if (f)
{
if (fgets(buf, sizeof(buf), f) == NULL)
{
fclose(f);
return 0;
}
fclose(f);
line = strchr(buf, ' ')+1;
tok = strtok(line, " ");
while (tok)
{
use = atol(tok);
total += use;
i++;
if (i == 4)
idle = use;
tok = strtok(NULL, " ");
}
}
total_change = total - inst->cfg->cpumonitor.total;
idle_change = idle - inst->cfg->cpumonitor.idle;
if (total_change != 0)
percent = 100 * (1 - ((float)idle_change / (float)total_change));
if (percent > 100) percent = 100;
else if (percent < 0) percent = 0;
inst->cfg->cpumonitor.total = total;
inst->cfg->cpumonitor.idle = idle;
return percent;
}

View File

@ -0,0 +1,191 @@
#include "memusage.h"
typedef struct _Thread_Config Thread_Config;
struct _Thread_Config
{
int interval;
Instance *inst;
int memstatus;
int swapstatus;
};
static void
_memusage_face_update(Instance *inst, Eina_Bool swap, int status)
{
Edje_Message_Int_Set *usage_msg;
usage_msg = malloc(sizeof(Edje_Message_Int_Set) + 1 * sizeof(int));
EINA_SAFETY_ON_NULL_RETURN(usage_msg);
usage_msg->count = 1;
usage_msg->val[0] = status;
if (!swap)
edje_object_message_send(elm_layout_edje_get(inst->cfg->memusage.o_gadget), EDJE_MESSAGE_INT_SET, 1,
usage_msg);
else
edje_object_message_send(elm_layout_edje_get(inst->cfg->memusage.o_gadget), EDJE_MESSAGE_INT_SET, 2,
usage_msg);
}
static void
_memusage_cb_usage_check_main(void *data, Ecore_Thread *th)
{
Thread_Config *thc = data;
for (;;)
{
if (ecore_thread_check(th)) break;
thc->memstatus = _memusage_proc_getmemusage();
thc->swapstatus = _memusage_proc_getswapusage();
ecore_thread_feedback(th, NULL);
if (ecore_thread_check(th)) break;
usleep((1000000.0 / 8.0) * (double)thc->interval);
}
E_FREE_FUNC(thc, free);
}
static void
_memusage_cb_usage_check_notify(void *data,
Ecore_Thread *th EINA_UNUSED,
void *msg EINA_UNUSED)
{
Thread_Config *thc = data;
Instance *inst = thc->inst;
if (inst->cfg->esm != E_SYSINFO_MODULE_MEMUSAGE && inst->cfg->esm != E_SYSINFO_MODULE_SYSINFO) return;
if (!inst->cfg) return;
_memusage_face_update(inst, EINA_FALSE, thc->memstatus);
_memusage_face_update(inst, EINA_TRUE, thc->swapstatus);
}
void
_memusage_config_updated(Instance *inst)
{
Thread_Config *thc;
if (inst->cfg->memusage.usage_check_thread)
{
ecore_thread_cancel(inst->cfg->memusage.usage_check_thread);
inst->cfg->memusage.usage_check_thread = NULL;
}
thc = E_NEW(Thread_Config, 1);
if (thc)
{
thc->inst = inst;
thc->interval = inst->cfg->memusage.poll_interval;
thc->memstatus = 0;
thc->swapstatus = 0;
inst->cfg->memusage.usage_check_thread =
ecore_thread_feedback_run(_memusage_cb_usage_check_main,
_memusage_cb_usage_check_notify,
NULL, NULL, thc, EINA_TRUE);
}
e_config_save_queue();
}
static void
_memusage_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
{
Instance *inst = data;
if (inst->o_main != event_data) return;
if (inst->cfg->memusage.usage_check_thread)
{
ecore_thread_cancel(inst->cfg->memusage.usage_check_thread);
inst->cfg->memusage.usage_check_thread = NULL;
}
sysinfo_config->items = eina_list_remove(sysinfo_config->items, inst->cfg);
E_FREE(inst->cfg);
}
void
sysinfo_memusage_remove(Instance *inst)
{
if (inst->cfg->memusage.usage_check_thread)
{
ecore_thread_cancel(inst->cfg->memusage.usage_check_thread);
inst->cfg->memusage.usage_check_thread = NULL;
}
}
static void
_memusage_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
{
Instance *inst = data;
inst->cfg->memusage.o_gadget = elm_layout_add(inst->o_main);
e_theme_edje_object_set(inst->cfg->memusage.o_gadget, "base/theme/modules/memusage",
"e/modules/memusage/main");
E_EXPAND(inst->cfg->memusage.o_gadget);
E_FILL(inst->cfg->memusage.o_gadget);
elm_box_pack_end(inst->o_main, inst->cfg->memusage.o_gadget);
evas_object_show(inst->cfg->memusage.o_gadget);
evas_object_smart_callback_del_full(obj, "gadget_created", _memusage_created_cb, data);
_memusage_config_updated(inst);
}
Evas_Object *
sysinfo_memusage_create(Evas_Object *parent, Instance *inst)
{
inst->cfg->memusage.o_gadget = elm_layout_add(parent);
e_theme_edje_object_set(inst->cfg->memusage.o_gadget, "base/theme/modules/memusage",
"e/modules/memusage/main");
E_EXPAND(inst->cfg->memusage.o_gadget);
E_FILL(inst->cfg->memusage.o_gadget);
evas_object_show(inst->cfg->memusage.o_gadget);
_memusage_config_updated(inst);
return inst->cfg->memusage.o_gadget;
}
static Config_Item *
_conf_item_get(int *id)
{
Config_Item *ci;
Eina_List *l;
if (*id > 0)
{
EINA_LIST_FOREACH(sysinfo_config->items, l, ci)
if (*id == ci->id && ci->esm == E_SYSINFO_MODULE_MEMUSAGE) return ci;
}
ci = E_NEW(Config_Item, 1);
if (*id != -1)
ci->id = eina_list_count(sysinfo_config->items)+1;
else
ci->id = -1;
ci->esm = E_SYSINFO_MODULE_MEMUSAGE;
ci->memusage.poll_interval = 32;
sysinfo_config->items = eina_list_append(sysinfo_config->items, ci);
return ci;
}
Evas_Object *
memusage_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient EINA_UNUSED)
{
Instance *inst;
inst = E_NEW(Instance, 1);
inst->cfg = _conf_item_get(id);
*id = inst->cfg->id;
inst->o_main = elm_box_add(parent);
E_EXPAND(inst->o_main);
evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
evas_object_smart_callback_add(parent, "gadget_created", _memusage_created_cb, inst);
evas_object_smart_callback_add(parent, "gadget_removed", _memusage_removed_cb, inst);
evas_object_show(inst->o_main);
if (inst->cfg->id < 0) return inst->o_main;
sysinfo_instances =
eina_list_append(sysinfo_instances, inst);
return inst->o_main;
}

View File

@ -0,0 +1,10 @@
#ifndef MEMUSAGE_H
#define MEMUSAGE_H
#include "../sysinfo.h"
void _memusage_config_updated(Instance *inst);
int _memusage_proc_getmemusage();
int _memusage_proc_getswapusage();
#endif

View File

@ -0,0 +1,82 @@
#include "memusage.h"
int _memusage_proc_getswapusage(void)
{
long swap_total = 0, swap_free = 0, swap_used = 0;
int percent = 0;
char buf[4096], *line, *tok;
FILE *f;
f = fopen("/proc/meminfo", "r");
if (f)
{
while(fgets(buf, sizeof(buf), f) != NULL)
{
if (!strncmp("SwapTotal:", buf, 10))
{
line = strchr(buf, ':')+1;
while(isspace(*line)) line++;
tok = strtok(line, " ");
swap_total = atol(tok);
}
else if (!strncmp("SwapFree:", buf, 9))
{
line = strchr(buf, ':')+1;
while(isspace(*line)) line++;
tok = strtok(line, " ");
swap_free = atol(tok);
}
if (swap_total && swap_free)
break;
}
fclose(f);
swap_used = swap_total - swap_free;
percent = 100 * ((float)swap_used / (float)swap_total);
}
if (percent > 100) percent = 100;
else if (percent < 0) percent = 0;
return percent;
}
int _memusage_proc_getmemusage(void)
{
long mem_total = 0, mem_free = 0, mem_used = 0;
int percent = 0;
char buf[4096], *line, *tok;
FILE *f;
f = fopen("/proc/meminfo", "r");
if (f)
{
while(fgets(buf, sizeof(buf), f) != NULL)
{
if (!strncmp("MemTotal:", buf, 9))
{
line = strchr(buf, ':')+1;
while(isspace(*line)) line++;
tok = strtok(line, " ");
mem_total = atol(tok);
}
else if (!strncmp("MemFree:", buf, 8))
{
line = strchr(buf, ':')+1;
while(isspace(*line)) line++;
tok = strtok(line, " ");
mem_free = atol(tok);
}
if (mem_total && mem_free)
break;
}
fclose(f);
mem_used = mem_total - mem_free;
percent = 100 * ((float)mem_used / (float)mem_total);
}
if (percent > 100) percent = 100;
else if (percent < 0) percent = 0;
return percent;
}

View File

@ -0,0 +1,204 @@
#include "netstatus.h"
typedef struct _Thread_Config Thread_Config;
struct _Thread_Config
{
int interval;
Instance *inst;
const char *rstatus;
const char *tstatus;
};
static void
_netstatus_face_update(Instance *inst, Eina_Bool trans, const char *status)
{
if (!trans && status)
{
elm_layout_signal_emit(inst->cfg->netstatus.o_gadget, "e,state,received,active", "e");
elm_layout_text_set(inst->cfg->netstatus.o_gadget, "e.text.received", status);
}
else if (trans && status)
{
elm_layout_signal_emit(inst->cfg->netstatus.o_gadget, "e,state,transmitted,active", "e");
elm_layout_text_set(inst->cfg->netstatus.o_gadget, "e.text.transmitted", status);
}
else if (!trans && !status)
{
elm_layout_signal_emit(inst->cfg->netstatus.o_gadget, "e,state,received,idle", "e");
elm_layout_text_set(inst->cfg->netstatus.o_gadget, "e.text.received", "Rx: 0");
}
else if (trans && !status)
{
elm_layout_signal_emit(inst->cfg->netstatus.o_gadget, "e,state,transmitted,idle", "e");
elm_layout_text_set(inst->cfg->netstatus.o_gadget, "e.text.transmitted", "Tx: 0");
}
}
static void
_netstatus_cb_usage_check_main(void *data, Ecore_Thread *th)
{
Thread_Config *thc = data;
for (;;)
{
if (ecore_thread_check(th)) break;
E_FREE_FUNC(thc->rstatus, eina_stringshare_del);
E_FREE_FUNC(thc->tstatus, eina_stringshare_del);
thc->rstatus = _netstatus_proc_getrstatus(thc->inst);
thc->tstatus = _netstatus_proc_gettstatus(thc->inst);
ecore_thread_feedback(th, NULL);
if (ecore_thread_check(th)) break;
usleep((1000000.0 / 8.0) * (double)thc->interval);
}
E_FREE_FUNC(thc->rstatus, eina_stringshare_del);
E_FREE_FUNC(thc->tstatus, eina_stringshare_del);
E_FREE_FUNC(thc, free);
}
static void
_netstatus_cb_usage_check_notify(void *data,
Ecore_Thread *th EINA_UNUSED,
void *msg EINA_UNUSED)
{
Thread_Config *thc = data;
Instance *inst = thc->inst;
if (inst->cfg->esm != E_SYSINFO_MODULE_NETSTATUS && inst->cfg->esm != E_SYSINFO_MODULE_SYSINFO) return;
if (!inst->cfg) return;
_netstatus_face_update(inst, EINA_FALSE, thc->rstatus);
_netstatus_face_update(inst, EINA_TRUE, thc->tstatus);
}
void
_netstatus_config_updated(Instance *inst)
{
Thread_Config *thc;
if (inst->cfg->netstatus.usage_check_thread)
{
ecore_thread_cancel(inst->cfg->netstatus.usage_check_thread);
inst->cfg->netstatus.usage_check_thread = NULL;
}
thc = E_NEW(Thread_Config, 1);
if (thc)
{
thc->inst = inst;
thc->interval = inst->cfg->netstatus.poll_interval;
inst->cfg->netstatus.usage_check_thread =
ecore_thread_feedback_run(_netstatus_cb_usage_check_main,
_netstatus_cb_usage_check_notify,
NULL, NULL, thc, EINA_TRUE);
}
e_config_save_queue();
}
static void
_netstatus_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
{
Instance *inst = data;
if (inst->o_main != event_data) return;
if (inst->cfg->netstatus.usage_check_thread)
{
ecore_thread_cancel(inst->cfg->netstatus.usage_check_thread);
inst->cfg->netstatus.usage_check_thread = NULL;
}
sysinfo_config->items = eina_list_remove(sysinfo_config->items, inst->cfg);
E_FREE(inst->cfg);
}
void
sysinfo_netstatus_remove(Instance *inst)
{
if (inst->cfg->netstatus.usage_check_thread)
{
ecore_thread_cancel(inst->cfg->netstatus.usage_check_thread);
inst->cfg->netstatus.usage_check_thread = NULL;
}
}
static void
_netstatus_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
{
Instance *inst = data;
inst->cfg->netstatus.o_gadget = elm_layout_add(inst->o_main);
e_theme_edje_object_set(inst->cfg->netstatus.o_gadget, "base/theme/modules/netstatus",
"e/modules/netstatus/main");
E_EXPAND(inst->cfg->netstatus.o_gadget);
E_FILL(inst->cfg->netstatus.o_gadget);
elm_box_pack_end(inst->o_main, inst->cfg->netstatus.o_gadget);
evas_object_show(inst->cfg->netstatus.o_gadget);
evas_object_smart_callback_del_full(obj, "gadget_created", _netstatus_created_cb, data);
_netstatus_config_updated(inst);
}
Evas_Object *
sysinfo_netstatus_create(Evas_Object *parent, Instance *inst)
{
inst->cfg->netstatus.o_gadget = elm_layout_add(parent);
e_theme_edje_object_set(inst->cfg->netstatus.o_gadget, "base/theme/modules/netstatus",
"e/modules/netstatus/main");
E_EXPAND(inst->cfg->netstatus.o_gadget);
E_FILL(inst->cfg->netstatus.o_gadget);
evas_object_show(inst->cfg->netstatus.o_gadget);
_netstatus_config_updated(inst);
return inst->cfg->netstatus.o_gadget;
}
static Config_Item *
_conf_item_get(int *id)
{
Config_Item *ci;
Eina_List *l;
if (*id > 0)
{
EINA_LIST_FOREACH(sysinfo_config->items, l, ci)
if (*id == ci->id && ci->esm == E_SYSINFO_MODULE_NETSTATUS) return ci;
}
ci = E_NEW(Config_Item, 1);
if (*id != -1)
ci->id = eina_list_count(sysinfo_config->items)+1;
else
ci->id = -1;
ci->esm = E_SYSINFO_MODULE_NETSTATUS;
ci->netstatus.poll_interval = 32;
ci->netstatus.in = 0;
ci->netstatus.out = 0;
sysinfo_config->items = eina_list_append(sysinfo_config->items, ci);
return ci;
}
Evas_Object *
netstatus_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient EINA_UNUSED)
{
Instance *inst;
inst = E_NEW(Instance, 1);
inst->cfg = _conf_item_get(id);
*id = inst->cfg->id;
inst->cfg->netstatus.in = 0;
inst->cfg->netstatus.out = 0;
inst->o_main = elm_box_add(parent);
E_EXPAND(inst->o_main);
evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
evas_object_smart_callback_add(parent, "gadget_created", _netstatus_created_cb, inst);
evas_object_smart_callback_add(parent, "gadget_removed", _netstatus_removed_cb, inst);
evas_object_show(inst->o_main);
if (inst->cfg->id < 0) return inst->o_main;
sysinfo_instances =
eina_list_append(sysinfo_instances, inst);
return inst->o_main;
}

View File

@ -0,0 +1,10 @@
#ifndef NETSTATUS_H
#define NETSTATUS_H
#include "../sysinfo.h"
void _netstatus_config_updated(Instance *inst);
const char *_netstatus_proc_getrstatus(Instance *inst);
const char *_netstatus_proc_gettstatus(Instance *inst);
#endif

View File

@ -0,0 +1,78 @@
#include "netstatus.h"
const char *
_netstatus_proc_getrstatus(Instance *inst)
{
long in, dummy, tot_in = 0;
long diffin;
char buf[4096], rin[4096], dummys[64];
FILE *f;
f = fopen("/proc/net/dev", "r");
if (f)
{
while(fgets(buf, sizeof(buf), f) != NULL)
{
if (sscanf (buf, "%s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu "
"%lu %lu %lu %lu\n", dummys, &in, &dummy, &dummy,
&dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy,
&dummy, &dummy, &dummy, &dummy, &dummy, &dummy) < 17)
continue;
tot_in += in;
}
fclose(f);
}
diffin = tot_in - inst->cfg->netstatus.in;
inst->cfg->netstatus.in = tot_in;
if (!diffin) return NULL;
else
{
diffin /= 0.5;
if (diffin > 1048576)
snprintf(rin, sizeof(rin), "Rx: %.2f MB/s", ((float)diffin / 1048576));
else if ((diffin > 1024) && (diffin < 1048576))
snprintf(rin, sizeof(rin), "Rx: %lu KB/s", (diffin / 1024));
else
snprintf(rin, sizeof(rin), "Rx: %lu B/s", diffin);
}
return eina_stringshare_add(rin);
}
const char *
_netstatus_proc_gettstatus(Instance *inst)
{
long out, dummy, tot_out = 0;
long diffout;
char buf[4096], rout[4096], dummys[64];
FILE *f;
f = fopen("/proc/net/dev", "r");
if (f)
{
while(fgets(buf, sizeof(buf), f) != NULL)
{
if (sscanf (buf, "%s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu "
"%lu %lu %lu %lu\n", dummys, &dummy, &dummy, &dummy,
&dummy, &dummy, &dummy, &dummy, &dummy, &out, &dummy,
&dummy, &dummy, &dummy, &dummy, &dummy, &dummy) < 17)
continue;
tot_out += out;
}
fclose(f);
}
diffout = tot_out - inst->cfg->netstatus.out;
inst->cfg->netstatus.out = tot_out;
if (!diffout) return NULL;
else
{
diffout /= 0.5;
if (diffout > 1048576)
snprintf(rout, sizeof(rout), "Tx: %.2f MB/s", ((float)diffout / 1048576));
else if ((diffout > 1024) && (diffout < 1048576))
snprintf(rout, sizeof(rout), "Tx: %lu KB/s", (diffout / 1024));
else
snprintf(rout, sizeof(rout), "Tx: %lu B/s", diffout);
}
return eina_stringshare_add(rout);
}

View File

@ -0,0 +1,306 @@
#include "thermal.h"
static void
_thermal_thread_free(Tempthread *tth)
{
const char *s;
eina_stringshare_del(tth->sensor_name);
eina_stringshare_del(tth->sensor_path);
#ifdef HAVE_EEZE
EINA_LIST_FREE(tth->tempdevs, s) eina_stringshare_del(s);
#endif
free(tth->extn);
free(tth);
}
static void
_thermal_face_level_set(Instance *inst, double level)
{
Edje_Message_Float msg;
if (level < 0.0) level = 0.0;
else if (level > 1.0) level = 1.0;
msg.val = level;
edje_object_message_send(elm_layout_edje_get(inst->cfg->thermal.o_gadget), EDJE_MESSAGE_FLOAT, 1, &msg);
}
static void
_thermal_apply(Instance *inst, int temp)
{
char buf[64];
if (inst->cfg->thermal.temp == temp) return;
inst->cfg->thermal.temp = temp;
if (temp != -999)
{
if (inst->cfg->thermal.units == FAHRENHEIT) temp = (temp * 9.0 / 5.0) + 32;
if (!inst->cfg->thermal.have_temp)
{
/* enable therm object */
elm_layout_signal_emit(inst->cfg->thermal.o_gadget, "e,state,known", "");
inst->cfg->thermal.have_temp = EINA_TRUE;
}
if (inst->cfg->thermal.units == FAHRENHEIT)
snprintf(buf, sizeof(buf), "%i°F", temp);
else
snprintf(buf, sizeof(buf), "%i°C", temp);
_thermal_face_level_set(inst,
(double)(temp - inst->cfg->thermal.low) /
(double)(inst->cfg->thermal.high - inst->cfg->thermal.low));
elm_layout_text_set(inst->cfg->thermal.o_gadget, "e.text.reading", buf);
}
else
{
if (inst->cfg->thermal.have_temp)
{
/* disable therm object */
elm_layout_signal_emit(inst->cfg->thermal.o_gadget, "e,state,unknown", "");
elm_layout_text_set(inst->cfg->thermal.o_gadget, "e.text.reading", "N/A");
_thermal_face_level_set(inst, 0.5);
inst->cfg->thermal.have_temp = EINA_FALSE;
}
}
}
#ifdef HAVE_EEZE
static Eina_Bool
_thermal_udev_poll(void *data)
{
Tempthread *tth = data;
int temp = thermal_udev_get(tth);
_thermal_apply(tth->inst, temp);
return EINA_TRUE;
}
#endif
#if defined __FreeBSD__ || defined __OpenBSD__ || defined __DragonflyBSD__
static void
_thermal_check_sysctl(void *data, Ecore_Thread *th)
{
Tempthread *tth = data;
int ptemp = -500, temp;
for (;;)
{
if (ecore_thread_check(th)) break;
temp = thermal_sysctl_get(tth);
if (ptemp != temp) ecore_thread_feedback(th, (void *)((long)temp));
ptemp = temp;
usleep((1000000.0 / 8.0) * (double)tth->poll_interval);
if (ecore_thread_check(th)) break;
}
}
#endif
#if !defined HAVE_EEZE && !defined __FreeBSD__ && !defined __OpenBSD__ && !defined __DragonflyBSD__
static void
_thermal_check_fallback(void *data, Ecore_Thread *th)
{
Tempthread *tth = data;
int ptemp = -500, temp;
for (;;)
{
if (ecore_thread_check(th)) break;
temp = thermal_fallback_get(tth);
if (ptemp != temp) ecore_thread_feedback(th, (void *)((long)temp));
ptemp = temp;
usleep((1000000.0 / 8.0) * (double)tth->poll_interval);
if (ecore_thread_check(th)) break;
}
}
#endif
#if !defined HAVE_EEZE
static void
_thermal_check_notify(void *data, Ecore_Thread *th, void *msg)
{
Tempthread *tth = data;
Instance *inst = tth->inst;
int temp = (int)((long)msg);
if (th != inst->cfg->thermal.th) return;
_thermal_apply(inst, temp);
}
static void
_thermal_check_done(void *data, Ecore_Thread *th EINA_UNUSED)
{
_thermal_thread_free(data);
}
#endif
void
_thermal_config_updated(Instance *inst)
{
Tempthread *tth;
if (inst->cfg->thermal.th) ecore_thread_cancel(inst->cfg->thermal.th);
tth = calloc(1, sizeof(Tempthread));
tth->poll_interval = inst->cfg->thermal.poll_interval;
tth->sensor_type = inst->cfg->thermal.sensor_type;
tth->inst = inst;
if (inst->cfg->thermal.sensor_name)
tth->sensor_name = eina_stringshare_add(inst->cfg->thermal.sensor_name);
#ifdef HAVE_EEZE
_thermal_udev_poll(tth);
inst->cfg->thermal.poller = ecore_poller_add(ECORE_POLLER_CORE, inst->cfg->thermal.poll_interval,
_thermal_udev_poll, tth);
inst->cfg->thermal.tth = tth;
#elif defined __FreeBSD__ || defined __OpenBSD__ || defined __DragonflyBSD__
inst->cfg->thermal.th = ecore_thread_feedback_run(_thermal_check_sysctl,
_thermal_check_notify,
_thermal_check_done,
_thermal_check_done,
tth, EINA_TRUE);
#else
inst->cfg->thermal.th = ecore_thread_feedback_run(_thermal_check_main,
_thermal_check_notify,
_thermal_check_done,
_thermal_check_done,
tth, EINA_TRUE);
#endif
}
static void
_thermal_face_shutdown(Instance *inst)
{
if (inst->cfg->thermal.th) ecore_thread_cancel(inst->cfg->thermal.th);
if (inst->cfg->thermal.sensor_name) eina_stringshare_del(inst->cfg->thermal.sensor_name);
#ifdef HAVE_EEZE
if (inst->cfg->thermal.poller)
{
ecore_poller_del(inst->cfg->thermal.poller);
_thermal_thread_free(inst->cfg->thermal.tth);
}
#endif
}
static void
_thermal_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
{
Instance *inst = data;
if (inst->o_main != event_data) return;
_thermal_face_shutdown(inst);
#ifdef HAVE_EEZE
eeze_shutdown();
#endif
sysinfo_config->items = eina_list_remove(sysinfo_config->items, inst->cfg);
E_FREE(inst->cfg);
}
void
sysinfo_thermal_remove(Instance *inst)
{
_thermal_face_shutdown(inst);
#ifdef HAVE_EEZE
eeze_shutdown();
#endif
}
static void
_thermal_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
{
Instance *inst = data;
inst->cfg->thermal.temp = 900;
inst->cfg->thermal.have_temp = EINA_FALSE;
inst->cfg->thermal.o_gadget = elm_layout_add(inst->o_main);
e_theme_edje_object_set(inst->cfg->thermal.o_gadget, "base/theme/modules/temperature",
"e/modules/temperature/main");
E_EXPAND(inst->cfg->thermal.o_gadget);
E_FILL(inst->cfg->thermal.o_gadget);
elm_box_pack_end(inst->o_main, inst->cfg->thermal.o_gadget);
evas_object_show(inst->cfg->thermal.o_gadget);
evas_object_smart_callback_del_full(obj, "gadget_created", _thermal_created_cb, data);
_thermal_config_updated(inst);
}
Evas_Object *
sysinfo_thermal_create(Evas_Object *parent, Instance *inst)
{
inst->cfg->thermal.temp = 900;
inst->cfg->thermal.have_temp = EINA_FALSE;
inst->cfg->thermal.o_gadget = elm_layout_add(parent);
e_theme_edje_object_set(inst->cfg->thermal.o_gadget, "base/theme/modules/temperature",
"e/modules/temperature/main");
E_EXPAND(inst->cfg->thermal.o_gadget);
E_FILL(inst->cfg->thermal.o_gadget);
evas_object_show(inst->cfg->thermal.o_gadget);
_thermal_config_updated(inst);
return inst->cfg->thermal.o_gadget;
}
static Config_Item *
_conf_item_get(int *id)
{
Config_Item *ci;
Eina_List *l;
if (*id > 0)
{
EINA_LIST_FOREACH(sysinfo_config->items, l, ci)
if (*id == ci->id && ci->esm == E_SYSINFO_MODULE_THERMAL) return ci;
}
ci = E_NEW(Config_Item, 1);
if (*id != -1)
ci->id = eina_list_count(sysinfo_config->items)+1;
else
ci->id = -1;
ci->esm = E_SYSINFO_MODULE_THERMAL;
ci->thermal.poll_interval = 128;
ci->thermal.low = 30;
ci->thermal.high = 80;
ci->thermal.sensor_type = SENSOR_TYPE_NONE;
ci->thermal.sensor_name = NULL;
ci->thermal.units = CELSIUS;
sysinfo_config->items = eina_list_append(sysinfo_config->items, ci);
return ci;
}
Evas_Object *
thermal_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient EINA_UNUSED)
{
Instance *inst;
inst = E_NEW(Instance, 1);
inst->cfg = _conf_item_get(id);
*id = inst->cfg->id;
inst->o_main = elm_box_add(parent);
E_EXPAND(inst->o_main);
evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
evas_object_smart_callback_add(parent, "gadget_created", _thermal_created_cb, inst);
evas_object_smart_callback_add(parent, "gadget_removed", _thermal_removed_cb, inst);
evas_object_show(inst->o_main);
#ifdef HAVE_EEZE
eeze_init();
#endif
if (inst->cfg->id < 0) return inst->o_main;
sysinfo_instances =
eina_list_append(sysinfo_instances, inst);
return inst->o_main;
}

View File

@ -0,0 +1,17 @@
#ifndef THERMAL_H
#define THERMAL_H
#include "../sysinfo.h"
#ifdef HAVE_EEZE
int thermal_udev_get(Tempthread *tth);
#endif
#if defined __OpenBSD__ || defined __DragonFly__ || defined __FreeBSD__
int thermal_sysctl_get(Tempthread *tth);
#endif
int thermal_fallback_get(Tempthread *tth);
void _thermal_config_updated(Instance *inst);
#endif

View File

@ -0,0 +1,431 @@
#include "thermal.h"
typedef struct
{
int dummy;
} Extn;
Eina_List *
temperature_get_bus_files(const char *bus)
{
Eina_List *result;
Eina_List *therms;
char path[PATH_MAX];
char busdir[PATH_MAX];
char *name;
result = NULL;
snprintf(busdir, sizeof(busdir), "/sys/bus/%s/devices", bus);
/* Look through all the devices for the given bus. */
therms = ecore_file_ls(busdir);
EINA_LIST_FREE(therms, name)
{
Eina_List *files;
char *file;
/* Search each device for temp*_input, these should be
* temperature devices. */
snprintf(path, sizeof(path), "%s/%s", busdir, name);
files = ecore_file_ls(path);
EINA_LIST_FREE(files, file)
{
if ((!strncmp("temp", file, 4)) &&
(!strcmp("_input", &file[strlen(file) - 6])))
{
char *f;
snprintf(path, sizeof(path),
"%s/%s/%s", busdir, name, file);
f = strdup(path);
if (f) result = eina_list_append(result, f);
}
free(file);
}
free(name);
}
return result;
}
static void
init(Tempthread *tth)
{
Eina_List *therms;
char path[512];
Extn *extn;
if (tth->initted) return;
tth->initted = EINA_TRUE;
extn = calloc(1, sizeof(Extn));
tth->extn = extn;
if ((!tth->sensor_type) ||
((!tth->sensor_name) ||
(tth->sensor_name[0] == 0)))
{
eina_stringshare_del(tth->sensor_name);
tth->sensor_name = NULL;
eina_stringshare_del(tth->sensor_path);
tth->sensor_path = NULL;
therms = ecore_file_ls("/proc/acpi/thermal_zone");
if (therms)
{
char *name;
name = eina_list_data_get(therms);
tth->sensor_type = SENSOR_TYPE_LINUX_ACPI;
tth->sensor_name = eina_stringshare_add(name);
eina_list_free(therms);
}
else
{
eina_list_free(therms);
therms = ecore_file_ls("/sys/class/thermal");
if (therms)
{
char *name;
Eina_List *l;
EINA_LIST_FOREACH(therms, l, name)
{
if (!strncmp(name, "thermal", 7))
{
tth->sensor_type = SENSOR_TYPE_LINUX_SYS;
tth->sensor_name = eina_stringshare_add(name);
eina_list_free(therms);
therms = NULL;
break;
}
}
if (therms) eina_list_free(therms);
}
if (therms)
{
if (ecore_file_exists("/proc/omnibook/temperature"))
{
tth->sensor_type = SENSOR_TYPE_OMNIBOOK;
tth->sensor_name = eina_stringshare_add("dummy");
}
else if (ecore_file_exists("/sys/devices/temperatures/sensor1_temperature"))
{
tth->sensor_type = SENSOR_TYPE_LINUX_PBOOK;
tth->sensor_name = eina_stringshare_add("dummy");
}
else if (ecore_file_exists("/sys/devices/temperatures/cpu_temperature"))
{
tth->sensor_type = SENSOR_TYPE_LINUX_MACMINI;
tth->sensor_name = eina_stringshare_add("dummy");
}
else if (ecore_file_exists("/sys/devices/platform/coretemp.0/temp1_input"))
{
tth->sensor_type = SENSOR_TYPE_LINUX_INTELCORETEMP;
tth->sensor_name = eina_stringshare_add("dummy");
}
else if (ecore_file_exists("/sys/devices/platform/thinkpad_hwmon/temp1_input"))
{
tth->sensor_type = SENSOR_TYPE_LINUX_THINKPAD;
tth->sensor_name = eina_stringshare_add("dummy");
}
else
{
// try the i2c bus
therms = temperature_get_bus_files("i2c");
if (therms)
{
char *name;
if ((name = eina_list_data_get(therms)))
{
if (ecore_file_exists(name))
{
int len;
snprintf(path, sizeof(path),
"%s", ecore_file_file_get(name));
len = strlen(path);
if (len > 6) path[len - 6] = '\0';
tth->sensor_type = SENSOR_TYPE_LINUX_I2C;
tth->sensor_path = eina_stringshare_add(name);
tth->sensor_name = eina_stringshare_add(path);
}
}
eina_list_free(therms);
}
if (!tth->sensor_path)
{
// try the pci bus
therms = temperature_get_bus_files("pci");
if (therms)
{
char *name;
if ((name = eina_list_data_get(therms)))
{
if (ecore_file_exists(name))
{
int len;
snprintf(path, sizeof(path),
"%s", ecore_file_file_get(name));
len = strlen(path);
if (len > 6) path[len - 6] = '\0';
tth->sensor_type = SENSOR_TYPE_LINUX_PCI;
tth->sensor_path = eina_stringshare_add(name);
eina_stringshare_del(tth->sensor_name);
tth->sensor_name = eina_stringshare_add(path);
}
}
eina_list_free(therms);
}
}
}
}
}
}
if ((tth->sensor_type) && (tth->sensor_name) && (!tth->sensor_path))
{
char *name;
switch (tth->sensor_type)
{
case SENSOR_TYPE_NONE:
break;
case SENSOR_TYPE_OMNIBOOK:
tth->sensor_path = eina_stringshare_add("/proc/omnibook/temperature");
break;
case SENSOR_TYPE_LINUX_MACMINI:
tth->sensor_path = eina_stringshare_add("/sys/devices/temperatures/cpu_temperature");
break;
case SENSOR_TYPE_LINUX_PBOOK:
tth->sensor_path = eina_stringshare_add("/sys/devices/temperatures/sensor1_temperature");
break;
case SENSOR_TYPE_LINUX_INTELCORETEMP:
tth->sensor_path = eina_stringshare_add("/sys/devices/platform/coretemp.0/temp1_input");
break;
case SENSOR_TYPE_LINUX_THINKPAD:
tth->sensor_path = eina_stringshare_add("/sys/devices/platform/thinkpad_hwmon/temp1_input");
break;
case SENSOR_TYPE_LINUX_I2C:
therms = ecore_file_ls("/sys/bus/i2c/devices");
EINA_LIST_FREE(therms, name)
{
snprintf(path, sizeof(path),
"/sys/bus/i2c/devices/%s/%s_input",
name, tth->sensor_name);
if (ecore_file_exists(path))
{
tth->sensor_path = eina_stringshare_add(path);
/* We really only care about the first
* one for the default. */
break;
}
free(name);
}
break;
case SENSOR_TYPE_LINUX_PCI:
therms = ecore_file_ls("/sys/bus/pci/devices");
EINA_LIST_FREE(therms, name)
{
snprintf(path, sizeof(path),
"/sys/bus/pci/devices/%s/%s_input",
name, tth->sensor_name);
if (ecore_file_exists(path))
{
tth->sensor_path = eina_stringshare_add(path);
/* We really only care about the first
* one for the default. */
break;
}
free(name);
}
break;
case SENSOR_TYPE_LINUX_ACPI:
snprintf(path, sizeof(path),
"/proc/acpi/thermal_zone/%s/temperature",
tth->sensor_name);
tth->sensor_path = eina_stringshare_add(path);
break;
case SENSOR_TYPE_LINUX_SYS:
snprintf(path, sizeof(path),
"/sys/class/thermal/%s/temp", tth->sensor_name);
tth->sensor_path = eina_stringshare_add(path);
break;
default:
break;
}
}
}
static int
check(Tempthread *tth)
{
FILE *f = NULL;
int ret = 0;
int temp = 0;
char buf[512];
/* TODO: Make standard parser. Seems to be two types of temperature string:
* - Somename: <temp> C
* - <temp>
*/
switch (tth->sensor_type)
{
case SENSOR_TYPE_NONE:
/* TODO: Slow down poller? */
break;
case SENSOR_TYPE_OMNIBOOK:
f = fopen(tth->sensor_path, "r");
if (f)
{
char dummy[4096];
fclose(f);
f = NULL;
if (sscanf(buf, "%s %s %i", dummy, dummy, &temp) == 3)
ret = 1;
else
goto error;
}
else
goto error;
break;
case SENSOR_TYPE_LINUX_MACMINI:
case SENSOR_TYPE_LINUX_PBOOK:
f = fopen(tth->sensor_path, "rb");
if (f)
{
if (fgets(buf, sizeof(buf), f) == NULL) goto error;
fclose(f);
f = NULL;
if (sscanf(buf, "%i", &temp) == 1)
ret = 1;
else
goto error;
}
else
goto error;
break;
case SENSOR_TYPE_LINUX_INTELCORETEMP:
case SENSOR_TYPE_LINUX_I2C:
case SENSOR_TYPE_LINUX_THINKPAD:
f = fopen(tth->sensor_path, "r");
if (f)
{
if (fgets(buf, sizeof(buf), f) == NULL) goto error;
fclose(f);
f = NULL;
/* actually read the temp */
if (sscanf(buf, "%i", &temp) == 1)
ret = 1;
else
goto error;
/* Hack for temp */
temp = temp / 1000;
}
else
goto error;
break;
case SENSOR_TYPE_LINUX_PCI:
f = fopen(tth->sensor_path, "r");
if (f)
{
if (fgets(buf, sizeof(buf), f) == NULL) goto error;
fclose(f);
f = NULL;
/* actually read the temp */
if (sscanf(buf, "%i", &temp) == 1)
ret = 1;
else
goto error;
/* Hack for temp */
temp = temp / 1000;
}
else
goto error;
break;
case SENSOR_TYPE_LINUX_ACPI:
f = fopen(tth->sensor_path, "r");
if (f)
{
char *p, *q;
if (fgets(buf, sizeof(buf), f) == NULL) goto error;
fclose(f);
f = NULL;
p = strchr(buf, ':');
if (p)
{
p++;
while (*p == ' ')
p++;
q = strchr(p, ' ');
if (q) *q = 0;
temp = atoi(p);
ret = 1;
}
else
goto error;
}
else
goto error;
break;
case SENSOR_TYPE_LINUX_SYS:
f = fopen(tth->sensor_path, "r");
if (f)
{
if (fgets(buf, sizeof(buf), f) == NULL) goto error;
fclose(f);
f = NULL;
temp = atoi(buf);
temp /= 1000;
ret = 1;
}
else
goto error;
break;
default:
break;
}
if (ret) return temp;
return -999;
error:
if (f) fclose(f);
tth->sensor_type = SENSOR_TYPE_NONE;
eina_stringshare_del(tth->sensor_name);
tth->sensor_name = NULL;
eina_stringshare_del(tth->sensor_path);
tth->sensor_path = NULL;
return -999;
}
int
thermal_fallback_get(Tempthread *tth)
{
int temp;
init(tth);
temp = check(tth);
return temp;
}

View File

@ -0,0 +1,214 @@
#include "thermal.h"
#if defined (__FreeBSD__) || defined(__DragonFly__)
# include <sys/types.h>
# include <sys/sysctl.h>
# include <errno.h>
#endif
#ifdef __OpenBSD__
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/sensors.h>
#include <errno.h>
#include <err.h>
#endif
#if defined (__FreeBSD__) || defined(__DragonFly__) || defined (__OpenBSD__)
typedef struct
{
int mib[CTL_MAXNAME];
#if defined (__FreeBSD__) || defined(__DragonFly__)
unsigned int miblen;
#endif
int dummy;
} Extn;
#if defined (__FreeBSD__) || defined(__DragonFly__)
static const char *sources[] =
{
"hw.acpi.thermal.tz0.temperature",
"dev.cpu.0.temperature",
"dev.aibs.0.temp.0",
"dev.lm75.0.temperature",
NULL
};
#endif
#ifdef __OpenBSD__
static struct sensor snsr;
static size_t slen = sizeof(snsr);
#endif
static void
init(Tempthread *tth)
{
Eina_List *therms;
char path[512];
#ifdef __OpenBSD__
int dev, numt;
struct sensordev snsrdev;
size_t sdlen = sizeof(snsrdev);
#endif
#if defined (__FreeBSD__) || defined(__DragonFly__)
unsigned i;
size_t len;
int rc;
#endif
Extn *extn;
if (tth->initted) return;
tth->initted = EINA_TRUE;
extn = calloc(1, sizeof(Extn));
tth->extn = extn;
if ((!tth->sensor_type) ||
((!tth->sensor_name) ||
(tth->sensor_name[0] == 0)))
{
eina_stringshare_del(tth->sensor_name);
tth->sensor_name = NULL;
eina_stringshare_del(tth->sensor_path);
tth->sensor_path = NULL;
#if defined (__FreeBSD__) || defined(__DragonFly__)
for (i = 0; sources[i]; i++)
{
rc = sysctlbyname(sources[i], NULL, NULL, NULL, 0);
if (rc == 0)
{
tth->sensor_type = SENSOR_TYPE_FREEBSD;
tth->sensor_name = eina_stringshare_add(sources[i]);
break;
}
}
#elif defined(__OpenBSD__)
extn->mib[0] = CTL_HW;
extn->mib[1] = HW_SENSORS;
for (dev = 0;; dev++)
{
extn->mib[2] = dev;
if (sysctl(extn->mib, 3, &snsrdev, &sdlen, NULL, 0) == -1)
{
if (errno == ENOENT) /* no further sensors */
break;
else
continue;
}
if (strcmp(snsrdev.xname, "cpu0") == 0)
{
tth->sensor_type = SENSOR_TYPE_OPENBSD;
tth->sensor_name = strdup("cpu0");
break;
}
else if (strcmp(snsrdev.xname, "km0") == 0)
{
tth->sensor_type = SENSOR_TYPE_OPENBSD;
tth->sensor_name = strdup("km0");
break;
}
}
#endif
}
if ((tth->sensor_type) && (tth->sensor_name) && (!tth->sensor_path))
{
char *name;
if (tth->sensor_type == SENSOR_TYPE_FREEBSD)
{
#if defined (__FreeBSD__) || defined(__DragonFly__)
len = sizeof(extn->mib) / sizeof(extn->mib[0]);
rc = sysctlnametomib(tth->sensor_name, extn->mib, &len);
if (rc == 0)
{
extn->miblen = len;
tth->sensor_path = eina_stringshare_add(tth->sensor_name);
}
#endif
}
else if (tth->sensor_type == SENSOR_TYPE_OPENBSD)
{
#ifdef __OpenBSD__
for (numt = 0; numt < snsrdev.maxnumt[SENSOR_TEMP]; numt++)
{
extn->mib[4] = numt;
slen = sizeof(snsr);
if (sysctl(extn->mib, 5, &snsr, &slen, NULL, 0) == -1)
continue;
if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0)
{
break;
}
}
#endif
}
}
}
static int
check(Tempthread *tth)
{
FILE *f = NULL;
int ret = 0;
int temp = 0;
char buf[512];
#if defined (__FreeBSD__) || defined(__DragonFly__)
size_t len;
size_t ftemp = 0;
#endif
#if defined (__FreeBSD__) || defined(__DragonFly__) || defined (__OpenBSD__)
Extn *extn = tth->extn;
#endif
/* TODO: Make standard parser. Seems to be two types of temperature string:
* - Somename: <temp> C
* - <temp>
*/
if (tth->sensor_type == SENSOR_TYPE_FREEBSD)
{
#if defined (__FreeBSD__) || defined(__DragonFly__)
len = sizeof(ftemp);
if (sysctl(extn->mib, extn->miblen, &ftemp, &len, NULL, 0) == 0)
{
temp = (ftemp - 2732) / 10;
ret = 1;
}
else
goto error;
#endif
else if (tth->sensor_type == SENSOR_TYPE_OPENBSD)
{
#ifdef __OpenBSD_
if (sysctl(extn->mib, 5, &snsr, &slen, NULL, 0) != -1)
{
temp = (snsr.value - 273150000) / 1000000.0;
ret = 1;
}
else
goto error;
#endif
}
if (ret) return temp;
return -999;
error:
if (f) fclose(f);
tth->sensor_type = SENSOR_TYPE_NONE;
eina_stringshare_del(tth->sensor_name);
tth->sensor_name = NULL;
eina_stringshare_del(tth->sensor_path);
tth->sensor_path = NULL;
return -999;
}
int
thermal_sysctl_get(Tempthread *tth)
{
int temp;
init(tth);
temp = check(tth);
return temp;
}
#endif

View File

@ -0,0 +1,50 @@
#include "thermal.h"
int
thermal_udev_get(Tempthread *tth)
{
Eina_List *l;
double cur, temp;
char *syspath;
const char *test;
char buf[256];
int x, y, cpus = 0;
temp = -999;
if (!tth->tempdevs)
tth->tempdevs =
eeze_udev_find_by_type(EEZE_UDEV_TYPE_IS_IT_HOT_OR_IS_IT_COLD_SENSOR,
NULL);
if (tth->tempdevs)
{
temp = 0;
EINA_LIST_FOREACH(tth->tempdevs, l, syspath)
{
for (x = 1, y = 0; x < 15; x++)
{
if (y >= 2) break;
sprintf(buf, "temp%d_input", x);
if ((test = eeze_udev_syspath_get_sysattr(syspath, buf)))
{
y = 0;
cur = atoi(test);
if (cur > 0)
{
/* udev reports temp in (celsius * 1000) */
temp += (cur / 1000);
cpus++;
}
}
/* keep checking for sensors until 2 in a row don't exist */
else y++;
}
}
if (cpus > 0)
{
temp /= (double)cpus;
return temp;
}
}
return -999;
}