enlightenment/src/modules/bluez5/bz_obj.c

930 lines
24 KiB
C

#include "bz.h"
#include "e_mod_main.h"
static Eldbus_Object *objman_obj = NULL;
static Eldbus_Proxy *objman_proxy = NULL;
static Eldbus_Signal_Handler *sig_ifadd = NULL;
static Eldbus_Signal_Handler *sig_ifdel = NULL;
static Eldbus_Pending *pend_getobj = NULL;
static Eina_Hash *obj_table = NULL;
static void (*fn_obj_add) (Obj *o) = NULL;
/*
static void
cb_obj_prop_mandata(void *data, const void *key, Eldbus_Message_Iter *var)
{
Obj *o = data;
unsigned short *skey = key;
printf(" M KEY %x\n", (int)*skey);
}
*/
static void
cb_obj_prop_entry(void *data, const void *key, Eldbus_Message_Iter *var)
{
Obj *o = data;
const char *skey = key;
if (!strcmp(skey, "Paired"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->paired = val;
}
if (!strcmp(skey, "Connected"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->connected = val;
}
if (!strcmp(skey, "Trusted"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->trusted = val;
}
if (!strcmp(skey, "Blocked"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->blocked = val;
}
if (!strcmp(skey, "LegacyPairing"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->legacy_pairing = val;
}
if (!strcmp(skey, "ServicesResolved"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->services_resolved = val;
}
if (!strcmp(skey, "Address"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->address = eina_stringshare_add(val);
}
if (!strcmp(skey, "AddressType"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->address_type = eina_stringshare_add(val);
}
if (!strcmp(skey, "Name"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->name = eina_stringshare_add(val);
}
if (!strcmp(skey, "Icon"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->icon = eina_stringshare_add(val);
}
if (!strcmp(skey, "Alias"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->alias = eina_stringshare_add(val);
}
if (!strcmp(skey, "Modalias"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->modalias = eina_stringshare_add(val);
}
if (!strcmp(skey, "Adapter"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "o", &val))
o->adapter = eina_stringshare_add(val);
}
if (!strcmp(skey, "Class"))
{
unsigned int val = 0;
if (eldbus_message_iter_arguments_get(var, "u", &val))
o->klass = val;
}
if (!strcmp(skey, "Appearance"))
{
unsigned short val = 0;
if (eldbus_message_iter_arguments_get(var, "q", &val))
o->appearance = val;
}
if (!strcmp(skey, "RSSI"))
{
short val = 0;
if (eldbus_message_iter_arguments_get(var, "n", &val))
o->rssi = val;
}
if (!strcmp(skey, "TxPower"))
{
unsigned short val = 0;
if (eldbus_message_iter_arguments_get(var, "n", &val))
o->txpower = val;
}
if (!strcmp(skey, "UUIDs"))
{
Eldbus_Message_Iter *array = NULL;
if (eldbus_message_iter_arguments_get(var, "as", &array))
{
const char *val = NULL;
while (eldbus_message_iter_get_and_next(array, 's', &val))
{
if (!o->uuids) o->uuids = eina_array_new(1);
eina_array_push(o->uuids, eina_stringshare_add(val));
}
}
}
if (!strcmp(skey, "Discoverable"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->discoverable = val;
}
if (!strcmp(skey, "Discovering"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->discovering = val;
}
if (!strcmp(skey, "Pairable"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->pairable = val;
}
if (!strcmp(skey, "Powered"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->powered = val;
}
if (!strcmp(skey, "DiscoverableTimeout"))
{
unsigned int val = 0;
if (eldbus_message_iter_arguments_get(var, "u", &val))
o->discoverable_timeout = val;
}
if (!strcmp(skey, "PairableTimeout"))
{
unsigned int val = 0;
if (eldbus_message_iter_arguments_get(var, "u", &val))
o->pairable_timeout = val;
}
// dict ManufacturerData [readonly, optional]
// Manufacturer specific advertisement data. Keys are
// 16 bits Manufacturer ID followed by its byte array
// value.
/*
if (!strcmp(skey, "ManufacturerData"))
{
Eldbus_Message_Iter *array = NULL;
if (eldbus_message_iter_arguments_get(var, "a{qv}", &array))
eldbus_message_iter_dict_iterate(array, "qv", cb_obj_prop_mandata, o);
}
*/
// dict ServiceData [readonly, optional]
// Service advertisement data. Keys are the UUIDs in
// string format followed by its byte array value.
//
// array{byte} AdvertisingFlags [readonly, experimental]
// The Advertising Data Flags of the remote device.
//
// dict AdvertisingData [readonly, experimental]
// The Advertising Data of the remote device. Keys are
// are 8 bits AD Type followed by data as byte array.
}
static void
_obj_clear(Obj *o)
{
o->paired = EINA_FALSE;
o->connected = EINA_FALSE;
o->trusted = EINA_FALSE;
o->blocked = EINA_FALSE;
o->legacy_pairing = EINA_FALSE;
o->services_resolved = EINA_FALSE;
eina_stringshare_del(o->address);
o->address = NULL;
eina_stringshare_del(o->address_type);
o->address_type = NULL;
eina_stringshare_del(o->name);
o->name = NULL;
eina_stringshare_del(o->icon);
o->icon = NULL;
eina_stringshare_del(o->alias);
o->alias = NULL;
eina_stringshare_del(o->adapter);
o->adapter = NULL;
eina_stringshare_del(o->modalias);
o->modalias = NULL;
eina_stringshare_del(o->modalias);
o->modalias = NULL;
o->klass = 0;
o->appearance = 0;
o->txpower = 0;
o->rssi = 0;
if (o->uuids)
{
const char *val;
while ((val = eina_array_pop(o->uuids)))
eina_stringshare_del(val);
eina_array_free(o->uuids);
o->uuids = NULL;
}
}
#define ERR_PRINT(str) \
do { const char *name, *text; \
if (eldbus_message_error_get(msg, &name, &text)) { \
printf("Error: %s.\n %s:\n %s\n", str, name, text); \
return; \
} \
} while(0)
static void
cb_obj_prop(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
Obj *o = data;
Eldbus_Message_Iter *array;
if (eldbus_message_error_get(msg, NULL, NULL)) return;
_obj_clear(o);
if (eldbus_message_arguments_get(msg, "a{sv}", &array))
eldbus_message_iter_dict_iterate(array, "sv", cb_obj_prop_entry, o);
bz_obj_ref(o);
if ((o->powered) && (o->path))
{
const char *s = strrchr(o->path, '/');
if (s) ebluez5_rfkill_unblock(s + 1);
}
if (!o->add_called)
{
o->add_called = EINA_TRUE;
if (fn_obj_add) fn_obj_add(o);
}
if (o->fn_change) o->fn_change(o);
bz_obj_unref(o);
}
static void
cb_obj_prop_changed(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
{
Obj *o = data;
if (!o->proxy) return;
eldbus_proxy_property_get_all(o->proxy, cb_obj_prop, o);
}
//static void
//cb_obj_discovery_filter(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
//{
// ERR_PRINT("Discovery Filter Clear");
//}
Obj *
bz_obj_add(const char *path)
{
Obj *o = calloc(1, sizeof(Obj));
o->ref = 1;
o->path = eina_stringshare_add(path);
o->obj = eldbus_object_get(bz_conn, "org.bluez", o->path);
o->type = BZ_OBJ_UNKNOWN;
o->in_table = EINA_TRUE;
eina_hash_add(obj_table, o->path, o);
if (!strcmp(o->path, "/org/bluez"))
{
o->proxy = eldbus_proxy_get(o->obj, "org.bluez.AgentManager1");
o->type = BZ_OBJ_BLUEZ;
o->add_called = EINA_TRUE;
bz_obj_ref(o);
if (fn_obj_add) fn_obj_add(o);
bz_obj_unref(o);
goto done;
}
// all devices are /org/bluez/XXX/dev_XXX so look for /dev_
else if (strstr(o->path, "/dev_"))
{
o->proxy = eldbus_proxy_get(o->obj, "org.bluez.Device1");
o->type = BZ_OBJ_DEVICE;
if (o->proxy)
{
eldbus_proxy_property_get_all(o->proxy, cb_obj_prop, o);
o->prop_proxy = eldbus_proxy_get(o->obj,
"org.freedesktop.DBus.Properties");
if (o->prop_proxy)
o->prop_sig = eldbus_proxy_signal_handler_add(o->prop_proxy,
"PropertiesChanged",
cb_obj_prop_changed, o);
}
goto done;
}
// all dadapters begin with /org/bluez/
else if (!strncmp(o->path, "/org/bluez/", 11))
{
o->proxy = eldbus_proxy_get(o->obj, "org.bluez.Adapter1");
o->type = BZ_OBJ_ADAPTER;
if (o->proxy)
{
eldbus_proxy_property_get_all(o->proxy, cb_obj_prop, o);
o->prop_proxy = eldbus_proxy_get(o->obj,
"org.freedesktop.DBus.Properties");
if (o->prop_proxy)
o->prop_sig = eldbus_proxy_signal_handler_add(o->prop_proxy,
"PropertiesChanged",
cb_obj_prop_changed, o);
// disable the filter for discovery later
// XXX: this doesnt seem to exist on the bluez daemons i see
// so don't do this to avoid error noise and it's useless it seems
// eldbus_proxy_call
// (o->proxy, "SetDiscoveryFilter", cb_obj_discovery_filter, o, -1, "");
}
goto done;
}
done:
return o;
}
Obj *
bz_obj_find(const char *path)
{
return eina_hash_find(obj_table, path);
}
static void
cb_power_on(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Power On");
}
void
bz_obj_power_on(Obj *o)
{
Eina_Bool val = EINA_TRUE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Powered", "b", (void *)(uintptr_t)val, cb_power_on, o);
}
static void
cb_power_off(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Power Off");
}
void
bz_obj_power_off(Obj *o)
{
Eina_Bool val = EINA_FALSE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Powered", "b", (void *)(uintptr_t)val, cb_power_off, o);
}
static void
cb_discoverable(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Discoverable");
}
void
bz_obj_discoverable(Obj *o)
{
Eina_Bool val = EINA_TRUE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Discoverable", "b", (void *)(uintptr_t)val, cb_discoverable, o);
}
static void
cb_undiscoverable(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Undiscoverable");
}
void
bz_obj_undiscoverable(Obj *o)
{
Eina_Bool val = EINA_FALSE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Discoverable", "b", (void *)(uintptr_t)val, cb_undiscoverable, o);
}
static void
cb_pairable(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Pairable");
}
void
bz_obj_pairable(Obj *o)
{
Eina_Bool val = EINA_TRUE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Pairable", "b", (void *)(uintptr_t)val, cb_pairable, o);
}
static void
cb_unpairable(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Unpairable");
}
void
bz_obj_unpairable(Obj *o)
{
Eina_Bool val = EINA_FALSE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Pairable", "b", (void *)(uintptr_t)val, cb_unpairable, o);
}
static void
cb_trust(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Trust");
}
void
bz_obj_trust(Obj *o)
{
Eina_Bool val = EINA_TRUE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Trusted", "b", (void *)(uintptr_t)val, cb_trust, o);
}
static void
cb_distrust(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Distrust");
}
void
bz_obj_distrust(Obj *o)
{
Eina_Bool val = EINA_FALSE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Trusted", "b", (void *)(uintptr_t)val, cb_distrust, o);
}
static void
cb_pair(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Pair");
}
void
bz_obj_pair(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call(o->proxy, "Pair", cb_pair, o, -1, "");
}
static void
cb_pair_cancel(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Pair Cancel");
}
void
bz_obj_pair_cancel(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "CancelPairing", cb_pair_cancel, o, -1, "");
}
static void
cb_connect(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Connect");
}
void
bz_obj_connect(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "Connect", cb_connect, o, -1, "");
}
static void
cb_disconnect(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Disconnect");
}
void
bz_obj_disconnect(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "Disconnect", cb_disconnect, o, -1, "");
}
static void
_cb_l2ping(void *data, const char *params)
{
Obj *o = data;
char addr[256];
int timeout = 0;
if (sscanf(params, "%255s %i", addr, &timeout) == 2)
{
if (!strcmp(o->address, addr))
{
if (o->ping_busy)
{
e_system_handler_del("l2ping-ping", _cb_l2ping, o);
o->ping_busy = EINA_FALSE;
}
if (timeout >= 0)
{
if (!o->ping_ok)
{
printf("@@@PING SUCCEED\n");
o->ping_ok = EINA_TRUE;
if (o->fn_change) o->fn_change(o);
}
}
else
{
if (o->ping_ok)
{
printf("@@@PING FAIL\n");
o->ping_ok = EINA_FALSE;
if (o->fn_change) o->fn_change(o);
}
}
}
}
}
static int
ping_powersave_timeout_get(void)
{
int timeout = 10;
E_Powersave_Mode pm = e_powersave_mode_get();
if (pm <= E_POWERSAVE_MODE_LOW) timeout = 5;
else if (pm <= E_POWERSAVE_MODE_MEDIUM) timeout = 8;
else if (pm <= E_POWERSAVE_MODE_HIGH) timeout = 12;
else if (pm <= E_POWERSAVE_MODE_EXTREME) timeout = 30;
return timeout;
}
static void
ping_do(Obj *o)
{
int timeout = 1000 * ping_powersave_timeout_get();
if (o->ping_busy)
e_system_handler_del("l2ping-ping", _cb_l2ping, o);
o->ping_busy = EINA_TRUE;
e_system_handler_add("l2ping-ping", _cb_l2ping, o);
e_system_send("l2ping-ping", "%s %i", o->address, timeout);
printf("@@@ run new ping %s %i\n", o->address, timeout);
}
static Eina_Bool cb_ping_timer(void *data);
static void
ping_schedule(Obj *o)
{
double timeout = ping_powersave_timeout_get() + 1.0;
if (o->ping_timer) ecore_timer_del(o->ping_timer);
o->ping_timer = ecore_timer_add(timeout, cb_ping_timer, o);
}
static Eina_Bool
cb_ping_timer(void *data)
{
Obj *o = data;
printf("@@@ ping timer %s\n", o->address);
if (o->ping_busy)
{
o->ping_busy = EINA_FALSE;
e_system_handler_del("l2ping-ping", _cb_l2ping, o);
if (o->ping_ok)
{
o->ping_ok = EINA_FALSE;
if (o->fn_change) o->fn_change(o);
}
}
ping_do(o);
ping_schedule(o);
return EINA_TRUE;
}
void
bz_obj_ping_begin(Obj *o)
{
if (o->ping_timer) return;
if (o->ping_busy)
{
o->ping_busy = EINA_FALSE;
e_system_handler_del("l2ping-ping", _cb_l2ping, o);
}
ping_do(o);
ping_schedule(o);
}
void
bz_obj_ping_end(Obj *o)
{
if (o->ping_timer)
{
ecore_timer_del(o->ping_timer);
o->ping_timer = NULL;
}
if (o->ping_busy)
{
o->ping_busy = EINA_FALSE;
e_system_handler_del("l2ping-ping", _cb_l2ping, o);
}
if (o->ping_ok)
{
printf("@@@PING END %s\n", o->address);
o->ping_ok = EINA_FALSE;
if (o->fn_change) o->fn_change(o);
}
}
static void
cb_remove(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Remove");
}
/*
void
bz_obj_profile_connect(Obj *o, const char *uuid)
{
if (!o->proxy) return;
eldbus_proxy_call(o->proxy, "ConnectProfile", NULL, NULL, -1, "s", uuid);
}
void
bz_obj_profile_disconnect(Obj *o, const char *uuid)
{
if (!o->proxy) return;
eldbus_proxy_call(o->proxy, "DisconnectProfile", NULL, NULL, -1, "s", uuid);
}
*/
void
bz_obj_remove(Obj *o)
{
if (o->adapter)
{
Obj *adapter = bz_obj_find(o->adapter);
if (adapter)
{
if (!adapter->proxy) return;
eldbus_proxy_call(adapter->proxy, "RemoveDevice",
cb_remove, adapter, -1,
"o", o->path);
}
}
}
void
bz_obj_ref(Obj *o)
{
o->ref++;
}
void
bz_obj_unref(Obj *o)
{
o->ref--;
if (o->ref > 0) return;
if (o->in_table)
{
o->in_table = EINA_FALSE;
eina_hash_del(obj_table, o->path, o);
}
if (o->ping_busy)
{
o->ping_busy = EINA_FALSE;
e_system_handler_del("l2ping-ping", _cb_l2ping, o);
}
_obj_clear(o);
if (o->prop_sig)
{
eldbus_signal_handler_del(o->prop_sig);
o->prop_sig = NULL;
}
if (o->path)
{
eina_stringshare_del(o->path);
o->path = NULL;
}
if (o->agent_request)
{
eina_stringshare_del(o->agent_request);
o->agent_request = NULL;
}
if (o->agent_msg_err)
{
bz_agent_msg_drop(o->agent_msg_err);
o->agent_msg_err = NULL;
}
if (o->agent_msg_ok)
{
bz_agent_msg_drop(o->agent_msg_ok);
o->agent_msg_ok = NULL;
}
if (o->ping_timer)
{
ecore_timer_del(o->ping_timer);
o->ping_timer = NULL;
}
if (o->proxy)
{
eldbus_proxy_unref(o->proxy);
o->proxy = NULL;
}
if (o->prop_proxy)
{
eldbus_proxy_unref(o->prop_proxy);
o->prop_proxy = NULL;
}
if (o->obj)
{
eldbus_object_unref(o->obj);
o->obj = NULL;
}
free(o);
}
static void
cb_discovery_start(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Discovery Start");
}
void
bz_obj_discover_start(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "StartDiscovery", cb_discovery_start, o, -1, "");
}
static void
cb_discovery_stop(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Discovery Stop");
}
void
bz_obj_discover_stop(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "StopDiscovery", cb_discovery_stop, o, -1, "");
}
void
bz_obj_agent_request(Obj *o, const char *req, void (*fn) (Eldbus_Message *msg, const char *str), Eldbus_Message *msg_ok, Eldbus_Message *msg_err)
{
if (o->agent_msg_ok) bz_agent_msg_drop(o->agent_msg_ok);
if (o->agent_msg_err) bz_agent_msg_reply(o->agent_msg_err);
o->agent_msg_ok = msg_ok;
o->agent_msg_err = msg_err;
o->agent_entry_fn = fn;
o->agent_alert = EINA_TRUE;
eina_stringshare_replace(&(o->agent_request), req);
bz_obj_ref(o);
if (o->fn_change) o->fn_change(o);
bz_obj_unref(o);
}
static void
cb_obj_add(void *data EINA_UNUSED, const Eldbus_Message *msg)
{
const char *path = NULL;
if (!eldbus_message_arguments_get(msg, "o", &path)) return;
if (bz_obj_find(path)) return;
bz_obj_add(path);
}
static void
cb_obj_del(void *data EINA_UNUSED, const Eldbus_Message *msg)
{
Obj *o;
const char *path = NULL;
if (!eldbus_message_arguments_get(msg, "o", &path)) return;
o = bz_obj_find(path);
if (o)
{
bz_obj_ref(o);
if (o->fn_del) o->fn_del(o);
bz_obj_unref(o);
bz_obj_unref(o);
}
}
static void
cb_getobj(void *data EINA_UNUSED, const Eldbus_Message *msg,
Eldbus_Pending *pending EINA_UNUSED)
{
Eldbus_Message_Iter *prop, *dict;
pend_getobj = NULL;
ERR_PRINT("Get Objects");
if (eldbus_message_arguments_get(msg, "a{oa{sa{sv}}}", &prop))
{
while (eldbus_message_iter_get_and_next(prop, 'e', &dict))
{
const char *path;
path = NULL;
if (!eldbus_message_iter_arguments_get(dict, "o", &path))
{
return;
}
bz_obj_add(path);
}
}
}
static void
_obj_hash_free(Obj *o)
{
o->in_table = 0;
bz_obj_unref(o);
}
void
bz_obj_init(void)
{
obj_table = eina_hash_string_superfast_new((void *)_obj_hash_free);
objman_obj = eldbus_object_get(bz_conn, "org.bluez", "/");
objman_proxy = eldbus_proxy_get(objman_obj, "org.freedesktop.DBus.ObjectManager");
sig_ifadd = eldbus_proxy_signal_handler_add(objman_proxy, "InterfacesAdded",
cb_obj_add, NULL);
sig_ifdel = eldbus_proxy_signal_handler_add(objman_proxy, "InterfacesRemoved",
cb_obj_del, NULL);
pend_getobj = eldbus_proxy_call(objman_proxy, "GetManagedObjects",
cb_getobj, NULL, -1, "");
}
void
bz_obj_shutdown(void)
{
eina_hash_free(obj_table);
obj_table = NULL;
if (pend_getobj)
{
eldbus_pending_cancel(pend_getobj);
pend_getobj = NULL;
}
if (sig_ifadd)
{
eldbus_signal_handler_del(sig_ifadd);
sig_ifadd = NULL;
}
if (sig_ifdel)
{
eldbus_signal_handler_del(sig_ifdel);
sig_ifdel = NULL;
}
if (objman_proxy)
{
eldbus_proxy_unref(objman_proxy);
objman_proxy = NULL;
}
if (objman_obj)
{
eldbus_object_unref(objman_obj);
objman_obj = NULL;
}
}
void
bz_obj_add_func_set(void (*fn) (Obj *o))
{
fn_obj_add = fn;
}