* [PATCH 1/5] Add bluetooth plugin skeleton. @ 2010-06-08 7:43 Gustavo F. Padovan 2010-06-08 7:43 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Gustavo F. Padovan 2010-06-10 21:13 ` [PATCH 1/5] Add bluetooth plugin skeleton Denis Kenzior 0 siblings, 2 replies; 12+ messages in thread From: Gustavo F. Padovan @ 2010-06-08 7:43 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 5750 bytes --] The bluetooth plugin has bluetooth_resgister_uuid() and bluetooth_unresgister_uuid() where bluetooth profiles plugins such as HFP and DUN can register themselves to get know about BlueZ stuff ( new devices, bluetoothd shutdown, etc..) --- Makefile.am | 3 ++ plugins/bluetooth.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/bluetooth.h | 42 ++++++++++++++++++++++++++++ plugins/hfp.c | 8 +---- 4 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 plugins/bluetooth.c create mode 100644 plugins/bluetooth.h diff --git a/Makefile.am b/Makefile.am index 2922be9..47b8306 100644 --- a/Makefile.am +++ b/Makefile.am @@ -238,6 +238,9 @@ builtin_sources += plugins/em770.c builtin_modules += novatel builtin_sources += plugins/novatel.c +builtin_modules += bluetooth +builtin_sources += plugins/bluetooth.c + builtin_modules += hfp builtin_sources += plugins/hfp.c diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c new file mode 100644 index 0000000..b4fe676 --- /dev/null +++ b/plugins/bluetooth.c @@ -0,0 +1,75 @@ +/* + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. + * Copyright (C) 2010 ProFUSION embedded systems + * Copyright (C) 2010 Gustavo F. Padovan <gustavo@padovan.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <glib.h> +#include <gdbus.h> +#include <ofono.h> + +#include <ofono/dbus.h> + +#include "bluetooth.h" + +static DBusConnection *connection; +static GHashTable *uuid_hash = NULL; +static GHashTable *adapter_address_hash = NULL; + +int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile) +{ + if (uuid_hash) + goto done; + + connection = ofono_dbus_get_connection(); + + uuid_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + + adapter_address_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + +done: + g_hash_table_insert(uuid_hash, g_strdup(uuid), profile); + + return 0; +} + +void bluetooth_unregister_uuid(const char *uuid) +{ + g_hash_table_remove(uuid_hash, uuid); + + if (g_hash_table_size(uuid_hash)) + return; + + g_hash_table_destroy(uuid_hash); + g_hash_table_destroy(adapter_address_hash); + uuid_hash = NULL; +} + +OFONO_PLUGIN_DEFINE(bluetooth, "Bluetooth Utils Plugins", VERSION, + OFONO_PLUGIN_PRIORITY_DEFAULT, NULL, NULL) diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h new file mode 100644 index 0000000..94ebaf6 --- /dev/null +++ b/plugins/bluetooth.h @@ -0,0 +1,42 @@ +/* + * oFono - Open Source Telephony + * + * Copyright (C) 2010 Gustavo F. Padovan <gustavo@padovan.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#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 HFP_AG_UUID "0000111F-0000-1000-8000-00805F9B34FB" + +/* Profiles bitfield */ +#define HFP_AG 0x01 + +struct bluetooth_profile { + const char *name; + int (*create)(const char *device, const char *dev_addr, + const char *adapter_addr, const char *alias); + void (*remove_all)(); + void (*set_alias)(const char *device, const char *); +}; + +int bluetooth_register_uuid(const char *uuid, + struct bluetooth_profile *profile); +void bluetooth_unregister_uuid(const char *uuid); + diff --git a/plugins/hfp.c b/plugins/hfp.c index e37c9fc..a49e4af 100644 --- a/plugins/hfp.c +++ b/plugins/hfp.c @@ -45,17 +45,13 @@ #include <ofono/dbus.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" +#include "bluetooth.h" + #define BLUEZ_GATEWAY_INTERFACE BLUEZ_SERVICE ".HandsfreeGateway" #define HFP_AGENT_INTERFACE "org.bluez.HandsfreeAgent" #define HFP_AGENT_ERROR_INTERFACE "org.bluez.Error" -#define HFP_AG_UUID "0000111F-0000-1000-8000-00805F9B34FB" - #ifndef DBUS_TYPE_UNIX_FD #define DBUS_TYPE_UNIX_FD -1 #endif -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c 2010-06-08 7:43 [PATCH 1/5] Add bluetooth plugin skeleton Gustavo F. Padovan @ 2010-06-08 7:43 ` Gustavo F. Padovan 2010-06-08 7:43 ` [PATCH 3/5] Remove send_method_call from hfp.c Gustavo F. Padovan 2010-06-10 21:17 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Denis Kenzior 2010-06-10 21:13 ` [PATCH 1/5] Add bluetooth plugin skeleton Denis Kenzior 1 sibling, 2 replies; 12+ messages in thread From: Gustavo F. Padovan @ 2010-06-08 7:43 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 29375 bytes --] The new Bluetooth plugin will be responsible for handle DBus for the Bluetooth profiles implemented by oFono. Each Bluetooth profile can register callbacks to create a modem, remove all modems and set alias. The idea is to have here soon code the handle Bluetooth Agent stuff too. --- plugins/bluetooth.c | 478 +++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/hfp.c | 458 ++++--------------------------------------------- 2 files changed, 514 insertions(+), 422 deletions(-) diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c index b4fe676..b452d73 100644 --- a/plugins/bluetooth.c +++ b/plugins/bluetooth.c @@ -40,13 +40,474 @@ static DBusConnection *connection; static GHashTable *uuid_hash = NULL; static GHashTable *adapter_address_hash = NULL; +static int send_method_call_with_reply(const char *dest, const char *path, + const char *interface, const char *method, + DBusPendingCallNotifyFunction cb, + void *user_data, DBusFreeFunction free_func, + int timeout, int type, ...) +{ + DBusMessage *msg; + DBusPendingCall *call; + va_list args; + int err; + + msg = dbus_message_new_method_call(dest, path, interface, method); + if (!msg) { + ofono_error("Unable to allocate new D-Bus %s message", method); + err = -ENOMEM; + goto fail; + } + + va_start(args, type); + + if (!dbus_message_append_args_valist(msg, type, args)) { + va_end(args); + err = -EIO; + goto fail; + } + + va_end(args); + + if (timeout > 0) + timeout *= 1000; + + if (!dbus_connection_send_with_reply(connection, msg, &call, timeout)) { + ofono_error("Sending %s failed", method); + err = -EIO; + goto fail; + } + + dbus_pending_call_set_notify(call, cb, user_data, free_func); + dbus_pending_call_unref(call); + dbus_message_unref(msg); + + return 0; + +fail: + if (free_func && user_data) + free_func(user_data); + + if (msg) + dbus_message_unref(msg); + + return err; +} + +typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data); + +struct property_handler { + const char *property; + PropertyHandler callback; + gpointer user_data; +}; + +static gint property_handler_compare(gconstpointer a, gconstpointer b) +{ + const struct property_handler *handler = a; + const char *property = b; + + return strcmp(handler->property, property); +} + +static void parse_properties_reply(DBusMessage *reply, + const char *property, ...) +{ + va_list args; + GSList *prop_handlers = NULL; + DBusMessageIter array, dict; + + va_start(args, property); + + while (property != NULL) { + struct property_handler *handler = + g_new0(struct property_handler, 1); + + handler->property = property; + handler->callback = va_arg(args, PropertyHandler); + handler->user_data = va_arg(args, gpointer); + + property = va_arg(args, const char *); + + prop_handlers = g_slist_prepend(prop_handlers, handler); + } + + va_end(args); + + if (dbus_message_iter_init(reply, &array) == FALSE) + goto done; + + if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) + goto done; + + dbus_message_iter_recurse(&array, &dict); + + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value; + const char *key; + GSList *l; + + dbus_message_iter_recurse(&dict, &entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + goto done; + + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) + goto done; + + dbus_message_iter_recurse(&entry, &value); + + l = g_slist_find_custom(prop_handlers, key, + property_handler_compare); + + if (l) { + struct property_handler *handler = l->data; + + handler->callback(&value, handler->user_data); + } + + dbus_message_iter_next(&dict); + } + +done: + g_slist_foreach(prop_handlers, (GFunc)g_free, NULL); + g_slist_free(prop_handlers); +} + +static void has_uuid(DBusMessageIter *array, gpointer user_data) +{ + gboolean *profiles = user_data; + DBusMessageIter value; + + if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(array, &value); + + while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) { + const char *uuid; + + dbus_message_iter_get_basic(&value, &uuid); + + if (!strcasecmp(uuid, HFP_AG_UUID)) + *profiles |= HFP_AG; + + dbus_message_iter_next(&value); + } +} + +static void parse_string(DBusMessageIter *iter, gpointer user_data) +{ + char **str = user_data; + int arg_type = dbus_message_iter_get_arg_type(iter); + + if (arg_type != DBUS_TYPE_OBJECT_PATH && arg_type != DBUS_TYPE_STRING) + return; + + dbus_message_iter_get_basic(iter, str); +} + +static void device_properties_cb(DBusPendingCall *call, gpointer user_data) +{ + DBusMessage *reply; + int have_uuid = 0; + const char *path = user_data; + const char *adapter = NULL; + const char *adapter_addr = NULL; + const char *device_addr = NULL; + const char *alias = NULL; + struct bluetooth_profile *profile; + + reply = dbus_pending_call_steal_reply(call); + + if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { + DBG("Bluetooth daemon is apparently not available."); + goto done; + } + + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { + if (!dbus_message_is_error(reply, DBUS_ERROR_UNKNOWN_METHOD)) + ofono_info("Error from GetProperties reply: %s", + dbus_message_get_error_name(reply)); + + goto done; + } + + parse_properties_reply(reply, "UUIDs", has_uuid, &have_uuid, + "Adapter", parse_string, &adapter, + "Address", parse_string, &device_addr, + "Alias", parse_string, &alias, NULL); + + if (adapter) + adapter_addr = g_hash_table_lookup(adapter_address_hash, + adapter); + + if ((have_uuid & HFP_AG) && device_addr && adapter_addr) { + profile = g_hash_table_lookup(uuid_hash, HFP_AG_UUID); + profile->create(path, device_addr, adapter_addr, alias); + } + +done: + dbus_message_unref(reply); +} + +static void parse_devices(DBusMessageIter *array, gpointer user_data) +{ + DBusMessageIter value; + GSList **device_list = user_data; + + DBG(""); + + if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(array, &value); + + while (dbus_message_iter_get_arg_type(&value) + == DBUS_TYPE_OBJECT_PATH) { + const char *path; + + dbus_message_iter_get_basic(&value, &path); + + *device_list = g_slist_prepend(*device_list, (gpointer) path); + + dbus_message_iter_next(&value); + } +} + +static gboolean property_changed(DBusConnection *connection, DBusMessage *msg, + void *user_data) +{ + const char *property; + DBusMessageIter iter; + + dbus_message_iter_init(msg, &iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return FALSE; + + dbus_message_iter_get_basic(&iter, &property); + if (g_str_equal(property, "UUIDs") == TRUE) { + int profiles = 0; + const char *path = dbus_message_get_path(msg); + DBusMessageIter variant; + + + if (!dbus_message_iter_next(&iter)) + return FALSE; + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) + return FALSE; + + dbus_message_iter_recurse(&iter, &variant); + + has_uuid(&variant, &profiles); + + /* We need the full set of properties to be able to create + * the modem properly, including Adapter and Alias, so + * refetch everything again + */ + if (profiles) + send_method_call_with_reply(BLUEZ_SERVICE, path, + BLUEZ_DEVICE_INTERFACE, "GetProperties", + device_properties_cb, g_strdup(path), g_free, + -1, DBUS_TYPE_INVALID); + } else if (g_str_equal(property, "Alias") == TRUE) { + const char *path = dbus_message_get_path(msg); + struct bluetooth_profile *profile; + const char *alias = NULL; + DBusMessageIter variant; + GHashTableIter hash_iter; + gpointer key, value; + + if (!dbus_message_iter_next(&iter)) + return FALSE; + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) + return FALSE; + + dbus_message_iter_recurse(&iter, &variant); + + parse_string(&variant, &alias); + + g_hash_table_iter_init(&hash_iter, uuid_hash); + while (g_hash_table_iter_next(&hash_iter, &key, &value)) { + profile = value; + profile->set_alias(path, alias); + } + } + + return TRUE; +} + +static void adapter_properties_cb(DBusPendingCall *call, gpointer user_data) +{ + const char *path = user_data; + DBusMessage *reply; + GSList *device_list = NULL; + GSList *l; + const char *addr; + + reply = dbus_pending_call_steal_reply(call); + + if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { + DBG("Bluetooth daemon is apparently not available."); + goto done; + } + + parse_properties_reply(reply, "Devices", parse_devices, &device_list, + "Address", parse_string, &addr, NULL); + + DBG("Adapter Address: %s, Path: %s", addr, path); + g_hash_table_insert(adapter_address_hash, + g_strdup(path), g_strdup(addr)); + + for (l = device_list; l; l = l->next) { + const char *device = l->data; + + send_method_call_with_reply(BLUEZ_SERVICE, device, + BLUEZ_DEVICE_INTERFACE, "GetProperties", + device_properties_cb, g_strdup(device), g_free, + -1, DBUS_TYPE_INVALID); + } + +done: + g_slist_free(device_list); + dbus_message_unref(reply); +} + +static gboolean adapter_added(DBusConnection *connection, DBusMessage *message, + void *user_data) +{ + const char *path; + int ret; + + dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID); + + ret = send_method_call_with_reply(BLUEZ_SERVICE, path, + BLUEZ_ADAPTER_INTERFACE, "GetProperties", + adapter_properties_cb, g_strdup(path), g_free, + -1, DBUS_TYPE_INVALID); + + return TRUE; +} + +static gboolean adapter_removed(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + const char *path; + + if (dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID) == TRUE) + g_hash_table_remove(adapter_address_hash, path); + + return TRUE; +} + +static void parse_adapters(DBusMessageIter *array, gpointer user_data) +{ + DBusMessageIter value; + + DBG(""); + + if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(array, &value); + + while (dbus_message_iter_get_arg_type(&value) + == DBUS_TYPE_OBJECT_PATH) { + const char *path; + + dbus_message_iter_get_basic(&value, &path); + + DBG("Calling GetProperties on %s", path); + + send_method_call_with_reply(BLUEZ_SERVICE, path, + BLUEZ_ADAPTER_INTERFACE, "GetProperties", + adapter_properties_cb, g_strdup(path), g_free, + -1, DBUS_TYPE_INVALID); + + dbus_message_iter_next(&value); + } +} + +static void manager_properties_cb(DBusPendingCall *call, gpointer user_data) +{ + DBusMessage *reply; + + reply = dbus_pending_call_steal_reply(call); + + if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { + DBG("Bluetooth daemon is apparently not available."); + goto done; + } + + DBG(""); + + parse_properties_reply(reply, "Adapters", parse_adapters, NULL, NULL); + +done: + dbus_message_unref(reply); +} + +static void bluetooth_remove_all_modem(gpointer key, gpointer value, gpointer user_data) +{ + struct bluetooth_profile *profile = value; + + profile->remove_all(); +} + +static void bluetooth_disconnect(DBusConnection *connection, void *user_data) +{ + if (!uuid_hash) + return; + + g_hash_table_foreach(uuid_hash, bluetooth_remove_all_modem, NULL); +} + +static guint bluetooth_watch; +static guint adapter_added_watch; +static guint adapter_removed_watch; +static guint property_watch; + int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile) { + int err; + if (uuid_hash) goto done; connection = ofono_dbus_get_connection(); + bluetooth_watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE, + NULL, bluetooth_disconnect, NULL, NULL); + + adapter_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + BLUEZ_MANAGER_INTERFACE, + "AdapterAdded", + adapter_added, NULL, NULL); + + adapter_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + BLUEZ_MANAGER_INTERFACE, + "AdapterRemoved", + adapter_removed, NULL, NULL); + + property_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + BLUEZ_DEVICE_INTERFACE, + "PropertyChanged", + property_changed, NULL, NULL); + + if (bluetooth_watch == 0 || adapter_added_watch == 0 || + adapter_removed_watch == 0 || property_watch == 0) { + err = -EIO; + goto remove; + } + uuid_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); @@ -56,7 +517,19 @@ int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile) done: g_hash_table_insert(uuid_hash, g_strdup(uuid), profile); + send_method_call_with_reply(BLUEZ_SERVICE, "/", + BLUEZ_MANAGER_INTERFACE, "GetProperties", + manager_properties_cb, NULL, NULL, -1, + DBUS_TYPE_INVALID); + return 0; + +remove: + g_dbus_remove_watch(connection, bluetooth_watch); + g_dbus_remove_watch(connection, adapter_added_watch); + g_dbus_remove_watch(connection, adapter_removed_watch); + g_dbus_remove_watch(connection, property_watch); + return err; } void bluetooth_unregister_uuid(const char *uuid) @@ -66,6 +539,11 @@ void bluetooth_unregister_uuid(const char *uuid) if (g_hash_table_size(uuid_hash)) return; + g_dbus_remove_watch(connection, bluetooth_watch); + g_dbus_remove_watch(connection, adapter_added_watch); + g_dbus_remove_watch(connection, adapter_removed_watch); + g_dbus_remove_watch(connection, property_watch); + g_hash_table_destroy(uuid_hash); g_hash_table_destroy(adapter_address_hash); uuid_hash = NULL; diff --git a/plugins/hfp.c b/plugins/hfp.c index a49e4af..01d56fa 100644 --- a/plugins/hfp.c +++ b/plugins/hfp.c @@ -62,8 +62,7 @@ static const char *cmer_prefix[] = { "+CMER:", NULL }; static const char *chld_prefix[] = { "+CHLD:", NULL }; static DBusConnection *connection; -static GHashTable *uuid_hash = NULL; -static GHashTable *adapter_address_hash; +static GHashTable *modem_hash = NULL; static void hfp_debug(const char *str, void *user_data) { @@ -259,101 +258,6 @@ fail: return err; } -typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data); - -struct property_handler { - const char *property; - PropertyHandler callback; - gpointer user_data; -}; - -static gint property_handler_compare(gconstpointer a, gconstpointer b) -{ - const struct property_handler *handler = a; - const char *property = b; - - return strcmp(handler->property, property); -} - -static void parse_properties_reply(DBusMessage *reply, - const char *property, ...) -{ - va_list args; - GSList *prop_handlers = NULL; - DBusMessageIter array, dict; - - va_start(args, property); - - while (property != NULL) { - struct property_handler *handler = - g_new0(struct property_handler, 1); - - handler->property = property; - handler->callback = va_arg(args, PropertyHandler); - handler->user_data = va_arg(args, gpointer); - - property = va_arg(args, const char *); - - prop_handlers = g_slist_prepend(prop_handlers, handler); - } - - va_end(args); - - if (dbus_message_iter_init(reply, &array) == FALSE) - goto done; - - if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) - goto done; - - dbus_message_iter_recurse(&array, &dict); - - while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter entry, value; - const char *key; - GSList *l; - - dbus_message_iter_recurse(&dict, &entry); - - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) - goto done; - - dbus_message_iter_get_basic(&entry, &key); - - dbus_message_iter_next(&entry); - - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) - goto done; - - dbus_message_iter_recurse(&entry, &value); - - l = g_slist_find_custom(prop_handlers, key, - property_handler_compare); - - if (l) { - struct property_handler *handler = l->data; - - handler->callback(&value, handler->user_data); - } - - dbus_message_iter_next(&dict); - } - -done: - g_slist_foreach(prop_handlers, (GFunc)g_free, NULL); - g_slist_free(prop_handlers); -} - -static void parse_string(DBusMessageIter *iter, gpointer user_data) -{ - char **str = user_data; - int arg_type = dbus_message_iter_get_arg_type(iter); - - if (arg_type != DBUS_TYPE_OBJECT_PATH && arg_type != DBUS_TYPE_STRING) - return; - - dbus_message_iter_get_basic(iter, str); -} - static void cind_status_cb(gboolean ok, GAtResult *result, gpointer user_data) { @@ -596,6 +500,10 @@ static int hfp_create_modem(const char *device, const char *dev_addr, struct hfp_data *data; char buf[256]; + /* We already have this device in our hash, ignore */ + if (g_hash_table_lookup(modem_hash, device) != NULL) + return -EALREADY; + ofono_info("Using device: %s, devaddr: %s, adapter: %s", device, dev_addr, adapter_addr); @@ -624,7 +532,7 @@ static int hfp_create_modem(const char *device, const char *dev_addr, ofono_modem_set_name(modem, alias); ofono_modem_register(modem); - g_hash_table_insert(uuid_hash, g_strdup(device), modem); + g_hash_table_insert(modem_hash, g_strdup(device), modem); return 0; @@ -635,286 +543,35 @@ free: return -ENOMEM; } -static void has_hfp_uuid(DBusMessageIter *array, gpointer user_data) -{ - gboolean *hfp = user_data; - DBusMessageIter value; - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) - return; - - dbus_message_iter_recurse(array, &value); - - while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) { - const char *uuid; - - dbus_message_iter_get_basic(&value, &uuid); - - if (!strcasecmp(uuid, HFP_AG_UUID)) { - *hfp = TRUE; - return; - } - - dbus_message_iter_next(&value); - } -} - -static void device_properties_cb(DBusPendingCall *call, gpointer user_data) -{ - DBusMessage *reply; - char *path = user_data; - gboolean have_hfp = FALSE; - const char *adapter = NULL; - const char *adapter_addr = NULL; - const char *device_addr = NULL; - const char *alias = NULL; - - reply = dbus_pending_call_steal_reply(call); - - if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { - DBG("Bluetooth daemon is apparently not available."); - goto done; - } - - if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { - if (!dbus_message_is_error(reply, DBUS_ERROR_UNKNOWN_METHOD)) - ofono_info("Error from GetProperties reply: %s", - dbus_message_get_error_name(reply)); - - goto done; - } - - parse_properties_reply(reply, "UUIDs", has_hfp_uuid, &have_hfp, - "Adapter", parse_string, &adapter, - "Address", parse_string, &device_addr, - "Alias", parse_string, &alias, NULL); - - if (adapter) - adapter_addr = g_hash_table_lookup(adapter_address_hash, - adapter); - - if (have_hfp && device_addr && adapter_addr) - hfp_create_modem(path, device_addr, adapter_addr, alias); - -done: - dbus_message_unref(reply); -} - -static void parse_devices(DBusMessageIter *array, gpointer user_data) -{ - DBusMessageIter value; - GSList **device_list = user_data; - - DBG(""); - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) - return; - - dbus_message_iter_recurse(array, &value); - - while (dbus_message_iter_get_arg_type(&value) - == DBUS_TYPE_OBJECT_PATH) { - const char *path; - - dbus_message_iter_get_basic(&value, &path); - - *device_list = g_slist_prepend(*device_list, (gpointer) path); - - dbus_message_iter_next(&value); - } -} - -static void adapter_properties_cb(DBusPendingCall *call, gpointer user_data) -{ - const char *path = user_data; - DBusMessage *reply; - GSList *device_list = NULL; - GSList *l; - const char *addr; - - reply = dbus_pending_call_steal_reply(call); - - if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { - DBG("Bluetooth daemon is apparently not available."); - goto done; - } - - parse_properties_reply(reply, "Devices", parse_devices, &device_list, - "Address", parse_string, &addr, NULL); - - DBG("Adapter Address: %s, Path: %s", addr, path); - g_hash_table_insert(adapter_address_hash, - g_strdup(path), g_strdup(addr)); - - for (l = device_list; l; l = l->next) { - const char *device = l->data; - - send_method_call_with_reply(BLUEZ_SERVICE, device, - BLUEZ_DEVICE_INTERFACE, "GetProperties", - device_properties_cb, g_strdup(device), g_free, - -1, DBUS_TYPE_INVALID); - } - -done: - g_slist_free(device_list); - dbus_message_unref(reply); -} - -static gboolean adapter_added(DBusConnection *connection, DBusMessage *message, - void *user_data) -{ - const char *path; - int ret; - - dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - - ret = send_method_call_with_reply(BLUEZ_SERVICE, path, - BLUEZ_ADAPTER_INTERFACE, "GetProperties", - adapter_properties_cb, g_strdup(path), g_free, - -1, DBUS_TYPE_INVALID); - - return TRUE; -} - -static gboolean adapter_removed(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - const char *path; - - if (dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID) == TRUE) - g_hash_table_remove(adapter_address_hash, path); - - return TRUE; -} - -static gboolean property_changed(DBusConnection *connection, DBusMessage *msg, - void *user_data) +static gboolean hfp_remove_each_modem(gpointer key, gpointer value, gpointer user_data) { - const char *property; - DBusMessageIter iter; - - dbus_message_iter_init(msg, &iter); - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) - return FALSE; - - dbus_message_iter_get_basic(&iter, &property); - if (g_str_equal(property, "UUIDs") == TRUE) { - gboolean have_hfp = FALSE; - const char *path = dbus_message_get_path(msg); - DBusMessageIter variant; - - /* We already have this device in our hash, ignore */ - if (g_hash_table_lookup(uuid_hash, path) != NULL) - return TRUE; - - if (!dbus_message_iter_next(&iter)) - return FALSE; - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) - return FALSE; - - dbus_message_iter_recurse(&iter, &variant); - - has_hfp_uuid(&variant, &have_hfp); - - /* We need the full set of properties to be able to create - * the modem properly, including Adapter and Alias, so - * refetch everything again - */ - if (have_hfp) - send_method_call_with_reply(BLUEZ_SERVICE, path, - BLUEZ_DEVICE_INTERFACE, "GetProperties", - device_properties_cb, g_strdup(path), g_free, - -1, DBUS_TYPE_INVALID); - } else if (g_str_equal(property, "Alias") == TRUE) { - const char *path = dbus_message_get_path(msg); - struct ofono_modem *modem = - g_hash_table_lookup(uuid_hash, path); - const char *alias = NULL; - DBusMessageIter variant; - - if (modem == NULL) - return TRUE; - - if (!dbus_message_iter_next(&iter)) - return FALSE; - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) - return FALSE; - - dbus_message_iter_recurse(&iter, &variant); - - parse_string(&variant, &alias); + struct ofono_modem *modem = value; - ofono_modem_set_name(modem, alias); - } + ofono_modem_remove(modem); return TRUE; } -static void parse_adapters(DBusMessageIter *array, gpointer user_data) +static void hfp_remove_all_modem() { - DBusMessageIter value; - - DBG(""); - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) + if (modem_hash == NULL) return; - dbus_message_iter_recurse(array, &value); - - while (dbus_message_iter_get_arg_type(&value) - == DBUS_TYPE_OBJECT_PATH) { - const char *path; - - dbus_message_iter_get_basic(&value, &path); - - DBG("Calling GetProperties on %s", path); - - send_method_call_with_reply(BLUEZ_SERVICE, path, - BLUEZ_ADAPTER_INTERFACE, "GetProperties", - adapter_properties_cb, g_strdup(path), g_free, - -1, DBUS_TYPE_INVALID); - - dbus_message_iter_next(&value); - } -} - -static void manager_properties_cb(DBusPendingCall *call, gpointer user_data) -{ - DBusMessage *reply; - - reply = dbus_pending_call_steal_reply(call); - - if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { - DBG("Bluetooth daemon is apparently not available."); - goto done; - } - - parse_properties_reply(reply, "Adapters", parse_adapters, NULL, NULL); - -done: - dbus_message_unref(reply); + g_hash_table_foreach_remove(modem_hash, hfp_remove_each_modem, NULL); } -static gboolean hfp_remove_each_modem(gpointer key, gpointer value, gpointer user_data) +static void hfp_set_alias(const char *device, const char *alias) { - struct ofono_modem *modem = value; - - ofono_modem_remove(modem); + struct ofono_modem *modem; - return TRUE; -} + if (!device || !alias) + return; -static void bluetooth_disconnect(DBusConnection *connection, void *user_data) -{ - if (uuid_hash == NULL) + modem = g_hash_table_lookup(modem_hash, device); + if (!modem) return; - g_hash_table_foreach_remove(uuid_hash, hfp_remove_each_modem, NULL); + ofono_modem_set_name(modem, alias); } static int hfp_register_ofono_handsfree(struct ofono_modem *modem) @@ -971,7 +628,7 @@ static void hfp_remove(struct ofono_modem *modem) HFP_AGENT_INTERFACE)) hfp_unregister_ofono_handsfree(modem); - g_hash_table_remove(uuid_hash, data->handsfree_path); + g_hash_table_remove(modem_hash, data->handsfree_path); g_free(data->handsfree_path); g_free(data); @@ -1104,10 +761,12 @@ static struct ofono_modem_driver hfp_driver = { .post_sim = hfp_post_sim, }; -static guint bluetooth_exit_watch; -static guint adapter_added_watch; -static guint adapter_removed_watch; -static guint uuid_watch; +static struct bluetooth_profile hfp_profile = { + .name = "hfp", + .create = hfp_create_modem, + .remove_all = hfp_remove_all_modem, + .set_alias = hfp_set_alias, +}; static int hfp_init() { @@ -1118,73 +777,28 @@ static int hfp_init() connection = ofono_dbus_get_connection(); - bluetooth_exit_watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE, - NULL, bluetooth_disconnect, NULL, NULL); - - adapter_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, - BLUEZ_MANAGER_INTERFACE, - "AdapterAdded", - adapter_added, NULL, NULL); - - adapter_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, - BLUEZ_MANAGER_INTERFACE, - "AdapterRemoved", - adapter_removed, NULL, NULL); - - uuid_watch = g_dbus_add_signal_watch(connection, NULL, NULL, - BLUEZ_DEVICE_INTERFACE, - "PropertyChanged", - property_changed, NULL, NULL); + err = ofono_modem_driver_register(&hfp_driver); + if (err < 0) + return err; - if (bluetooth_exit_watch == 0 || adapter_added_watch == 0 || - adapter_removed_watch == 0|| uuid_watch == 0) { - err = -EIO; - goto remove; + err = bluetooth_register_uuid(HFP_AG_UUID, &hfp_profile); + if (err < 0) { + ofono_modem_driver_unregister(&hfp_driver); + return err; } - uuid_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - adapter_address_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - - err = ofono_modem_driver_register(&hfp_driver); - if (err < 0) - goto remove; - - send_method_call_with_reply(BLUEZ_SERVICE, "/", - BLUEZ_MANAGER_INTERFACE, "GetProperties", - manager_properties_cb, NULL, NULL, -1, - DBUS_TYPE_INVALID); - return 0; - -remove: - g_dbus_remove_watch(connection, bluetooth_exit_watch); - g_dbus_remove_watch(connection, adapter_added_watch); - g_dbus_remove_watch(connection, adapter_removed_watch); - g_dbus_remove_watch(connection, uuid_watch); - - if (uuid_hash) - g_hash_table_destroy(uuid_hash); - - if (adapter_address_hash) - g_hash_table_destroy(adapter_address_hash); - - return err; } static void hfp_exit() { - g_dbus_remove_watch(connection, bluetooth_exit_watch); - g_dbus_remove_watch(connection, adapter_added_watch); - g_dbus_remove_watch(connection, adapter_removed_watch); - g_dbus_remove_watch(connection, uuid_watch); - + bluetooth_unregister_uuid(HFP_AG_UUID); ofono_modem_driver_unregister(&hfp_driver); - g_hash_table_destroy(uuid_hash); - g_hash_table_destroy(adapter_address_hash); + g_hash_table_destroy(modem_hash); } OFONO_PLUGIN_DEFINE(hfp, "Hands-Free Profile Plugins", VERSION, -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/5] Remove send_method_call from hfp.c 2010-06-08 7:43 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Gustavo F. Padovan @ 2010-06-08 7:43 ` Gustavo F. Padovan 2010-06-08 7:43 ` [PATCH 4/5] Move create_path() to bluetooth plugin Gustavo F. Padovan 2010-06-10 21:17 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Denis Kenzior 1 sibling, 1 reply; 12+ messages in thread From: Gustavo F. Padovan @ 2010-06-08 7:43 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 4142 bytes --] That function should be only in the bluetooth plugin, then we can avoid code duplication. There is a plan to remove send_method_call_with_reply too once the Bluetooth agent moves to the bluetooth plugin. --- plugins/hfp.c | 73 +++++++++++++++++++++++++------------------------------- 1 files changed, 33 insertions(+), 40 deletions(-) diff --git a/plugins/hfp.c b/plugins/hfp.c index 01d56fa..6fd3464 100644 --- a/plugins/hfp.c +++ b/plugins/hfp.c @@ -178,33 +178,11 @@ static void cmer_cb(gboolean ok, GAtResult *result, gpointer user_data) sevice_level_conn_established(modem); } -static int send_method_call(const char *dest, const char *path, - const char *interface, const char *method, - int type, ...) -{ - DBusMessage *msg; - va_list args; - - msg = dbus_message_new_method_call(dest, path, interface, method); - if (!msg) { - ofono_error("Unable to allocate new D-Bus %s message", method); - return -ENOMEM; - } - - va_start(args, type); - - if (!dbus_message_append_args_valist(msg, type, args)) { - dbus_message_unref(msg); - va_end(args); - return -EIO; - } - - va_end(args); - - g_dbus_send_message(connection, msg); - return 0; -} - +/* + * FIXME: Group all agent stuff DBus calls in bluetooth.c + * then we can reuse common agent code for all Bluetooth plugins. + * That will remove this function from hfp.c + */ static int send_method_call_with_reply(const char *dest, const char *path, const char *interface, const char *method, DBusPendingCallNotifyFunction cb, @@ -578,26 +556,40 @@ static int hfp_register_ofono_handsfree(struct ofono_modem *modem) { const char *obj_path = ofono_modem_get_path(modem); struct hfp_data *data = ofono_modem_get_data(modem); + DBusMessage *msg; DBG("Registering oFono Agent to bluetooth daemon"); - return send_method_call(BLUEZ_SERVICE, data->handsfree_path, - BLUEZ_GATEWAY_INTERFACE, "RegisterAgent", - DBUS_TYPE_OBJECT_PATH, &obj_path, + msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path, + BLUEZ_GATEWAY_INTERFACE, "RegisterAgent"); + if (!msg) + return -ENOMEM; + + dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path, DBUS_TYPE_INVALID); + + g_dbus_send_message(connection, msg); + return 0; } static int hfp_unregister_ofono_handsfree(struct ofono_modem *modem) { const char *obj_path = ofono_modem_get_path(modem); struct hfp_data *data = ofono_modem_get_data(modem); + DBusMessage *msg; DBG("Unregistering oFono Agent from bluetooth daemon"); - return send_method_call(BLUEZ_SERVICE, data->handsfree_path, - BLUEZ_GATEWAY_INTERFACE, "UnregisterAgent", - DBUS_TYPE_OBJECT_PATH, &obj_path, + msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path, + BLUEZ_GATEWAY_INTERFACE, "UnregisterAgent"); + if (!msg) + return -ENOMEM; + + dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path, DBUS_TYPE_INVALID); + + g_dbus_send_message(connection, msg); + return 0; } static int hfp_probe(struct ofono_modem *modem) @@ -641,8 +633,7 @@ static void hfp_connect_reply(DBusPendingCall *call, gpointer user_data) struct ofono_modem *modem = user_data; struct hfp_data *data = ofono_modem_get_data(modem); DBusError derr; - DBusMessage *reply; - int ret; + DBusMessage *reply, *msg; reply = dbus_pending_call_steal_reply(call); @@ -656,11 +647,13 @@ static void hfp_connect_reply(DBusPendingCall *call, gpointer user_data) DBG("Connect reply: %s", derr.message); if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY)) { - ret = send_method_call(BLUEZ_SERVICE, data->handsfree_path, - BLUEZ_GATEWAY_INTERFACE, "Disconnect", - DBUS_TYPE_INVALID); - if (ret < 0) - ofono_error("Disconnect failed(%d)", ret); + msg = dbus_message_new_method_call(BLUEZ_SERVICE, + data->handsfree_path, + BLUEZ_GATEWAY_INTERFACE, "Disconnect"); + if (!msg) + ofono_error("Disconnect failed"); + else + g_dbus_send_message(connection, msg); } ofono_modem_set_powered(modem, FALSE); -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/5] Move create_path() to bluetooth plugin 2010-06-08 7:43 ` [PATCH 3/5] Remove send_method_call from hfp.c Gustavo F. Padovan @ 2010-06-08 7:43 ` Gustavo F. Padovan 2010-06-08 7:44 ` [PATCH 5/5] Remove hfpmodem's header guard Gustavo F. Padovan 0 siblings, 1 reply; 12+ messages in thread From: Gustavo F. Padovan @ 2010-06-08 7:43 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 3102 bytes --] --- plugins/bluetooth.c | 22 ++++++++++++++++++++++ plugins/bluetooth.h | 3 +++ plugins/hfp.c | 25 +------------------------ 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c index b452d73..4b3d94c 100644 --- a/plugins/bluetooth.c +++ b/plugins/bluetooth.c @@ -40,6 +40,28 @@ static DBusConnection *connection; static GHashTable *uuid_hash = NULL; static GHashTable *adapter_address_hash = NULL; +void bluetooth_create_path(const char *dev_addr, const char *adapter_addr, char *buf, int size) +{ + int i, j; + + for (i = 0, j = 0; adapter_addr[j] && i < size - 1; j++) + if (adapter_addr[j] >= '0' && adapter_addr[j] <= '9') + buf[i++] = adapter_addr[j]; + else if (adapter_addr[j] >= 'A' && adapter_addr[j] <= 'F') + buf[i++] = adapter_addr[j]; + + if (i < size - 1) + buf[i++] = '_'; + + for (j = 0; dev_addr[j] && i < size - 1; j++) + if (dev_addr[j] >= '0' && dev_addr[j] <= '9') + buf[i++] = dev_addr[j]; + else if (dev_addr[j] >= 'A' && dev_addr[j] <= 'F') + buf[i++] = dev_addr[j]; + + buf[i] = '\0'; +} + static int send_method_call_with_reply(const char *dest, const char *path, const char *interface, const char *method, DBusPendingCallNotifyFunction cb, diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h index 94ebaf6..430f4cf 100644 --- a/plugins/bluetooth.h +++ b/plugins/bluetooth.h @@ -40,3 +40,6 @@ int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile); void bluetooth_unregister_uuid(const char *uuid); +void bluetooth_create_path(const char *dev_addr, const char *adapter_addr, + char *buf, int size); + diff --git a/plugins/hfp.c b/plugins/hfp.c index 6fd3464..c2b3711 100644 --- a/plugins/hfp.c +++ b/plugins/hfp.c @@ -448,29 +448,6 @@ static GDBusMethodTable agent_methods[] = { { NULL, NULL, NULL, NULL } }; -static void create_path(const char *dev_addr, const char *adapter_addr, - char *buf, int size) -{ - int i, j; - - for (i = 0, j = 0; adapter_addr[j] && i < size - 1; j++) - if (adapter_addr[j] >= '0' && adapter_addr[j] <= '9') - buf[i++] = adapter_addr[j]; - else if (adapter_addr[j] >= 'A' && adapter_addr[j] <= 'F') - buf[i++] = adapter_addr[j]; - - if (i < size - 1) - buf[i++] = '_'; - - for (j = 0; dev_addr[j] && i < size - 1; j++) - if (dev_addr[j] >= '0' && dev_addr[j] <= '9') - buf[i++] = dev_addr[j]; - else if (dev_addr[j] >= 'A' && dev_addr[j] <= 'F') - buf[i++] = dev_addr[j]; - - buf[i] = '\0'; -} - static int hfp_create_modem(const char *device, const char *dev_addr, const char *adapter_addr, const char *alias) { @@ -486,7 +463,7 @@ static int hfp_create_modem(const char *device, const char *dev_addr, device, dev_addr, adapter_addr); strcpy(buf, "hfp/"); - create_path(dev_addr, adapter_addr, buf + 4, sizeof(buf) - 4); + bluetooth_create_path(dev_addr, adapter_addr, buf + 4, sizeof(buf) - 4); modem = ofono_modem_create(buf, "hfp"); if (modem == NULL) -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/5] Remove hfpmodem's header guard 2010-06-08 7:43 ` [PATCH 4/5] Move create_path() to bluetooth plugin Gustavo F. Padovan @ 2010-06-08 7:44 ` Gustavo F. Padovan 2010-06-10 21:19 ` Denis Kenzior 0 siblings, 1 reply; 12+ messages in thread From: Gustavo F. Padovan @ 2010-06-08 7:44 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 659 bytes --] --- drivers/hfpmodem/hfpmodem.h | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/drivers/hfpmodem/hfpmodem.h b/drivers/hfpmodem/hfpmodem.h index c95ea3f..bf5d563 100644 --- a/drivers/hfpmodem/hfpmodem.h +++ b/drivers/hfpmodem/hfpmodem.h @@ -18,8 +18,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ -#ifndef __BLUETOOTH_H__ -#define __BLUETOOTH_H__ #include <drivers/atmodem/atutil.h> #include <ofono/dbus.h> @@ -82,5 +80,3 @@ extern void hfp_call_volume_exit(); extern void hfp_voicecall_init(); extern void hfp_voicecall_exit(); - -#endif -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 5/5] Remove hfpmodem's header guard 2010-06-08 7:44 ` [PATCH 5/5] Remove hfpmodem's header guard Gustavo F. Padovan @ 2010-06-10 21:19 ` Denis Kenzior 0 siblings, 0 replies; 12+ messages in thread From: Denis Kenzior @ 2010-06-10 21:19 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 181 bytes --] Hi Gustavo, > --- > drivers/hfpmodem/hfpmodem.h | 4 ---- > 1 files changed, 0 insertions(+), 4 deletions(-) > This one has been applied, thanks. Regards, -Denis ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c 2010-06-08 7:43 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Gustavo F. Padovan 2010-06-08 7:43 ` [PATCH 3/5] Remove send_method_call from hfp.c Gustavo F. Padovan @ 2010-06-10 21:17 ` Denis Kenzior 2010-06-12 3:53 ` Gustavo F. Padovan 1 sibling, 1 reply; 12+ messages in thread From: Denis Kenzior @ 2010-06-10 21:17 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 6097 bytes --] Hi Gustavo, Please break this patch up more. You're moving functions but also modifying them in between. I'm getting lost. > +static int send_method_call_with_reply(const char *dest, const char *path, > + const char *interface, const char *method, > + DBusPendingCallNotifyFunction cb, > + void *user_data, DBusFreeFunction free_func, > + int timeout, int type, ...) > +{ > + DBusMessage *msg; > + DBusPendingCall *call; > + va_list args; > + int err; > + > + msg = dbus_message_new_method_call(dest, path, interface, method); > + if (!msg) { > + ofono_error("Unable to allocate new D-Bus %s message", method); > + err = -ENOMEM; > + goto fail; > + } > + > + va_start(args, type); > + > + if (!dbus_message_append_args_valist(msg, type, args)) { > + va_end(args); > + err = -EIO; > + goto fail; > + } > + > + va_end(args); > + > + if (timeout > 0) > + timeout *= 1000; > + > + if (!dbus_connection_send_with_reply(connection, msg, &call, timeout)) { > + ofono_error("Sending %s failed", method); > + err = -EIO; > + goto fail; > + } > + > + dbus_pending_call_set_notify(call, cb, user_data, free_func); > + dbus_pending_call_unref(call); > + dbus_message_unref(msg); > + > + return 0; > + > +fail: > + if (free_func && user_data) > + free_func(user_data); > + > + if (msg) > + dbus_message_unref(msg); > + > + return err; > +} So this should be in a separate patch... > + > +typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer > user_data); + > +struct property_handler { > + const char *property; > + PropertyHandler callback; > + gpointer user_data; > +}; > + > +static gint property_handler_compare(gconstpointer a, gconstpointer b) > +{ > + const struct property_handler *handler = a; > + const char *property = b; > + > + return strcmp(handler->property, property); > +} > + > +static void parse_properties_reply(DBusMessage *reply, > + const char *property, ...) > +{ > + va_list args; > + GSList *prop_handlers = NULL; > + DBusMessageIter array, dict; > + > + va_start(args, property); > + > + while (property != NULL) { > + struct property_handler *handler = > + g_new0(struct property_handler, 1); > + > + handler->property = property; > + handler->callback = va_arg(args, PropertyHandler); > + handler->user_data = va_arg(args, gpointer); > + > + property = va_arg(args, const char *); > + > + prop_handlers = g_slist_prepend(prop_handlers, handler); > + } > + > + va_end(args); > + > + if (dbus_message_iter_init(reply, &array) == FALSE) > + goto done; > + > + if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) > + goto done; > + > + dbus_message_iter_recurse(&array, &dict); > + > + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { > + DBusMessageIter entry, value; > + const char *key; > + GSList *l; > + > + dbus_message_iter_recurse(&dict, &entry); > + > + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) > + goto done; > + > + dbus_message_iter_get_basic(&entry, &key); > + > + dbus_message_iter_next(&entry); > + > + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) > + goto done; > + > + dbus_message_iter_recurse(&entry, &value); > + > + l = g_slist_find_custom(prop_handlers, key, > + property_handler_compare); > + > + if (l) { > + struct property_handler *handler = l->data; > + > + handler->callback(&value, handler->user_data); > + } > + > + dbus_message_iter_next(&dict); > + } > + > +done: > + g_slist_foreach(prop_handlers, (GFunc)g_free, NULL); > + g_slist_free(prop_handlers); > +} And this one too... > + > +static void has_uuid(DBusMessageIter *array, gpointer user_data) > +{ > + gboolean *profiles = user_data; > + DBusMessageIter value; > + > + if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) > + return; > + > + dbus_message_iter_recurse(array, &value); > + > + while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) { > + const char *uuid; > + > + dbus_message_iter_get_basic(&value, &uuid); > + > + if (!strcasecmp(uuid, HFP_AG_UUID)) > + *profiles |= HFP_AG; > + > + dbus_message_iter_next(&value); > + } > +} > + > +static void parse_string(DBusMessageIter *iter, gpointer user_data) > +{ > + char **str = user_data; > + int arg_type = dbus_message_iter_get_arg_type(iter); > + > + if (arg_type != DBUS_TYPE_OBJECT_PATH && arg_type != DBUS_TYPE_STRING) > + return; > + > + dbus_message_iter_get_basic(iter, str); > +} > + > +static void device_properties_cb(DBusPendingCall *call, gpointer > user_data) +{ > + DBusMessage *reply; > + int have_uuid = 0; > + const char *path = user_data; > + const char *adapter = NULL; > + const char *adapter_addr = NULL; > + const char *device_addr = NULL; > + const char *alias = NULL; > + struct bluetooth_profile *profile; > + > + reply = dbus_pending_call_steal_reply(call); > + > + if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { > + DBG("Bluetooth daemon is apparently not available."); > + goto done; > + } > + > + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { > + if (!dbus_message_is_error(reply, DBUS_ERROR_UNKNOWN_METHOD)) > + ofono_info("Error from GetProperties reply: %s", > + dbus_message_get_error_name(reply)); > + > + goto done; > + } > + > + parse_properties_reply(reply, "UUIDs", has_uuid, &have_uuid, > + "Adapter", parse_string, &adapter, > + "Address", parse_string, &device_addr, > + "Alias", parse_string, &alias, NULL); > + > + if (adapter) > + adapter_addr = g_hash_table_lookup(adapter_address_hash, > + adapter); > + > + if ((have_uuid & HFP_AG) && device_addr && adapter_addr) { > + profile = g_hash_table_lookup(uuid_hash, HFP_AG_UUID); > + profile->create(path, device_addr, adapter_addr, alias); No checking of profile NULL-ness or profile->create NULL-ness? I noticed a few instances of this. Regards, -Denis ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c 2010-06-10 21:17 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Denis Kenzior @ 2010-06-12 3:53 ` Gustavo F. Padovan 2010-06-12 4:09 ` Denis Kenzior 0 siblings, 1 reply; 12+ messages in thread From: Gustavo F. Padovan @ 2010-06-12 3:53 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 4276 bytes --] Hi Denis, * Denis Kenzior <denkenz@gmail.com> [2010-06-10 16:17:12 -0500]: > Hi Gustavo, > > Please break this patch up more. You're moving functions but also modifying > them in between. I'm getting lost. > > > +static int send_method_call_with_reply(const char *dest, const char *path, > > + const char *interface, const char *method, > > + DBusPendingCallNotifyFunction cb, > > + void *user_data, DBusFreeFunction free_func, > > + int timeout, int type, ...) > > +{ > > + DBusMessage *msg; > > + DBusPendingCall *call; > > + va_list args; > > + int err; > > + > > + msg = dbus_message_new_method_call(dest, path, interface, method); > > + if (!msg) { > > + ofono_error("Unable to allocate new D-Bus %s message", method); > > + err = -ENOMEM; > > + goto fail; > > + } > > + > > + va_start(args, type); > > + > > + if (!dbus_message_append_args_valist(msg, type, args)) { > > + va_end(args); > > + err = -EIO; > > + goto fail; > > + } > > + > > + va_end(args); > > + > > + if (timeout > 0) > > + timeout *= 1000; > > + > > + if (!dbus_connection_send_with_reply(connection, msg, &call, timeout)) { > > + ofono_error("Sending %s failed", method); > > + err = -EIO; > > + goto fail; > > + } > > + > > + dbus_pending_call_set_notify(call, cb, user_data, free_func); > > + dbus_pending_call_unref(call); > > + dbus_message_unref(msg); > > + > > + return 0; > > + > > +fail: > > + if (free_func && user_data) > > + free_func(user_data); > > + > > + if (msg) > > + dbus_message_unref(msg); > > + > > + return err; > > +} > > So this should be in a separate patch... If I put this in a separate patch, it won't compile because no one is using send_method_call_with_reply. > > > + > > +typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer > > user_data); + > > +struct property_handler { > > + const char *property; > > + PropertyHandler callback; > > + gpointer user_data; > > +}; > > + > > +static gint property_handler_compare(gconstpointer a, gconstpointer b) > > +{ > > + const struct property_handler *handler = a; > > + const char *property = b; > > + > > + return strcmp(handler->property, property); > > +} > > + > > +static void parse_properties_reply(DBusMessage *reply, > > + const char *property, ...) > > +{ > > + va_list args; > > + GSList *prop_handlers = NULL; > > + DBusMessageIter array, dict; > > + > > + va_start(args, property); > > + > > + while (property != NULL) { > > + struct property_handler *handler = > > + g_new0(struct property_handler, 1); > > + > > + handler->property = property; > > + handler->callback = va_arg(args, PropertyHandler); > > + handler->user_data = va_arg(args, gpointer); > > + > > + property = va_arg(args, const char *); > > + > > + prop_handlers = g_slist_prepend(prop_handlers, handler); > > + } > > + > > + va_end(args); > > + > > + if (dbus_message_iter_init(reply, &array) == FALSE) > > + goto done; > > + > > + if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) > > + goto done; > > + > > + dbus_message_iter_recurse(&array, &dict); > > + > > + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { > > + DBusMessageIter entry, value; > > + const char *key; > > + GSList *l; > > + > > + dbus_message_iter_recurse(&dict, &entry); > > + > > + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) > > + goto done; > > + > > + dbus_message_iter_get_basic(&entry, &key); > > + > > + dbus_message_iter_next(&entry); > > + > > + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) > > + goto done; > > + > > + dbus_message_iter_recurse(&entry, &value); > > + > > + l = g_slist_find_custom(prop_handlers, key, > > + property_handler_compare); > > + > > + if (l) { > > + struct property_handler *handler = l->data; > > + > > + handler->callback(&value, handler->user_data); > > + } > > + > > + dbus_message_iter_next(&dict); > > + } > > + > > +done: > > + g_slist_foreach(prop_handlers, (GFunc)g_free, NULL); > > + g_slist_free(prop_handlers); > > +} > > And this one too... Same here. -- Gustavo F. Padovan http://padovan.org ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c 2010-06-12 3:53 ` Gustavo F. Padovan @ 2010-06-12 4:09 ` Denis Kenzior 2010-06-12 5:13 ` Gustavo F. Padovan 0 siblings, 1 reply; 12+ messages in thread From: Denis Kenzior @ 2010-06-12 4:09 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 298 bytes --] Hi Gustavo, > > So this should be in a separate patch... > > If I put this in a separate patch, it won't compile because no one is > using send_method_call_with_reply. Its ok, I just want to be able to follow the patches. Breaking them up will be much easier on me. Regards, -Denis ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c 2010-06-12 4:09 ` Denis Kenzior @ 2010-06-12 5:13 ` Gustavo F. Padovan 0 siblings, 0 replies; 12+ messages in thread From: Gustavo F. Padovan @ 2010-06-12 5:13 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 466 bytes --] Hi Denis, * Denis Kenzior <denkenz@gmail.com> [2010-06-11 23:09:55 -0500]: > Hi Gustavo, > > > So this should be in a separate patch... > > > > If I put this in a separate patch, it won't compile because no one is > > using send_method_call_with_reply. > > Its ok, I just want to be able to follow the patches. Breaking them up will > be much easier on me. Ok, but we are breaking bisect this way. -- Gustavo F. Padovan http://padovan.org ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/5] Add bluetooth plugin skeleton. 2010-06-08 7:43 [PATCH 1/5] Add bluetooth plugin skeleton Gustavo F. Padovan 2010-06-08 7:43 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Gustavo F. Padovan @ 2010-06-10 21:13 ` Denis Kenzior 1 sibling, 0 replies; 12+ messages in thread From: Denis Kenzior @ 2010-06-10 21:13 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 187 bytes --] Hi Gustavo, > +builtin_modules += bluetooth > +builtin_sources += plugins/bluetooth.c Unfortunately this breaks make distcheck. Otherwise patch looks fine. Regards, -Denis ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/5] Add bluetooth plugin skeleton. @ 2010-06-05 2:40 Gustavo F. Padovan 2010-06-05 2:40 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Gustavo F. Padovan 0 siblings, 1 reply; 12+ messages in thread From: Gustavo F. Padovan @ 2010-06-05 2:40 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 5750 bytes --] The bluetooth plugin has bluetooth_resgister_uuid() and bluetooth_unresgister_uuid() where bluetooth profiles plugins such as HFP and DUN can register themselves to get know about BlueZ stuff ( new devices, bluetoothd shutdown, etc..) --- Makefile.am | 3 ++ plugins/bluetooth.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/bluetooth.h | 42 ++++++++++++++++++++++++++++ plugins/hfp.c | 8 +---- 4 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 plugins/bluetooth.c create mode 100644 plugins/bluetooth.h diff --git a/Makefile.am b/Makefile.am index f657a63..f6b12b2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -231,6 +231,9 @@ builtin_sources += plugins/em770.c builtin_modules += novatel builtin_sources += plugins/novatel.c +builtin_modules += bluetooth +builtin_sources += plugins/bluetooth.c + builtin_modules += hfp builtin_sources += plugins/hfp.c diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c new file mode 100644 index 0000000..b4fe676 --- /dev/null +++ b/plugins/bluetooth.c @@ -0,0 +1,75 @@ +/* + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. + * Copyright (C) 2010 ProFUSION embedded systems + * Copyright (C) 2010 Gustavo F. Padovan <gustavo@padovan.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <glib.h> +#include <gdbus.h> +#include <ofono.h> + +#include <ofono/dbus.h> + +#include "bluetooth.h" + +static DBusConnection *connection; +static GHashTable *uuid_hash = NULL; +static GHashTable *adapter_address_hash = NULL; + +int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile) +{ + if (uuid_hash) + goto done; + + connection = ofono_dbus_get_connection(); + + uuid_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + + adapter_address_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + +done: + g_hash_table_insert(uuid_hash, g_strdup(uuid), profile); + + return 0; +} + +void bluetooth_unregister_uuid(const char *uuid) +{ + g_hash_table_remove(uuid_hash, uuid); + + if (g_hash_table_size(uuid_hash)) + return; + + g_hash_table_destroy(uuid_hash); + g_hash_table_destroy(adapter_address_hash); + uuid_hash = NULL; +} + +OFONO_PLUGIN_DEFINE(bluetooth, "Bluetooth Utils Plugins", VERSION, + OFONO_PLUGIN_PRIORITY_DEFAULT, NULL, NULL) diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h new file mode 100644 index 0000000..94ebaf6 --- /dev/null +++ b/plugins/bluetooth.h @@ -0,0 +1,42 @@ +/* + * oFono - Open Source Telephony + * + * Copyright (C) 2010 Gustavo F. Padovan <gustavo@padovan.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#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 HFP_AG_UUID "0000111F-0000-1000-8000-00805F9B34FB" + +/* Profiles bitfield */ +#define HFP_AG 0x01 + +struct bluetooth_profile { + const char *name; + int (*create)(const char *device, const char *dev_addr, + const char *adapter_addr, const char *alias); + void (*remove_all)(); + void (*set_alias)(const char *device, const char *); +}; + +int bluetooth_register_uuid(const char *uuid, + struct bluetooth_profile *profile); +void bluetooth_unregister_uuid(const char *uuid); + diff --git a/plugins/hfp.c b/plugins/hfp.c index e37c9fc..a49e4af 100644 --- a/plugins/hfp.c +++ b/plugins/hfp.c @@ -45,17 +45,13 @@ #include <ofono/dbus.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" +#include "bluetooth.h" + #define BLUEZ_GATEWAY_INTERFACE BLUEZ_SERVICE ".HandsfreeGateway" #define HFP_AGENT_INTERFACE "org.bluez.HandsfreeAgent" #define HFP_AGENT_ERROR_INTERFACE "org.bluez.Error" -#define HFP_AG_UUID "0000111F-0000-1000-8000-00805F9B34FB" - #ifndef DBUS_TYPE_UNIX_FD #define DBUS_TYPE_UNIX_FD -1 #endif -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c 2010-06-05 2:40 Gustavo F. Padovan @ 2010-06-05 2:40 ` Gustavo F. Padovan 0 siblings, 0 replies; 12+ messages in thread From: Gustavo F. Padovan @ 2010-06-05 2:40 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 29443 bytes --] The new Bluetooth plugin will be responsible for handle DBus for the Bluetooth profiles implemented by oFono. Each Bluetooth profile can register callbacks to create a modem, remove all modems and set alias. The idea is to have here soon code the handle Bluetooth Agent stuff too. --- plugins/bluetooth.c | 481 +++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/hfp.c | 458 ++++-------------------------------------------- 2 files changed, 517 insertions(+), 422 deletions(-) diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c index b4fe676..8d022d4 100644 --- a/plugins/bluetooth.c +++ b/plugins/bluetooth.c @@ -40,13 +40,477 @@ static DBusConnection *connection; static GHashTable *uuid_hash = NULL; static GHashTable *adapter_address_hash = NULL; +static int send_method_call_with_reply(const char *dest, const char *path, + const char *interface, const char *method, + DBusPendingCallNotifyFunction cb, + void *user_data, DBusFreeFunction free_func, + int timeout, int type, ...) +{ + DBusMessage *msg; + DBusPendingCall *call; + va_list args; + int err; + + msg = dbus_message_new_method_call(dest, path, interface, method); + if (!msg) { + ofono_error("Unable to allocate new D-Bus %s message", method); + err = -ENOMEM; + goto fail; + } + + va_start(args, type); + + if (!dbus_message_append_args_valist(msg, type, args)) { + va_end(args); + err = -EIO; + goto fail; + } + + va_end(args); + + if (timeout > 0) + timeout *= 1000; + + if (!dbus_connection_send_with_reply(connection, msg, &call, timeout)) { + ofono_error("Sending %s failed", method); + err = -EIO; + goto fail; + } + + dbus_pending_call_set_notify(call, cb, user_data, free_func); + dbus_pending_call_unref(call); + dbus_message_unref(msg); + + return 0; + +fail: + if (free_func && user_data) + free_func(user_data); + + if (msg) + dbus_message_unref(msg); + + return err; +} + +typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data); + +struct property_handler { + const char *property; + PropertyHandler callback; + gpointer user_data; +}; + +static gint property_handler_compare(gconstpointer a, gconstpointer b) +{ + const struct property_handler *handler = a; + const char *property = b; + + return strcmp(handler->property, property); +} + +static void parse_properties_reply(DBusMessage *reply, + const char *property, ...) +{ + va_list args; + GSList *prop_handlers = NULL; + DBusMessageIter array, dict; + + va_start(args, property); + + while (property != NULL) { + struct property_handler *handler = + g_new0(struct property_handler, 1); + + handler->property = property; + handler->callback = va_arg(args, PropertyHandler); + handler->user_data = va_arg(args, gpointer); + + property = va_arg(args, const char *); + + prop_handlers = g_slist_prepend(prop_handlers, handler); + } + + va_end(args); + + if (dbus_message_iter_init(reply, &array) == FALSE) + goto done; + + if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) + goto done; + + dbus_message_iter_recurse(&array, &dict); + + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value; + const char *key; + GSList *l; + + dbus_message_iter_recurse(&dict, &entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + goto done; + + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) + goto done; + + dbus_message_iter_recurse(&entry, &value); + + l = g_slist_find_custom(prop_handlers, key, + property_handler_compare); + + if (l) { + struct property_handler *handler = l->data; + + handler->callback(&value, handler->user_data); + } + + dbus_message_iter_next(&dict); + } + +done: + g_slist_foreach(prop_handlers, (GFunc)g_free, NULL); + g_slist_free(prop_handlers); +} + +static void has_uuid(DBusMessageIter *array, gpointer user_data) +{ + gboolean *profiles = user_data; + DBusMessageIter value; + + if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(array, &value); + + while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) { + const char *uuid; + + dbus_message_iter_get_basic(&value, &uuid); + + if (!strcasecmp(uuid, HFP_AG_UUID)) + *profiles |= HFP_AG; + + if (!strcasecmp(uuid, DUN_GW_UUID)) + *profiles |= DUN_GW; + + dbus_message_iter_next(&value); + } +} + +static void parse_string(DBusMessageIter *iter, gpointer user_data) +{ + char **str = user_data; + int arg_type = dbus_message_iter_get_arg_type(iter); + + if (arg_type != DBUS_TYPE_OBJECT_PATH && arg_type != DBUS_TYPE_STRING) + return; + + dbus_message_iter_get_basic(iter, str); +} + +static void device_properties_cb(DBusPendingCall *call, gpointer user_data) +{ + DBusMessage *reply; + int have_uuid = 0; + const char *path = user_data; + const char *adapter = NULL; + const char *adapter_addr = NULL; + const char *device_addr = NULL; + const char *alias = NULL; + struct bluetooth_profile *profile; + + reply = dbus_pending_call_steal_reply(call); + + if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { + DBG("Bluetooth daemon is apparently not available."); + goto done; + } + + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { + if (!dbus_message_is_error(reply, DBUS_ERROR_UNKNOWN_METHOD)) + ofono_info("Error from GetProperties reply: %s", + dbus_message_get_error_name(reply)); + + goto done; + } + + parse_properties_reply(reply, "UUIDs", has_uuid, &have_uuid, + "Adapter", parse_string, &adapter, + "Address", parse_string, &device_addr, + "Alias", parse_string, &alias, NULL); + + if (adapter) + adapter_addr = g_hash_table_lookup(adapter_address_hash, + adapter); + + if ((have_uuid & HFP_AG) && device_addr && adapter_addr) { + profile = g_hash_table_lookup(uuid_hash, HFP_AG_UUID); + profile->create(path, device_addr, adapter_addr, alias); + } + +done: + dbus_message_unref(reply); +} + +static void parse_devices(DBusMessageIter *array, gpointer user_data) +{ + DBusMessageIter value; + GSList **device_list = user_data; + + DBG(""); + + if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(array, &value); + + while (dbus_message_iter_get_arg_type(&value) + == DBUS_TYPE_OBJECT_PATH) { + const char *path; + + dbus_message_iter_get_basic(&value, &path); + + *device_list = g_slist_prepend(*device_list, (gpointer) path); + + dbus_message_iter_next(&value); + } +} + +static gboolean property_changed(DBusConnection *connection, DBusMessage *msg, + void *user_data) +{ + const char *property; + DBusMessageIter iter; + + dbus_message_iter_init(msg, &iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return FALSE; + + dbus_message_iter_get_basic(&iter, &property); + if (g_str_equal(property, "UUIDs") == TRUE) { + int profiles = 0; + const char *path = dbus_message_get_path(msg); + DBusMessageIter variant; + + + if (!dbus_message_iter_next(&iter)) + return FALSE; + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) + return FALSE; + + dbus_message_iter_recurse(&iter, &variant); + + has_uuid(&variant, &profiles); + + /* We need the full set of properties to be able to create + * the modem properly, including Adapter and Alias, so + * refetch everything again + */ + if (profiles) + send_method_call_with_reply(BLUEZ_SERVICE, path, + BLUEZ_DEVICE_INTERFACE, "GetProperties", + device_properties_cb, g_strdup(path), g_free, + -1, DBUS_TYPE_INVALID); + } else if (g_str_equal(property, "Alias") == TRUE) { + const char *path = dbus_message_get_path(msg); + struct bluetooth_profile *profile; + const char *alias = NULL; + DBusMessageIter variant; + GHashTableIter hash_iter; + gpointer key, value; + + if (!dbus_message_iter_next(&iter)) + return FALSE; + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) + return FALSE; + + dbus_message_iter_recurse(&iter, &variant); + + parse_string(&variant, &alias); + + g_hash_table_iter_init(&hash_iter, uuid_hash); + while (g_hash_table_iter_next(&hash_iter, &key, &value)) { + profile = value; + profile->set_alias(path, alias); + } + } + + return TRUE; +} + +static void adapter_properties_cb(DBusPendingCall *call, gpointer user_data) +{ + const char *path = user_data; + DBusMessage *reply; + GSList *device_list = NULL; + GSList *l; + const char *addr; + + reply = dbus_pending_call_steal_reply(call); + + if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { + DBG("Bluetooth daemon is apparently not available."); + goto done; + } + + parse_properties_reply(reply, "Devices", parse_devices, &device_list, + "Address", parse_string, &addr, NULL); + + DBG("Adapter Address: %s, Path: %s", addr, path); + g_hash_table_insert(adapter_address_hash, + g_strdup(path), g_strdup(addr)); + + for (l = device_list; l; l = l->next) { + const char *device = l->data; + + send_method_call_with_reply(BLUEZ_SERVICE, device, + BLUEZ_DEVICE_INTERFACE, "GetProperties", + device_properties_cb, g_strdup(device), g_free, + -1, DBUS_TYPE_INVALID); + } + +done: + g_slist_free(device_list); + dbus_message_unref(reply); +} + +static gboolean adapter_added(DBusConnection *connection, DBusMessage *message, + void *user_data) +{ + const char *path; + int ret; + + dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID); + + ret = send_method_call_with_reply(BLUEZ_SERVICE, path, + BLUEZ_ADAPTER_INTERFACE, "GetProperties", + adapter_properties_cb, g_strdup(path), g_free, + -1, DBUS_TYPE_INVALID); + + return TRUE; +} + +static gboolean adapter_removed(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + const char *path; + + if (dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID) == TRUE) + g_hash_table_remove(adapter_address_hash, path); + + return TRUE; +} + +static void parse_adapters(DBusMessageIter *array, gpointer user_data) +{ + DBusMessageIter value; + + DBG(""); + + if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(array, &value); + + while (dbus_message_iter_get_arg_type(&value) + == DBUS_TYPE_OBJECT_PATH) { + const char *path; + + dbus_message_iter_get_basic(&value, &path); + + DBG("Calling GetProperties on %s", path); + + send_method_call_with_reply(BLUEZ_SERVICE, path, + BLUEZ_ADAPTER_INTERFACE, "GetProperties", + adapter_properties_cb, g_strdup(path), g_free, + -1, DBUS_TYPE_INVALID); + + dbus_message_iter_next(&value); + } +} + +static void manager_properties_cb(DBusPendingCall *call, gpointer user_data) +{ + DBusMessage *reply; + + reply = dbus_pending_call_steal_reply(call); + + if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { + DBG("Bluetooth daemon is apparently not available."); + goto done; + } + + DBG(""); + + parse_properties_reply(reply, "Adapters", parse_adapters, NULL, NULL); + +done: + dbus_message_unref(reply); +} + +static void bluetooth_remove_all_modem(gpointer key, gpointer value, gpointer user_data) +{ + struct bluetooth_profile *profile = value; + + profile->remove_all(); +} + +static void bluetooth_disconnect(DBusConnection *connection, void *user_data) +{ + if (!uuid_hash) + return; + + g_hash_table_foreach(uuid_hash, bluetooth_remove_all_modem, NULL); +} + +static guint bluetooth_watch; +static guint adapter_added_watch; +static guint adapter_removed_watch; +static guint property_watch; + int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile) { + int err; + if (uuid_hash) goto done; connection = ofono_dbus_get_connection(); + bluetooth_watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE, + NULL, bluetooth_disconnect, NULL, NULL); + + adapter_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + BLUEZ_MANAGER_INTERFACE, + "AdapterAdded", + adapter_added, NULL, NULL); + + adapter_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + BLUEZ_MANAGER_INTERFACE, + "AdapterRemoved", + adapter_removed, NULL, NULL); + + property_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + BLUEZ_DEVICE_INTERFACE, + "PropertyChanged", + property_changed, NULL, NULL); + + if (bluetooth_watch == 0 || adapter_added_watch == 0 || + adapter_removed_watch == 0 || property_watch == 0) { + err = -EIO; + goto remove; + } + uuid_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); @@ -56,7 +520,19 @@ int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile) done: g_hash_table_insert(uuid_hash, g_strdup(uuid), profile); + send_method_call_with_reply(BLUEZ_SERVICE, "/", + BLUEZ_MANAGER_INTERFACE, "GetProperties", + manager_properties_cb, NULL, NULL, -1, + DBUS_TYPE_INVALID); + return 0; + +remove: + g_dbus_remove_watch(connection, bluetooth_watch); + g_dbus_remove_watch(connection, adapter_added_watch); + g_dbus_remove_watch(connection, adapter_removed_watch); + g_dbus_remove_watch(connection, property_watch); + return err; } void bluetooth_unregister_uuid(const char *uuid) @@ -66,6 +542,11 @@ void bluetooth_unregister_uuid(const char *uuid) if (g_hash_table_size(uuid_hash)) return; + g_dbus_remove_watch(connection, bluetooth_watch); + g_dbus_remove_watch(connection, adapter_added_watch); + g_dbus_remove_watch(connection, adapter_removed_watch); + g_dbus_remove_watch(connection, property_watch); + g_hash_table_destroy(uuid_hash); g_hash_table_destroy(adapter_address_hash); uuid_hash = NULL; diff --git a/plugins/hfp.c b/plugins/hfp.c index a49e4af..01d56fa 100644 --- a/plugins/hfp.c +++ b/plugins/hfp.c @@ -62,8 +62,7 @@ static const char *cmer_prefix[] = { "+CMER:", NULL }; static const char *chld_prefix[] = { "+CHLD:", NULL }; static DBusConnection *connection; -static GHashTable *uuid_hash = NULL; -static GHashTable *adapter_address_hash; +static GHashTable *modem_hash = NULL; static void hfp_debug(const char *str, void *user_data) { @@ -259,101 +258,6 @@ fail: return err; } -typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data); - -struct property_handler { - const char *property; - PropertyHandler callback; - gpointer user_data; -}; - -static gint property_handler_compare(gconstpointer a, gconstpointer b) -{ - const struct property_handler *handler = a; - const char *property = b; - - return strcmp(handler->property, property); -} - -static void parse_properties_reply(DBusMessage *reply, - const char *property, ...) -{ - va_list args; - GSList *prop_handlers = NULL; - DBusMessageIter array, dict; - - va_start(args, property); - - while (property != NULL) { - struct property_handler *handler = - g_new0(struct property_handler, 1); - - handler->property = property; - handler->callback = va_arg(args, PropertyHandler); - handler->user_data = va_arg(args, gpointer); - - property = va_arg(args, const char *); - - prop_handlers = g_slist_prepend(prop_handlers, handler); - } - - va_end(args); - - if (dbus_message_iter_init(reply, &array) == FALSE) - goto done; - - if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) - goto done; - - dbus_message_iter_recurse(&array, &dict); - - while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter entry, value; - const char *key; - GSList *l; - - dbus_message_iter_recurse(&dict, &entry); - - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) - goto done; - - dbus_message_iter_get_basic(&entry, &key); - - dbus_message_iter_next(&entry); - - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) - goto done; - - dbus_message_iter_recurse(&entry, &value); - - l = g_slist_find_custom(prop_handlers, key, - property_handler_compare); - - if (l) { - struct property_handler *handler = l->data; - - handler->callback(&value, handler->user_data); - } - - dbus_message_iter_next(&dict); - } - -done: - g_slist_foreach(prop_handlers, (GFunc)g_free, NULL); - g_slist_free(prop_handlers); -} - -static void parse_string(DBusMessageIter *iter, gpointer user_data) -{ - char **str = user_data; - int arg_type = dbus_message_iter_get_arg_type(iter); - - if (arg_type != DBUS_TYPE_OBJECT_PATH && arg_type != DBUS_TYPE_STRING) - return; - - dbus_message_iter_get_basic(iter, str); -} - static void cind_status_cb(gboolean ok, GAtResult *result, gpointer user_data) { @@ -596,6 +500,10 @@ static int hfp_create_modem(const char *device, const char *dev_addr, struct hfp_data *data; char buf[256]; + /* We already have this device in our hash, ignore */ + if (g_hash_table_lookup(modem_hash, device) != NULL) + return -EALREADY; + ofono_info("Using device: %s, devaddr: %s, adapter: %s", device, dev_addr, adapter_addr); @@ -624,7 +532,7 @@ static int hfp_create_modem(const char *device, const char *dev_addr, ofono_modem_set_name(modem, alias); ofono_modem_register(modem); - g_hash_table_insert(uuid_hash, g_strdup(device), modem); + g_hash_table_insert(modem_hash, g_strdup(device), modem); return 0; @@ -635,286 +543,35 @@ free: return -ENOMEM; } -static void has_hfp_uuid(DBusMessageIter *array, gpointer user_data) -{ - gboolean *hfp = user_data; - DBusMessageIter value; - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) - return; - - dbus_message_iter_recurse(array, &value); - - while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) { - const char *uuid; - - dbus_message_iter_get_basic(&value, &uuid); - - if (!strcasecmp(uuid, HFP_AG_UUID)) { - *hfp = TRUE; - return; - } - - dbus_message_iter_next(&value); - } -} - -static void device_properties_cb(DBusPendingCall *call, gpointer user_data) -{ - DBusMessage *reply; - char *path = user_data; - gboolean have_hfp = FALSE; - const char *adapter = NULL; - const char *adapter_addr = NULL; - const char *device_addr = NULL; - const char *alias = NULL; - - reply = dbus_pending_call_steal_reply(call); - - if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { - DBG("Bluetooth daemon is apparently not available."); - goto done; - } - - if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { - if (!dbus_message_is_error(reply, DBUS_ERROR_UNKNOWN_METHOD)) - ofono_info("Error from GetProperties reply: %s", - dbus_message_get_error_name(reply)); - - goto done; - } - - parse_properties_reply(reply, "UUIDs", has_hfp_uuid, &have_hfp, - "Adapter", parse_string, &adapter, - "Address", parse_string, &device_addr, - "Alias", parse_string, &alias, NULL); - - if (adapter) - adapter_addr = g_hash_table_lookup(adapter_address_hash, - adapter); - - if (have_hfp && device_addr && adapter_addr) - hfp_create_modem(path, device_addr, adapter_addr, alias); - -done: - dbus_message_unref(reply); -} - -static void parse_devices(DBusMessageIter *array, gpointer user_data) -{ - DBusMessageIter value; - GSList **device_list = user_data; - - DBG(""); - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) - return; - - dbus_message_iter_recurse(array, &value); - - while (dbus_message_iter_get_arg_type(&value) - == DBUS_TYPE_OBJECT_PATH) { - const char *path; - - dbus_message_iter_get_basic(&value, &path); - - *device_list = g_slist_prepend(*device_list, (gpointer) path); - - dbus_message_iter_next(&value); - } -} - -static void adapter_properties_cb(DBusPendingCall *call, gpointer user_data) -{ - const char *path = user_data; - DBusMessage *reply; - GSList *device_list = NULL; - GSList *l; - const char *addr; - - reply = dbus_pending_call_steal_reply(call); - - if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { - DBG("Bluetooth daemon is apparently not available."); - goto done; - } - - parse_properties_reply(reply, "Devices", parse_devices, &device_list, - "Address", parse_string, &addr, NULL); - - DBG("Adapter Address: %s, Path: %s", addr, path); - g_hash_table_insert(adapter_address_hash, - g_strdup(path), g_strdup(addr)); - - for (l = device_list; l; l = l->next) { - const char *device = l->data; - - send_method_call_with_reply(BLUEZ_SERVICE, device, - BLUEZ_DEVICE_INTERFACE, "GetProperties", - device_properties_cb, g_strdup(device), g_free, - -1, DBUS_TYPE_INVALID); - } - -done: - g_slist_free(device_list); - dbus_message_unref(reply); -} - -static gboolean adapter_added(DBusConnection *connection, DBusMessage *message, - void *user_data) -{ - const char *path; - int ret; - - dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - - ret = send_method_call_with_reply(BLUEZ_SERVICE, path, - BLUEZ_ADAPTER_INTERFACE, "GetProperties", - adapter_properties_cb, g_strdup(path), g_free, - -1, DBUS_TYPE_INVALID); - - return TRUE; -} - -static gboolean adapter_removed(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - const char *path; - - if (dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID) == TRUE) - g_hash_table_remove(adapter_address_hash, path); - - return TRUE; -} - -static gboolean property_changed(DBusConnection *connection, DBusMessage *msg, - void *user_data) +static gboolean hfp_remove_each_modem(gpointer key, gpointer value, gpointer user_data) { - const char *property; - DBusMessageIter iter; - - dbus_message_iter_init(msg, &iter); - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) - return FALSE; - - dbus_message_iter_get_basic(&iter, &property); - if (g_str_equal(property, "UUIDs") == TRUE) { - gboolean have_hfp = FALSE; - const char *path = dbus_message_get_path(msg); - DBusMessageIter variant; - - /* We already have this device in our hash, ignore */ - if (g_hash_table_lookup(uuid_hash, path) != NULL) - return TRUE; - - if (!dbus_message_iter_next(&iter)) - return FALSE; - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) - return FALSE; - - dbus_message_iter_recurse(&iter, &variant); - - has_hfp_uuid(&variant, &have_hfp); - - /* We need the full set of properties to be able to create - * the modem properly, including Adapter and Alias, so - * refetch everything again - */ - if (have_hfp) - send_method_call_with_reply(BLUEZ_SERVICE, path, - BLUEZ_DEVICE_INTERFACE, "GetProperties", - device_properties_cb, g_strdup(path), g_free, - -1, DBUS_TYPE_INVALID); - } else if (g_str_equal(property, "Alias") == TRUE) { - const char *path = dbus_message_get_path(msg); - struct ofono_modem *modem = - g_hash_table_lookup(uuid_hash, path); - const char *alias = NULL; - DBusMessageIter variant; - - if (modem == NULL) - return TRUE; - - if (!dbus_message_iter_next(&iter)) - return FALSE; - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) - return FALSE; - - dbus_message_iter_recurse(&iter, &variant); - - parse_string(&variant, &alias); + struct ofono_modem *modem = value; - ofono_modem_set_name(modem, alias); - } + ofono_modem_remove(modem); return TRUE; } -static void parse_adapters(DBusMessageIter *array, gpointer user_data) +static void hfp_remove_all_modem() { - DBusMessageIter value; - - DBG(""); - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) + if (modem_hash == NULL) return; - dbus_message_iter_recurse(array, &value); - - while (dbus_message_iter_get_arg_type(&value) - == DBUS_TYPE_OBJECT_PATH) { - const char *path; - - dbus_message_iter_get_basic(&value, &path); - - DBG("Calling GetProperties on %s", path); - - send_method_call_with_reply(BLUEZ_SERVICE, path, - BLUEZ_ADAPTER_INTERFACE, "GetProperties", - adapter_properties_cb, g_strdup(path), g_free, - -1, DBUS_TYPE_INVALID); - - dbus_message_iter_next(&value); - } -} - -static void manager_properties_cb(DBusPendingCall *call, gpointer user_data) -{ - DBusMessage *reply; - - reply = dbus_pending_call_steal_reply(call); - - if (dbus_message_is_error(reply, DBUS_ERROR_SERVICE_UNKNOWN)) { - DBG("Bluetooth daemon is apparently not available."); - goto done; - } - - parse_properties_reply(reply, "Adapters", parse_adapters, NULL, NULL); - -done: - dbus_message_unref(reply); + g_hash_table_foreach_remove(modem_hash, hfp_remove_each_modem, NULL); } -static gboolean hfp_remove_each_modem(gpointer key, gpointer value, gpointer user_data) +static void hfp_set_alias(const char *device, const char *alias) { - struct ofono_modem *modem = value; - - ofono_modem_remove(modem); + struct ofono_modem *modem; - return TRUE; -} + if (!device || !alias) + return; -static void bluetooth_disconnect(DBusConnection *connection, void *user_data) -{ - if (uuid_hash == NULL) + modem = g_hash_table_lookup(modem_hash, device); + if (!modem) return; - g_hash_table_foreach_remove(uuid_hash, hfp_remove_each_modem, NULL); + ofono_modem_set_name(modem, alias); } static int hfp_register_ofono_handsfree(struct ofono_modem *modem) @@ -971,7 +628,7 @@ static void hfp_remove(struct ofono_modem *modem) HFP_AGENT_INTERFACE)) hfp_unregister_ofono_handsfree(modem); - g_hash_table_remove(uuid_hash, data->handsfree_path); + g_hash_table_remove(modem_hash, data->handsfree_path); g_free(data->handsfree_path); g_free(data); @@ -1104,10 +761,12 @@ static struct ofono_modem_driver hfp_driver = { .post_sim = hfp_post_sim, }; -static guint bluetooth_exit_watch; -static guint adapter_added_watch; -static guint adapter_removed_watch; -static guint uuid_watch; +static struct bluetooth_profile hfp_profile = { + .name = "hfp", + .create = hfp_create_modem, + .remove_all = hfp_remove_all_modem, + .set_alias = hfp_set_alias, +}; static int hfp_init() { @@ -1118,73 +777,28 @@ static int hfp_init() connection = ofono_dbus_get_connection(); - bluetooth_exit_watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE, - NULL, bluetooth_disconnect, NULL, NULL); - - adapter_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, - BLUEZ_MANAGER_INTERFACE, - "AdapterAdded", - adapter_added, NULL, NULL); - - adapter_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, - BLUEZ_MANAGER_INTERFACE, - "AdapterRemoved", - adapter_removed, NULL, NULL); - - uuid_watch = g_dbus_add_signal_watch(connection, NULL, NULL, - BLUEZ_DEVICE_INTERFACE, - "PropertyChanged", - property_changed, NULL, NULL); + err = ofono_modem_driver_register(&hfp_driver); + if (err < 0) + return err; - if (bluetooth_exit_watch == 0 || adapter_added_watch == 0 || - adapter_removed_watch == 0|| uuid_watch == 0) { - err = -EIO; - goto remove; + err = bluetooth_register_uuid(HFP_AG_UUID, &hfp_profile); + if (err < 0) { + ofono_modem_driver_unregister(&hfp_driver); + return err; } - uuid_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - adapter_address_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - - err = ofono_modem_driver_register(&hfp_driver); - if (err < 0) - goto remove; - - send_method_call_with_reply(BLUEZ_SERVICE, "/", - BLUEZ_MANAGER_INTERFACE, "GetProperties", - manager_properties_cb, NULL, NULL, -1, - DBUS_TYPE_INVALID); - return 0; - -remove: - g_dbus_remove_watch(connection, bluetooth_exit_watch); - g_dbus_remove_watch(connection, adapter_added_watch); - g_dbus_remove_watch(connection, adapter_removed_watch); - g_dbus_remove_watch(connection, uuid_watch); - - if (uuid_hash) - g_hash_table_destroy(uuid_hash); - - if (adapter_address_hash) - g_hash_table_destroy(adapter_address_hash); - - return err; } static void hfp_exit() { - g_dbus_remove_watch(connection, bluetooth_exit_watch); - g_dbus_remove_watch(connection, adapter_added_watch); - g_dbus_remove_watch(connection, adapter_removed_watch); - g_dbus_remove_watch(connection, uuid_watch); - + bluetooth_unregister_uuid(HFP_AG_UUID); ofono_modem_driver_unregister(&hfp_driver); - g_hash_table_destroy(uuid_hash); - g_hash_table_destroy(adapter_address_hash); + g_hash_table_destroy(modem_hash); } OFONO_PLUGIN_DEFINE(hfp, "Hands-Free Profile Plugins", VERSION, -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2010-06-12 5:13 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-06-08 7:43 [PATCH 1/5] Add bluetooth plugin skeleton Gustavo F. Padovan 2010-06-08 7:43 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Gustavo F. Padovan 2010-06-08 7:43 ` [PATCH 3/5] Remove send_method_call from hfp.c Gustavo F. Padovan 2010-06-08 7:43 ` [PATCH 4/5] Move create_path() to bluetooth plugin Gustavo F. Padovan 2010-06-08 7:44 ` [PATCH 5/5] Remove hfpmodem's header guard Gustavo F. Padovan 2010-06-10 21:19 ` Denis Kenzior 2010-06-10 21:17 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Denis Kenzior 2010-06-12 3:53 ` Gustavo F. Padovan 2010-06-12 4:09 ` Denis Kenzior 2010-06-12 5:13 ` Gustavo F. Padovan 2010-06-10 21:13 ` [PATCH 1/5] Add bluetooth plugin skeleton Denis Kenzior -- strict thread matches above, loose matches on Subject: below -- 2010-06-05 2:40 Gustavo F. Padovan 2010-06-05 2:40 ` [PATCH 2/5] Move bluetooth utils from hfp.c to bluetooth.c Gustavo F. Padovan
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.