Add function to register/unregister Telephony agent to BlueZ
---
plugins/bluetooth.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++
plugins/bluetooth.h | 14 ++++
2 files changed, 212 insertions(+), 0 deletions(-)
diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index dbf79eb..971e2c6 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -44,6 +44,7 @@ static GHashTable *uuid_hash = NULL;
static GHashTable *adapter_address_hash = NULL;
static gint bluetooth_refcount;
static GSList *server_list = NULL;
+static GSList *telephony_list = NULL;
static const char *adapter_any_name = "any";
static char *adapter_any_path;
@@ -65,6 +66,13 @@ struct cb_data {
GIOChannel *io;
};
+struct agent {
+ char *path;
+ char *uuid;
+ guint16 version;
+ guint16 features;
+};
+
void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
{
@@ -146,6 +154,60 @@ fail:
return err;
}
+static void register_telephony_agent(const char *path, const char *handle,
+ struct agent *agent)
+{
+ DBusMessage *msg;
+ DBusMessageIter iter, dict;
+
+ DBG("Registering oFono Agent for %s to %s", agent->uuid, path);
+
+ msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+ BLUEZ_TELEPHONY_INTERFACE, "RegisterAgent");
+ if (msg == NULL)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &agent->path);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ ofono_dbus_dict_append(&dict, "UUID", DBUS_TYPE_STRING,
&agent->uuid);
+
+ ofono_dbus_dict_append(&dict, "Version", DBUS_TYPE_UINT16,
+ &agent->version);
+ ofono_dbus_dict_append(&dict, "Features", DBUS_TYPE_UINT16,
+ &agent->features);
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ g_dbus_send_message(connection, msg);
+}
+
+static void unregister_telephony_agent(const char *path, const char *handle,
+ struct agent *agent)
+{
+ DBusMessage *msg;
+
+ DBG("Unregistering oFono Agent for %s from %s", agent->uuid, path);
+
+ msg = dbus_message_new_method_call(BLUEZ_SERVICE, path,
+ BLUEZ_TELEPHONY_INTERFACE,
+ "UnregisterAgent");
+ if (msg == NULL)
+ return;
+
+ dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent->path,
+ DBUS_TYPE_INVALID);
+
+ g_dbus_send_message(connection, msg);
+}
+
typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data);
struct property_handler {
@@ -455,6 +517,9 @@ static void adapter_properties_cb(DBusPendingCall *call, gpointer
user_data)
g_free, -1, DBUS_TYPE_INVALID);
}
+ for (l = telephony_list; l; l = l->next)
+ register_telephony_agent(path, NULL, l->data);
+
done:
g_slist_free(device_list);
dbus_message_unref(reply);
@@ -982,5 +1047,138 @@ void bluetooth_unregister_server(struct server *server)
bluetooth_unref();
}
+int bluetooth_parse_newconnection_message(DBusMessage *msg, const char **device,
+ const char **uuid, guint16 *version,
+ guint16 *features,
+ const char **transport_path)
+{
+ DBusMessageIter args, props;
+ int fd;
+ gboolean has_device = FALSE;
+ gboolean has_uuid = FALSE;
+
+ dbus_message_iter_init(msg, &args);
+
+ if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_UNIX_FD)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&args, &fd);
+ dbus_message_iter_next(&args);
+
+ dbus_message_iter_recurse(&args, &props);
+ if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
+ return -EINVAL;
+
+ while (dbus_message_iter_get_arg_type(&props) == DBUS_TYPE_DICT_ENTRY) {
+ const char *key;
+ DBusMessageIter value, entry;
+ int var;
+
+ dbus_message_iter_recurse(&props, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &value);
+
+ var = dbus_message_iter_get_arg_type(&value);
+ if (strcasecmp(key, "Device") == 0) {
+ if (var != DBUS_TYPE_OBJECT_PATH)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, device);
+ has_device = TRUE;
+ } else if (strcasecmp(key, "UUID") == 0) {
+ if (var != DBUS_TYPE_STRING)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, uuid);
+ has_uuid = TRUE;
+ } else if (strcasecmp(key, "Version") == 0) {
+ if (var != DBUS_TYPE_UINT16)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, version);
+ } else if (strcasecmp(key, "Features") == 0) {
+ if (var != DBUS_TYPE_UINT16)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, features);
+ } else if (strcasecmp(key, "Transport") == 0) {
+ if (var != DBUS_TYPE_OBJECT_PATH)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, transport_path);
+ }
+
+ dbus_message_iter_next(&props);
+ }
+
+ return (has_device && has_uuid) ? fd : -EINVAL;
+}
+
+void bluetooth_register_telephony_agent(const char *path, const char *uuid,
+ guint16 version, guint16 features,
+ const GDBusMethodTable *methods,
+ void *user_data,
+ GDBusDestroyFunction destroy)
+{
+ GSList *l;
+ struct agent *agent;
+
+ for (l = telephony_list; l; l = l->next) {
+ agent = l->data;
+
+ if (g_strcmp0(path, agent->path) == 0) {
+ ofono_error("Telephony agent path \"%s\" already " \
+ "registered", path);
+ return;
+ }
+ }
+
+ agent = g_try_new0(struct agent, 1);
+ if (!agent)
+ return;
+
+ agent->path = g_strdup(path);
+ agent->uuid = g_strdup(uuid);
+ agent->version = version;
+ agent->features = features;
+
+ bluetooth_ref();
+
+ g_dbus_register_interface(connection, path,
+ BLUEZ_TELEPHONY_AGENT_INTERFACE, methods, NULL,
+ NULL, user_data, destroy);
+
+ telephony_list = g_slist_prepend(telephony_list, agent);
+
+ g_hash_table_foreach(adapter_address_hash,
+ (GHFunc) register_telephony_agent, agent);
+}
+
+void bluetooth_unregister_telephony_agent(const char *path)
+{
+ GSList *l;
+ struct agent *agent;
+
+ for (l = telephony_list; l; l = l->next) {
+ agent = l->data;
+
+ if (g_strcmp0(path, agent->path) == 0)
+ break;
+ }
+
+ if (l == NULL)
+ return;
+
+ g_hash_table_foreach(adapter_address_hash,
+ (GHFunc) unregister_telephony_agent, agent);
+
+ telephony_list = g_slist_remove(telephony_list, agent);
+ g_free(agent->path);
+ g_free(agent->uuid);
+ g_free(agent);
+
+ g_dbus_unregister_interface(connection, path,
+ BLUEZ_TELEPHONY_AGENT_INTERFACE);
+
+ bluetooth_unref();
+}
+
OFONO_PLUGIN_DEFINE(bluetooth, "Bluetooth Utils Plugins", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, NULL, NULL)
diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h
index daa1873..f81fc99 100644
--- a/plugins/bluetooth.h
+++ b/plugins/bluetooth.h
@@ -21,12 +21,15 @@
#include <ofono/modem.h>
#include <ofono/dbus.h>
+#include <gdbus.h>
#define BLUEZ_SERVICE "org.bluez"
#define BLUEZ_MANAGER_INTERFACE BLUEZ_SERVICE ".Manager"
#define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE ".Adapter"
#define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE ".Device"
#define BLUEZ_SERVICE_INTERFACE BLUEZ_SERVICE ".Service"
+#define BLUEZ_TELEPHONY_INTERFACE BLUEZ_SERVICE ".Telephony"
+#define BLUEZ_TELEPHONY_AGENT_INTERFACE BLUEZ_SERVICE ".TelephonyAgent"
#define DBUS_TIMEOUT 15
@@ -81,3 +84,14 @@ void bluetooth_parse_properties(DBusMessage *reply, const char
*property, ...);
int bluetooth_sap_client_register(struct bluetooth_sap_driver *sap,
struct ofono_modem *modem);
void bluetooth_sap_client_unregister(struct ofono_modem *modem);
+
+int bluetooth_parse_newconnection_message(DBusMessage *msg, const char **device,
+ const char **uuid, guint16 *version,
+ guint16 *features,
+ const char **transport_path);
+void bluetooth_register_telephony_agent(const char *path, const char *uuid,
+ guint16 version, guint16 features,
+ const GDBusMethodTable *methods,
+ void *user_data,
+ GDBusDestroyFunction destroy);
+void bluetooth_unregister_telephony_agent(const char *path);
--
1.7.1