aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac11
-rw-r--r--src/modules/Makefile.am4
-rw-r--r--src/modules/Makefile_bluez4.am22
-rw-r--r--src/modules/bluez4/agent.c133
-rw-r--r--src/modules/bluez4/agent.h6
-rw-r--r--src/modules/bluez4/e-module-bluez4.edjbin0 -> 56750 bytes
-rw-r--r--src/modules/bluez4/e_mod_main.c235
-rw-r--r--src/modules/bluez4/e_mod_main.h21
-rw-r--r--src/modules/bluez4/ebluez4.c216
-rw-r--r--src/modules/bluez4/ebluez4.h27
-rw-r--r--src/modules/bluez4/module.desktop.in6
11 files changed, 681 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 94d97a305..121c904fd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -799,6 +799,15 @@ dnl AC_E_CHECK_PKG(DUMMY, [ connman >= 1.0 ], [], [CONNMAN=false])
AC_SUBST(ECONNMAN_CFLAGS)
AC_SUBST(ECONNMAN_LIBS)
+AM_CONDITIONAL(HAVE_BLUEZ4, false)
+AM_CONDITIONAL(HAVE_DUMMY, false)
+define([CHECK_MODULE_BLUEZ4],
+[
+ AC_E_CHECK_PKG(BLUEZ4, [ edbus2 ],)
+])
+AC_SUBST(EBLUEZ4_CFLAGS)
+AC_SUBST(EBLUEZ4_LIBS)
+
have_wayland_clients=no
AC_ARG_ENABLE([wayland-clients],
AS_HELP_STRING([--enable-wayland-clients],[enable wayland clients in composite module @<:@default=disabled@:>@]),
@@ -857,6 +866,7 @@ AC_E_OPTIONAL_MODULE([conf_interaction], true)
AC_E_OPTIONAL_MODULE([gadman], true)
AC_E_OPTIONAL_MODULE([mixer], true, [CHECK_MODULE_MIXER])
AC_E_OPTIONAL_MODULE([connman], true, [CHECK_MODULE_CONNMAN])
+AC_E_OPTIONAL_MODULE([bluez4], true, [CHECK_MODULE_BLUEZ4])
AC_E_OPTIONAL_MODULE([illume2], true)
AC_E_OPTIONAL_MODULE([syscon], true)
AC_E_OPTIONAL_MODULE([everything], true)
@@ -957,6 +967,7 @@ src/modules/conf_randr/module.desktop
src/modules/gadman/module.desktop
src/modules/mixer/module.desktop
src/modules/connman/module.desktop
+src/modules/bluez4/module.desktop
src/modules/illume2/doc/illume.dox
src/modules/illume2/module.desktop
src/modules/illume-home/module.desktop
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
index 35f69cf97..73828a2df 100644
--- a/src/modules/Makefile.am
+++ b/src/modules/Makefile.am
@@ -30,6 +30,10 @@ if USE_MODULE_CONNMAN
include Makefile_connman.am
endif
+if USE_MODULE_BLUEZ4
+include Makefile_bluez4.am
+endif
+
if USE_MODULE_IBAR
include Makefile_ibar.am
endif
diff --git a/src/modules/Makefile_bluez4.am b/src/modules/Makefile_bluez4.am
new file mode 100644
index 000000000..6216c882d
--- /dev/null
+++ b/src/modules/Makefile_bluez4.am
@@ -0,0 +1,22 @@
+bluez4dir = $(MDIR)/bluez4
+bluez4_DATA = bluez4/e-module-bluez4.edj \
+ bluez4/module.desktop
+
+EXTRA_DIST += $(bluez4_DATA)
+
+bluez4pkgdir = $(MDIR)/bluez4/$(MODULE_ARCH)
+bluez4pkg_LTLIBRARIES = bluez4/module.la
+
+bluez4_module_la_SOURCES = bluez4/e_mod_main.h \
+ bluez4/e_mod_main.c \
+ bluez4/ebluez4.h \
+ bluez4/ebluez4.c \
+ bluez4/agent.h \
+ bluez4/agent.c
+
+bluez4_module_la_CFLAGS = $(AM_CFLAGS) -Wno-unused-parameter
+bluez4_module_la_LIBADD = @BLUEZ4_LIBS@
+
+.PHONY: bluez4 install-bluez4
+bluez4: $(bluez4pkg_LTLIBRARIES) $(bluez4_DATA)
+install-bluez4: install-bluez4DATA install-bluez4pkgLTLIBRARIES
diff --git a/src/modules/bluez4/agent.c b/src/modules/bluez4/agent.c
new file mode 100644
index 000000000..47baeef49
--- /dev/null
+++ b/src/modules/bluez4/agent.c
@@ -0,0 +1,133 @@
+#include <inttypes.h>
+#include "e.h"
+#include "agent.h"
+
+#define AGENT_INTERFACE "org.bluez.Agent"
+#define BLUEZ_ERROR_FAILED "org.bluez.Error.Failed"
+#define GET_ERROR_MSG "edbus_message_arguments_get() error"
+
+static EDBus_Message *
+_agent_release(const EDBus_Service_Interface *iface, const EDBus_Message *message)
+{
+ DBG("Agent Released.");
+ return edbus_message_method_return_new(message);
+}
+
+static EDBus_Message *
+_agent_request_pin_code(const EDBus_Service_Interface *iface, const EDBus_Message *message)
+{
+ //FIXME: generate random number and show it in dialog
+ EDBus_Message *reply = edbus_message_method_return_new(message);
+ edbus_message_arguments_set(reply, "s", "123456");
+ DBG("Pin Code Requested.");
+ return reply;
+}
+
+static EDBus_Message *
+_agent_request_passkey(const EDBus_Service_Interface *iface, const EDBus_Message *message)
+{
+ //FIXME: generate random number and show it in dialog
+ EDBus_Message *reply = edbus_message_method_return_new(message);
+ edbus_message_arguments_set(reply, "s", "123456");
+ DBG("Passkey Requested.");
+ return reply;
+}
+
+static EDBus_Message *
+_agent_display_passkey(const EDBus_Service_Interface *iface, const EDBus_Message *message)
+{
+ //FIXME: show passkey in dialog
+ const char *device;
+ uint32_t passkey;
+ uint16_t entered;
+ if(!edbus_message_arguments_get(message, "ouq", &device, &passkey, &entered))
+ return edbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG);
+ DBG("Device: %s", device);
+ DBG("Passkey: %u", passkey);
+ DBG("Entered: %d", entered);
+ return edbus_message_method_return_new(message);
+}
+
+static EDBus_Message *
+_agent_display_pin_code(const EDBus_Service_Interface *iface, const EDBus_Message *message)
+{
+ //FIXME: show passkey in dialog
+ const char *device, *pincode;
+ if(!edbus_message_arguments_get(message, "os", &device, &pincode))
+ return edbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG);
+ DBG("Device: %s", device);
+ DBG("Passkey: %s", pincode);
+ return edbus_message_method_return_new(message);
+}
+
+static EDBus_Message *
+_agent_request_confirmation(const EDBus_Service_Interface *iface, const EDBus_Message *message)
+{
+ //FIXME: Ask for confirmation in dialog
+ const char *device;
+ uint32_t passkey;
+ if(!edbus_message_arguments_get(message, "ou", &device, &passkey))
+ return edbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG);
+ DBG("Confirming request of %u for device %s", passkey, device);
+ return edbus_message_method_return_new(message);
+}
+
+static EDBus_Message *
+_agent_authorize(const EDBus_Service_Interface *iface, const EDBus_Message *message)
+{
+ //FIXME: Ask for authorization in dialog
+ const char *device, *uuid;
+ if(!edbus_message_arguments_get(message, "os", &device, &uuid))
+ return edbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG);
+ DBG("Authorizing request for %s", device);
+ return edbus_message_method_return_new(message);
+}
+
+static EDBus_Message *
+_agent_cancel(const EDBus_Service_Interface *iface, const EDBus_Message *message)
+{
+ DBG("Request canceled.");
+ return edbus_message_method_return_new(message);
+}
+
+static const EDBus_Method agent_methods[] = {
+ { "Release", NULL, NULL, _agent_release, 0 },
+ {
+ "RequestPinCode", EDBUS_ARGS({"o", "device"}),
+ EDBUS_ARGS({"s", "pincode"}), _agent_request_pin_code, 0
+ },
+ {
+ "RequestPasskey", EDBUS_ARGS({"o", "device"}),
+ EDBUS_ARGS({"u", "passkey"}), _agent_request_passkey, 0
+ },
+ {
+ "DisplayPasskey",
+ EDBUS_ARGS({"o", "device"},{"u", "passkey"},{"q", "entered"}),
+ NULL, _agent_display_passkey, 0
+ },
+ {
+ "DisplayPinCode", EDBUS_ARGS({"o", "device"},{"s", "pincode"}),
+ NULL, _agent_display_pin_code, 0
+ },
+ {
+ "RequestConfirmation", EDBUS_ARGS({"o", "device"},{"u", "passkey"}),
+ NULL, _agent_request_confirmation, 0
+ },
+ {
+ "Authorize", EDBUS_ARGS({"o", "device"},{"s", "uuid"}),
+ NULL, _agent_authorize, 0
+ },
+ { "Cancel", NULL, NULL, _agent_cancel, 0 },
+ { NULL, NULL, NULL, NULL, 0 }
+};
+
+static const EDBus_Service_Interface_Desc agent_iface = {
+ AGENT_INTERFACE, agent_methods, NULL, NULL, NULL, NULL
+};
+
+/* Public Functions */
+void ebluez4_register_agent_interfaces(EDBus_Connection *conn)
+{
+ edbus_service_interface_register(conn, AGENT_PATH, &agent_iface);
+ edbus_service_interface_register(conn, REMOTE_AGENT_PATH, &agent_iface);
+}
diff --git a/src/modules/bluez4/agent.h b/src/modules/bluez4/agent.h
new file mode 100644
index 000000000..a7e45c621
--- /dev/null
+++ b/src/modules/bluez4/agent.h
@@ -0,0 +1,6 @@
+#include "EDBus.h"
+
+#define AGENT_PATH "/org/bluez/Agent"
+#define REMOTE_AGENT_PATH "/org/bluez/RemoteAgent"
+
+void ebluez4_register_agent_interfaces(EDBus_Connection *conn);
diff --git a/src/modules/bluez4/e-module-bluez4.edj b/src/modules/bluez4/e-module-bluez4.edj
new file mode 100644
index 000000000..365585071
--- /dev/null
+++ b/src/modules/bluez4/e-module-bluez4.edj
Binary files differ
diff --git a/src/modules/bluez4/e_mod_main.c b/src/modules/bluez4/e_mod_main.c
new file mode 100644
index 000000000..50ce5c6f8
--- /dev/null
+++ b/src/modules/bluez4/e_mod_main.c
@@ -0,0 +1,235 @@
+#include <e.h>
+#include <EDBus.h>
+#include "e_mod_main.h"
+#include "ebluez4.h"
+
+/* Local Variables */
+static Eina_List *instances = NULL;
+static E_Module *mod = NULL;
+static char tmpbuf[1024];
+
+EAPI E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Bluez4"};
+
+/* Local Functions */
+static void
+_ebluez4_cb_pair(void *data, void *data2 __UNUSED__)
+{
+ Instance *inst = data;
+ const char *addr = e_widget_ilist_selected_value_get(inst->list);
+
+ if(!addr)
+ return;
+ e_gadcon_popup_hide(inst->popup);
+ DBG("Pairing with : %s", addr);
+}
+
+static Eina_Bool
+_ebluez4_cb_stop_search(void *data)
+{
+ Instance *inst = data;
+ ebluez4_stop_discovery();
+ e_widget_disabled_set(inst->bt, 0);
+ DBG("Stopping discovery...");
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_ebluez4_cb_search(void *data, void *data2 __UNUSED__)
+{
+ Instance *inst = data;
+ ebluez4_start_discovery();
+ e_widget_disabled_set(inst->bt, 1);
+ ecore_timer_add(60, _ebluez4_cb_stop_search, inst);
+ DBG("Starting discovery...");
+}
+
+static void
+_ebluez4_popup_new(Instance *inst)
+{
+ Evas_Object *list, *tb, *bt2;
+ Evas_Coord mw, mh;
+ Evas *evas;
+
+ EINA_SAFETY_ON_FALSE_RETURN(inst->popup == NULL);
+
+ inst->popup = e_gadcon_popup_new(inst->gcc);
+ evas = inst->popup->win->evas;
+
+ list = e_widget_list_add(evas, 0, 0);
+ inst->list = e_widget_ilist_add(evas, 0, 0, NULL);
+ e_widget_list_object_append(list, inst->list, 1, 1, 0.5);
+
+ e_widget_ilist_header_append(inst->list, NULL, "Devices Found");
+
+ inst->bt = e_widget_button_add(evas, "Search Devices", NULL,
+ _ebluez4_cb_search, inst, NULL);
+ bt2 = e_widget_button_add(evas, "Connect", NULL, _ebluez4_cb_pair, inst, NULL);
+
+ tb = e_widget_table_add(evas, 0);
+
+ e_widget_table_object_append(tb, inst->bt, 0, 0, 1, 1, 1, 1, 1, 1);
+ e_widget_table_object_append(tb, bt2, 1, 0, 1, 1, 1, 1, 1, 1);
+ e_widget_list_object_append(list, tb, 1, 0, 0.5);
+
+ e_widget_size_min_get(list, &mw, &mh);
+ if (mh < 220)
+ mh = 220;
+ if (mw < 250)
+ mw = 250;
+ e_widget_size_min_set(list, mw, mh);
+
+ e_gadcon_popup_content_set(inst->popup, list);
+ e_gadcon_popup_show(inst->popup);
+}
+
+static void
+_ebluez4_popup_del(Instance *inst)
+{
+ if (!inst->popup) return;
+ e_object_del(E_OBJECT(inst->popup));
+ inst->popup = NULL;
+}
+
+static void
+_ebluez4_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event)
+{
+ Instance *inst = NULL;
+ Evas_Event_Mouse_Down *ev = event;
+
+ if (!(inst = data)) return;
+ if (ev->button != 1) return;
+
+ if (!inst->popup)
+ _ebluez4_popup_new(inst);
+ else if (inst->popup->win->visible)
+ e_gadcon_popup_hide(inst->popup);
+ else
+ e_gadcon_popup_show(inst->popup);
+}
+
+/* Gadcon */
+static E_Gadcon_Client *
+_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
+{
+ Instance *inst = NULL;
+ char buf[1024];
+
+ snprintf(buf, sizeof(buf), "%s/e-module-bluez4.edj", mod->dir);
+
+ inst = E_NEW(Instance, 1);
+
+ inst->o_bluez4 = edje_object_add(gc->evas);
+ if (!e_theme_edje_object_set(inst->o_bluez4, "base/theme/modules/bluez4",
+ "modules/bluez4/main"))
+ edje_object_file_set(inst->o_bluez4, buf, "modules/bluez4/main");
+
+ inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->o_bluez4);
+ inst->gcc->data = inst;
+
+ evas_object_event_callback_add(inst->o_bluez4, EVAS_CALLBACK_MOUSE_DOWN,
+ _ebluez4_cb_mouse_down, inst);
+
+ instances = eina_list_append(instances, inst);
+
+ return inst->gcc;
+}
+
+static void
+_gc_shutdown(E_Gadcon_Client *gcc)
+{
+ Instance *inst = NULL;
+
+ if (!(inst = gcc->data)) return;
+ instances = eina_list_remove(instances, inst);
+
+ if (inst->o_bluez4)
+ {
+ evas_object_event_callback_del(inst->o_bluez4, EVAS_CALLBACK_MOUSE_DOWN,
+ _ebluez4_cb_mouse_down);
+ evas_object_del(inst->o_bluez4);
+ }
+
+ _ebluez4_popup_del(inst);
+
+ E_FREE(inst);
+}
+
+static const char *
+_gc_id_new(const E_Gadcon_Client_Class *client_class)
+{
+ snprintf(tmpbuf, sizeof(tmpbuf), "bluez4.%d", eina_list_count(instances));
+ return tmpbuf;
+}
+
+static void
+_gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient)
+{
+ e_gadcon_client_aspect_set(gcc, 16, 16);
+ e_gadcon_client_min_size_set(gcc, 16, 16);
+}
+
+static const char *
+_gc_label(const E_Gadcon_Client_Class *client_class)
+{
+ return "Bluez4";
+}
+
+static Evas_Object *
+_gc_icon(const E_Gadcon_Client_Class *client_class, Evas *evas)
+{
+ Evas_Object *o = NULL;
+ char buf[4096];
+
+ snprintf(buf, sizeof(buf), "%s/e-module-bluez4.edj", mod->dir);
+
+ o = edje_object_add(evas);
+
+ edje_object_file_set(o, buf, "icon");
+
+ return o;
+}
+
+static const E_Gadcon_Client_Class _gc_class =
+{
+ GADCON_CLIENT_CLASS_VERSION, "bluez4",
+ {_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon,
+ _gc_id_new, NULL, NULL},
+ E_GADCON_CLIENT_STYLE_PLAIN
+};
+
+/* Module Functions */
+EAPI void *
+e_modapi_init(E_Module *m)
+{
+ mod = m;
+
+ ebluez4_edbus_init();
+
+ e_gadcon_provider_register(&_gc_class);
+
+ return m;
+}
+
+EAPI int
+e_modapi_shutdown(E_Module *m)
+{
+ ebluez4_edbus_shutdown();
+ return 1;
+}
+
+EAPI int
+e_modapi_save(E_Module *m)
+{
+ return 1;
+}
+
+/* Public Functions */
+void
+ebluez4_disabled_set_all_search_buttons(Eina_Bool disabled)
+{
+ Eina_List *iter;
+ Instance *inst;
+
+ EINA_LIST_FOREACH(instances, iter, inst)
+ e_widget_disabled_set(inst->bt, disabled);
+}
diff --git a/src/modules/bluez4/e_mod_main.h b/src/modules/bluez4/e_mod_main.h
new file mode 100644
index 000000000..399463687
--- /dev/null
+++ b/src/modules/bluez4/e_mod_main.h
@@ -0,0 +1,21 @@
+#ifndef E_MOD_MAIN_H
+#define E_MOD_MAIN_H
+
+typedef struct _Instance Instance;
+struct _Instance
+{
+ E_Gadcon_Client *gcc;
+ E_Gadcon_Popup *popup;
+ Evas_Object *o_bluez4, *bt;
+ Evas_Object *list;
+};
+
+EAPI extern E_Module_Api e_modapi;
+
+EAPI void *e_modapi_init(E_Module *m);
+EAPI int e_modapi_shutdown(E_Module *m);
+EAPI int e_modapi_save(E_Module *m);
+
+void ebluez4_disabled_set_all_search_buttons(Eina_Bool disabled);
+
+#endif
diff --git a/src/modules/bluez4/ebluez4.c b/src/modules/bluez4/ebluez4.c
new file mode 100644
index 000000000..3d546604a
--- /dev/null
+++ b/src/modules/bluez4/ebluez4.c
@@ -0,0 +1,216 @@
+#include <unistd.h>
+#include "e.h"
+#include "agent.h"
+#include "e_mod_main.h"
+#include "ebluez4.h"
+
+/* Global Module Context */
+Context *ctxt;
+
+static int
+_addr_cmp(const void *d1, const void *d2)
+{
+ const Device *dev = d1;
+ const char *addr = d2;
+
+ return strcmp(dev->addr, addr);
+}
+
+static void
+_free_dev(Device *dev)
+{
+ eina_stringshare_del(dev->addr);
+ dev->addr = NULL;
+ eina_stringshare_del(dev->name);
+ dev->name = NULL;
+ free(dev);
+}
+
+static void
+_free_dev_list(Eina_List **list)
+{
+ Device *dev;
+
+ EINA_LIST_FREE(*list, dev)
+ _free_dev(dev);
+ *list = NULL;
+}
+
+static void
+_unset_adapter()
+{
+ if (!ctxt->adap_obj)
+ return;
+
+ DBG("Remove adapter %s", edbus_object_path_get(ctxt->adap_obj));
+
+ _free_dev_list(&ctxt->devices);
+ ctxt->devices = NULL;
+ edbus_object_unref(ctxt->adap_obj);
+ ctxt->adap_obj = NULL;
+ ebluez4_disabled_set_all_search_buttons(EINA_TRUE);
+}
+
+static void
+_on_device_found(void *context, const EDBus_Message *msg)
+{
+ EDBus_Message_Iter *dict, *entry, *variant;
+ const char *addr, *key, *name;
+ Device *dev;
+
+ if (!edbus_message_arguments_get(msg, "sa{sv}", &addr, &dict))
+ {
+ ERR("Error reading device address");
+ return;
+ }
+
+ if(eina_list_search_unsorted(ctxt->devices, _addr_cmp, addr))
+ return;
+
+ while (edbus_message_iter_get_and_next(dict,'e', &entry))
+ {
+ if(!edbus_message_iter_arguments_get(entry, "sv", &key, &variant))
+ {
+ ERR("Error reading device property");
+ return;
+ }
+
+ if(strcmp(key,"Name"))
+ continue;
+
+ if(!edbus_message_iter_arguments_get(variant, "s", &name))
+ {
+ ERR("Error reading device name");
+ return;
+ }
+
+ DBG("Device Found --- Name: %s", name);
+ dev = malloc(sizeof(Device));
+ dev->addr = eina_stringshare_add(addr);
+ dev->name = eina_stringshare_add(name);
+ ctxt->devices = eina_list_append(ctxt->devices, dev);
+ }
+}
+
+static void
+_set_adapter(const EDBus_Message *msg)
+{
+ const char *adap_path;
+
+ if (!edbus_message_arguments_get(msg, "o", &adap_path))
+ {
+ ERR("Error reading path of Default Adapter");
+ return;
+ }
+
+ DBG("Setting adapter to %s", adap_path);
+
+ if (ctxt->adap_obj)
+ _unset_adapter();
+
+ ctxt->adap_obj = edbus_object_get(ctxt->conn, BLUEZ_BUS, adap_path);
+ ctxt->adap_proxy = edbus_proxy_get(ctxt->adap_obj, ADAPTER_INTERFACE);
+
+ ebluez4_disabled_set_all_search_buttons(EINA_FALSE);
+ edbus_proxy_signal_handler_add(ctxt->adap_proxy, "DeviceFound",
+ _on_device_found, NULL);
+ edbus_proxy_call(ctxt->adap_proxy, "RegisterAgent", NULL, NULL, -1, "os",
+ REMOTE_AGENT_PATH, "KeyboardDisplay");
+}
+
+static void
+_default_adapter_get(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
+{
+ const char *err_name, *err_msg;
+
+ /*
+ * If bluetoothd is starting up, we can fail here and wait for the
+ * DefaultAdapterChanged signal later
+ */
+ if (edbus_message_error_get(msg, &err_name, &err_msg))
+ return;
+
+ if (!ctxt->adap_obj)
+ _set_adapter(msg);
+}
+
+static void
+_on_adapter_changed(void *context, const EDBus_Message *msg)
+{
+ _set_adapter(msg);
+}
+
+static void
+_on_adapter_removed(void *context, const EDBus_Message *msg)
+{
+ const char *adap_path;
+
+ if (!edbus_message_arguments_get(msg, "o", &adap_path))
+ {
+ ERR("Error reading path of Removed Adapter");
+ return;
+ }
+
+ if (!strcmp(edbus_object_path_get(ctxt->adap_obj), adap_path))
+ _unset_adapter();
+}
+
+static void
+_bluez_monitor(void *data, const char *bus, const char *old_id, const char *new_id)
+{
+ if (!strcmp(old_id,"") && strcmp(new_id,""))
+ // Bluez up
+ edbus_proxy_call(ctxt->man_proxy, "DefaultAdapter", _default_adapter_get,
+ NULL, -1, "");
+ else if (strcmp(old_id,"") && !strcmp(new_id,""))
+ // Bluez down
+ _unset_adapter();
+}
+
+/* Public Functions */
+void
+ebluez4_edbus_init()
+{
+ EDBus_Object *obj;
+
+ ctxt = calloc(1, sizeof(Context));
+
+ edbus_init();
+
+ ctxt->conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SYSTEM);
+ obj = edbus_object_get(ctxt->conn, BLUEZ_BUS, MANAGER_PATH);
+ ctxt->man_proxy = edbus_proxy_get(obj, MANAGER_INTERFACE);
+
+ ebluez4_register_agent_interfaces(ctxt->conn);
+
+ edbus_proxy_signal_handler_add(ctxt->man_proxy,
+ "DefaultAdapterChanged", _on_adapter_changed, NULL);
+ edbus_proxy_signal_handler_add(ctxt->man_proxy, "AdapterRemoved",
+ _on_adapter_removed, NULL);
+
+ edbus_name_owner_changed_callback_add(ctxt->conn, BLUEZ_BUS, _bluez_monitor,
+ NULL, EINA_TRUE);
+}
+
+void
+ebluez4_edbus_shutdown()
+{
+ _free_dev_list(&ctxt->devices);
+ edbus_connection_unref(ctxt->conn);
+ free(ctxt);
+
+ edbus_shutdown();
+}
+
+void
+ebluez4_start_discovery()
+{
+ _free_dev_list(&ctxt->devices);
+ edbus_proxy_call(ctxt->adap_proxy, "StartDiscovery", NULL, NULL, -1, "");
+}
+
+void
+ebluez4_stop_discovery()
+{
+ edbus_proxy_call(ctxt->adap_proxy, "StopDiscovery", NULL, NULL, -1, "");
+}
diff --git a/src/modules/bluez4/ebluez4.h b/src/modules/bluez4/ebluez4.h
new file mode 100644
index 000000000..2f449a6ff
--- /dev/null
+++ b/src/modules/bluez4/ebluez4.h
@@ -0,0 +1,27 @@
+#include "EDBus.h"
+
+#define BLUEZ_BUS "org.bluez"
+#define MANAGER_PATH "/"
+#define ADAPTER_INTERFACE "org.bluez.Adapter"
+#define MANAGER_INTERFACE "org.bluez.Manager"
+
+typedef struct _Device
+{
+ const char *addr;
+ const char *name;
+} Device;
+
+typedef struct _Context
+{
+ EDBus_Connection *conn;
+ const char *default_adap_path;
+ EDBus_Object *adap_obj;
+ EDBus_Proxy *man_proxy;
+ EDBus_Proxy *adap_proxy;
+ Eina_List *devices;
+} Context;
+
+void ebluez4_edbus_init();
+void ebluez4_edbus_shutdown();
+void ebluez4_start_discovery();
+void ebluez4_stop_discovery();
diff --git a/src/modules/bluez4/module.desktop.in b/src/modules/bluez4/module.desktop.in
new file mode 100644
index 000000000..f89e8d4e6
--- /dev/null
+++ b/src/modules/bluez4/module.desktop.in
@@ -0,0 +1,6 @@
+[Desktop Entry]
+Type=Link
+Name=Bluez4
+Icon=e-module-bluez4
+#Several different types available here. NEED TO DOC THESE.
+X-Enlightenment-ModuleType=utils