forked from enlightenment/enlightenment
Enlightenment: Sysinfo gadget supporting files
This commit is contained in:
parent
cd24662e9f
commit
b51b591171
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue