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 #include +#include #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