e/bluez4: include bluez4 module

Patch by: Lucas Joia <lucasjoia@profusion.mobi>


SVN revision: 82185
This commit is contained in:
Lucas Joia 2013-01-04 16:11:48 +00:00 committed by Lucas De Marchi
parent 271bc56cdd
commit 21c0a5381b
11 changed files with 681 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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

133
src/modules/bluez4/agent.c Normal file
View File

@ -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);
}

View File

@ -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);

Binary file not shown.

View File

@ -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);
}

View File

@ -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

View File

@ -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, "");
}

View File

@ -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();

View File

@ -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