You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
397 lines
11 KiB
397 lines
11 KiB
#include "batman.h" |
|
|
|
#define BUS "org.freedesktop.UPower" |
|
#define PATH "/org/freedesktop/UPower" |
|
#define IFACE "org.freedesktop.UPower" |
|
|
|
EINTERN extern Eina_List *batman_device_batteries; |
|
EINTERN extern Eina_List *batman_device_ac_adapters; |
|
EINTERN 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, const Eldbus_Message *msg) |
|
{ |
|
Battery *bat; |
|
Ac_Adapter *ac; |
|
const char *path; |
|
Instance *inst = data; |
|
Eina_List *batteries, *adapters, *l; |
|
Eina_Bool exists = EINA_FALSE; |
|
|
|
if (!eldbus_message_arguments_get(msg, "o", &path)) |
|
return; |
|
batteries = _batman_battery_find(path); |
|
if (eina_list_count(batteries)) |
|
{ |
|
EINA_LIST_FOREACH(batteries, l, bat) |
|
{ |
|
if (inst == bat->inst) |
|
{ |
|
inst = bat->inst; |
|
_battery_free(bat); |
|
_batman_device_update(inst); |
|
exists = EINA_TRUE; |
|
} |
|
} |
|
if (exists) |
|
{ |
|
eina_list_free(batteries); |
|
return; |
|
} |
|
} |
|
exists = EINA_FALSE; |
|
adapters = _batman_ac_adapter_get(path); |
|
if (eina_list_count(adapters)) |
|
{ |
|
EINA_LIST_FOREACH(adapters, l, ac) |
|
{ |
|
if (ac->inst == inst) |
|
{ |
|
inst = ac->inst; |
|
_ac_free(ac); |
|
_batman_device_update(inst); |
|
exists = EINA_TRUE; |
|
} |
|
} |
|
eina_list_free(adapters); |
|
} |
|
} |
|
|
|
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, inst); |
|
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); |
|
}
|
|
|