This patch adds NewConnection message arguments parsing: features,
version and Media Endpoints included in the fd_properties dictionary.
---
 Makefile.am             |   3 +-
 plugins/bluez5.c        |  81 +++++++++++++++++++++++++++
 plugins/bluez5.h        |   3 +
 plugins/hfp_hf_bluez5.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++-
 plugins/media.c         |  63 +++++++++++++++++++++
 plugins/media.h         |  29 ++++++++++
 6 files changed, 319 insertions(+), 4 deletions(-)
 create mode 100644 plugins/media.c
 create mode 100644 plugins/media.h

diff --git a/Makefile.am b/Makefile.am
index f24cac7..f1d241f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -438,7 +438,8 @@ builtin_modules += bluez5
 builtin_sources += plugins/bluez5.c plugins/bluez5.h
 
 builtin_modules += hfp_bluez5
-builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
+builtin_sources += plugins/bluez5.h plugins/media.h \
+                       plugins/media.c plugins/hfp_hf_bluez5.c
 endif
 endif
 endif
diff --git a/plugins/bluez5.c b/plugins/bluez5.c
index 84ba47d..6ba5ea1 100644
--- a/plugins/bluez5.c
+++ b/plugins/bluez5.c
@@ -36,6 +36,87 @@
 
 #define BLUEZ_PROFILE_MGMT_INTERFACE   BLUEZ_SERVICE ".ProfileManager1"
 
+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 g_strcmp0(handler->property, property);
+}
+
+void bluetooth_iter_parse_properties(DBusMessageIter *array,
+                                               const char *property, ...)
+{
+       va_list args;
+       GSList *prop_handlers = NULL;
+       DBusMessageIter dict;
+
+       if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
+               goto done;
+
+       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);
+
+       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 profile_register_cb(DBusPendingCall *call, gpointer user_data)
 {
        DBusMessage *reply;
diff --git a/plugins/bluez5.h b/plugins/bluez5.h
index 01ecfe8..7eae8c4 100644
--- a/plugins/bluez5.h
+++ b/plugins/bluez5.h
@@ -29,3 +29,6 @@ int bluetooth_register_profile(DBusConnection *conn, const 
char *uuid,
                                        const char *name, const char *object);
 
 void bluetooth_unregister_profile(DBusConnection *conn, const char *object);
+
+void bluetooth_iter_parse_properties(DBusMessageIter *array,
+                                               const char *property, ...);
diff --git a/plugins/hfp_hf_bluez5.c b/plugins/hfp_hf_bluez5.c
index e024838..636b1b3 100644
--- a/plugins/hfp_hf_bluez5.c
+++ b/plugins/hfp_hf_bluez5.c
@@ -35,6 +35,7 @@
 #include <ofono/log.h>
 
 #include "bluez5.h"
+#include "media.h"
 
 #ifndef DBUS_TYPE_UNIX_FD
 #define DBUS_TYPE_UNIX_FD -1
@@ -42,6 +43,106 @@
 
 #define HFP_EXT_PROFILE_PATH   "/bluetooth/profile/hfp_hf"
 
+static void parse_guint16(DBusMessageIter *iter, gpointer user_data)
+{
+       guint16 *value = user_data;
+
+       if (dbus_message_iter_get_arg_type(iter) !=  DBUS_TYPE_UINT16)
+               return;
+
+       dbus_message_iter_get_basic(iter, 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 parse_byte(DBusMessageIter *iter, gpointer user_data)
+{
+       guint8 *value = user_data;
+
+       if (dbus_message_iter_get_arg_type(iter) !=  DBUS_TYPE_BYTE)
+               return;
+
+       dbus_message_iter_get_basic(iter, value);
+}
+
+static void parse_byte_array(DBusMessageIter *iter, gpointer user_data)
+{
+       DBusMessageIter array;
+       GArray **garray = user_data;
+       guint8 *data = NULL;
+       int n = 0;
+
+       if (dbus_message_iter_get_arg_type(iter) !=  DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(iter, &array);
+       dbus_message_iter_get_fixed_array(&array, &data, &n);
+       if (n == 0)
+               return;
+
+       *garray = g_array_sized_new(TRUE, TRUE, sizeof(guint8), n);
+       *garray = g_array_append_vals(*garray, (gconstpointer) data, n);
+}
+
+static void parse_media_endpoints(DBusMessageIter *array, gpointer user_data)
+{
+       const char *path, *owner;
+       GSList **endpoints = user_data;
+       GArray *capabilities = NULL;
+       struct media_endpoint *endpoint;
+       guint8 codec;
+       DBusMessageIter dict, variant, entry;
+
+       if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(array, &dict);
+
+       while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+               path = NULL;
+               codec = 0x00;
+               capabilities = NULL;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+                       return;
+
+               dbus_message_iter_get_basic(&entry, &owner);
+
+               dbus_message_iter_next(&entry);
+
+               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+                       return;
+
+               dbus_message_iter_recurse(&entry, &variant);
+
+               bluetooth_iter_parse_properties(&variant,
+                               "Path", parse_string, &path,
+                               "Codec", parse_byte, &codec,
+                               "Capabilities", parse_byte_array, &capabilities,
+                               NULL);
+
+               dbus_message_iter_next(&dict);
+
+               endpoint = media_endpoint_new(owner, path, codec, capabilities);
+               if (capabilities)
+                       g_array_unref(capabilities);
+
+               *endpoints = g_slist_append(*endpoints, endpoint);
+
+               DBG("Media Endpoint %s %s codec: 0x%02X", owner, path, codec);
+       }
+}
+
 static int hfp_probe(struct ofono_modem *modem)
 {
        DBG("modem: %p", modem);
@@ -93,11 +194,48 @@ static struct ofono_modem_driver hfp_driver = {
 static DBusMessage *profile_new_connection(DBusConnection *conn,
                                        DBusMessage *msg, void *user_data)
 {
+       DBusMessageIter entry;
+       const char *device;
+       GSList *endpoints = NULL;
+       guint16 version, features;
+       int fd;
+
        DBG("Profile handler NewConnection");
 
-       return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
-                                       ".NotImplemented",
-                                       "Implementation not provided");
+       if (dbus_message_iter_init(msg, &entry) == FALSE)
+               goto error;
+
+       if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_OBJECT_PATH)
+               goto error;
+
+       dbus_message_iter_get_basic(&entry, &device);
+       dbus_message_iter_next(&entry);
+       if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_UNIX_FD)
+               goto error;
+
+       dbus_message_iter_get_basic(&entry, &fd);
+       if (fd < 0)
+               goto error;
+
+       dbus_message_iter_next(&entry);
+
+       bluetooth_iter_parse_properties(&entry,
+                       "Version", parse_guint16, &version,
+                       "Features", parse_guint16, &features,
+                       "MediaEndpoints", parse_media_endpoints, &endpoints,
+                       NULL);
+
+       DBG("%s version: 0x%04x features: 0x%04x", device, version, features);
+
+       if (endpoints == NULL) {
+               ofono_error("Media Endpoint missing");
+               goto error;
+       }
+       return NULL;
+
+error:
+       return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE ".Rejected",
+                                       "Invalid arguments in method call");
 }
 
 static DBusMessage *profile_release(DBusConnection *conn,
diff --git a/plugins/media.c b/plugins/media.c
new file mode 100644
index 0000000..b4f0650
--- /dev/null
+++ b/plugins/media.c
@@ -0,0 +1,63 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2013  Intel Corporation. All rights reserved.
+ *
+ *  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 <glib.h>
+
+#include "media.h"
+
+struct media_endpoint {
+       char *owner;
+       char *path;
+       guint8 codec;
+       GArray *capabilities;
+};
+
+struct media_endpoint *media_endpoint_new(const char *owner,
+                                       const char *path,
+                                       guint8 codec,
+                                       GArray *capabilities)
+{
+       struct media_endpoint *endpoint;
+
+       endpoint = g_new0(struct media_endpoint, 1);
+       endpoint->owner = g_strdup(owner);
+       endpoint->path = g_strdup(path);
+       endpoint->codec = codec;
+       if (capabilities)
+               endpoint->capabilities = g_array_ref(capabilities);
+
+       return endpoint;
+}
+
+void media_endpoint_free(gpointer data)
+{
+       struct media_endpoint *endpoint = data;
+
+       g_free(endpoint->owner);
+       g_free(endpoint->path);
+       if (endpoint->capabilities)
+               g_array_unref(endpoint->capabilities);
+       g_free(endpoint);
+}
diff --git a/plugins/media.h b/plugins/media.h
new file mode 100644
index 0000000..0df107f
--- /dev/null
+++ b/plugins/media.h
@@ -0,0 +1,29 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2013  Intel Corporation. All rights reserved.
+ *
+ *  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
+ *
+ */
+
+struct media_endpoint;
+
+struct media_endpoint *media_endpoint_new(const char *owner,
+                                       const char *path,
+                                       guint8 codec,
+                                       GArray *capabilities);
+
+void media_endpoint_free(gpointer data);
-- 
1.7.11.7

_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono

Reply via email to