client: Implement basic interface of ADV monitor in bluetoothctl
authorHoward Chung <howardchung@google.com>
Wed, 16 Sep 2020 07:16:49 +0000 (15:16 +0800)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 11 Mar 2022 13:38:32 +0000 (19:08 +0530)
This patch implements some basic functions for ADV monitor in
bluetoothctl

[bluetooth]# show
...
Advertisement Monitor Features:
SupportedMonitorTypes: or_patterns

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
Makefile.tools
client/adv_monitor.c [new file with mode: 0644]
client/adv_monitor.h [new file with mode: 0644]
client/main.c

index f717c50..c5db037 100755 (executable)
@@ -7,6 +7,8 @@ client_bluetoothctl_SOURCES = client/main.c \
                                        client/agent.h client/agent.c \
                                        client/advertising.h \
                                        client/advertising.c \
+                                       client/adv_monitor.h \
+                                       client/adv_monitor.c \
                                        client/gatt.h client/gatt.c \
                                        monitor/uuid.h monitor/uuid.c
 client_bluetoothctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
diff --git a/client/adv_monitor.c b/client/adv_monitor.c
new file mode 100644 (file)
index 0000000..dda0eaf
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2020 Google LLC
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "gdbus/gdbus.h"
+#include "src/shared/util.h"
+#include "src/shared/shell.h"
+#include "adv_monitor.h"
+
+#define ADV_MONITOR_APP_PATH   "/org/bluez/adv_monitor_app"
+#define ADV_MONITOR_INTERFACE  "org.bluez.AdvertisementMonitor1"
+
+static struct adv_monitor_manager {
+       GSList *supported_types;
+       GSList *supported_features;
+       GDBusProxy *proxy;
+       gboolean app_registered;
+} manager = { NULL, NULL, NULL, FALSE };
+
+static void set_supported_list(GSList **list, DBusMessageIter *iter)
+{
+       char *str;
+       DBusMessageIter subiter;
+
+       dbus_message_iter_recurse(iter, &subiter);
+       while (dbus_message_iter_get_arg_type(&subiter) ==
+                                               DBUS_TYPE_STRING) {
+               dbus_message_iter_get_basic(&subiter, &str);
+               *list = g_slist_append(*list, str);
+               dbus_message_iter_next(&subiter);
+       }
+}
+
+void adv_monitor_add_manager(DBusConnection *conn, GDBusProxy *proxy)
+{
+       DBusMessageIter iter;
+
+       if (manager.proxy != NULL || manager.supported_types != NULL ||
+                                       manager.supported_features != NULL) {
+               bt_shell_printf("advertisement monitor manager already "
+                               "added\n");
+               return;
+       }
+
+       manager.proxy = proxy;
+
+       if (g_dbus_proxy_get_property(proxy, "SupportedMonitorTypes", &iter))
+               set_supported_list(&(manager.supported_types), &iter);
+
+       if (g_dbus_proxy_get_property(proxy, "SupportedFeatures", &iter))
+               set_supported_list(&(manager.supported_features), &iter);
+
+}
+
+void adv_monitor_remove_manager(DBusConnection *conn)
+{
+       if (manager.supported_types != NULL)
+               g_slist_free(g_steal_pointer(&(manager.supported_types)));
+       if (manager.supported_features != NULL)
+               g_slist_free(g_steal_pointer(&(manager.supported_features)));
+       manager.proxy = NULL;
+       manager.app_registered = FALSE;
+}
+
+static void register_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *path = ADV_MONITOR_APP_PATH;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+static void register_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (!dbus_set_error_from_message(&error, message)) {
+               bt_shell_printf("AdvertisementMonitor path registered\n");
+               return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+       }
+
+       bt_shell_printf("Failed to register path: %s\n", error.name);
+       dbus_error_free(&error);
+       return bt_shell_noninteractive_quit(EXIT_FAILURE);
+}
+
+static void unregister_setup(DBusMessageIter *iter, void *user_data)
+{
+       const char *path = ADV_MONITOR_APP_PATH;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+static void unregister_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (!dbus_set_error_from_message(&error, message)) {
+               bt_shell_printf("AdvertisementMonitor path unregistered\n");
+               return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+       }
+
+       bt_shell_printf("Failed to unregister Advertisement Monitor:"
+                       " %s\n", error.name);
+       dbus_error_free(&error);
+       return bt_shell_noninteractive_quit(EXIT_FAILURE);
+}
+
+void adv_monitor_register_app(DBusConnection *conn)
+{
+       if (manager.app_registered) {
+               bt_shell_printf("Advertisement Monitor already registered\n");
+               return bt_shell_noninteractive_quit(EXIT_FAILURE);
+       } else if (manager.supported_types == NULL ||
+               !g_dbus_proxy_method_call(manager.proxy, "RegisterMonitor",
+                                       register_setup, register_reply,
+                                       NULL, NULL)) {
+               bt_shell_printf("Failed to register Advertisement Monitor\n");
+               return bt_shell_noninteractive_quit(EXIT_FAILURE);
+       }
+       manager.app_registered = TRUE;
+}
+
+void adv_monitor_unregister_app(DBusConnection *conn)
+{
+       if (!manager.app_registered) {
+               bt_shell_printf("Advertisement Monitor not registered\n");
+               return bt_shell_noninteractive_quit(EXIT_FAILURE);
+       } else if (!g_dbus_proxy_method_call(manager.proxy, "UnregisterMonitor",
+                                       unregister_setup, unregister_reply,
+                                       NULL, NULL)) {
+               bt_shell_printf("Failed to unregister Advertisement Monitor\n");
+               return bt_shell_noninteractive_quit(EXIT_FAILURE);
+       }
+       manager.app_registered = FALSE;
+}
diff --git a/client/adv_monitor.h b/client/adv_monitor.h
new file mode 100644 (file)
index 0000000..77b0b62
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2020 Google LLC
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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.
+ *
+ */
+
+void adv_monitor_add_manager(DBusConnection *conn, GDBusProxy *proxy);
+void adv_monitor_remove_manager(DBusConnection *conn);
+void adv_monitor_register_app(DBusConnection *conn);
+void adv_monitor_unregister_app(DBusConnection *conn);
index 86f16dc..79910f4 100644 (file)
@@ -40,6 +40,7 @@
 #include "agent.h"
 #include "gatt.h"
 #include "advertising.h"
+#include "adv_monitor.h"
 
 /* String display constants */
 #define COLORED_NEW    COLOR_GREEN "NEW" COLOR_OFF
@@ -57,6 +58,7 @@ static char *auto_register_agent = NULL;
 struct adapter {
        GDBusProxy *proxy;
        GDBusProxy *ad_proxy;
+       GDBusProxy *adv_monitor_proxy;
        GList *devices;
 };
 
@@ -527,6 +529,19 @@ static void ad_manager_added(GDBusProxy *proxy)
        adapter->ad_proxy = proxy;
 }
 
+static void admon_manager_added(GDBusProxy *proxy)
+{
+       struct adapter *adapter;
+
+       adapter = find_ctrl(ctrl_list, g_dbus_proxy_get_path(proxy));
+       if (!adapter)
+               adapter = adapter_new(proxy);
+
+       adapter->adv_monitor_proxy = proxy;
+       adv_monitor_add_manager(dbus_conn, proxy);
+       adv_monitor_register_app(dbus_conn);
+}
+
 static void proxy_added(GDBusProxy *proxy, void *user_data)
 {
        const char *interface;
@@ -559,6 +574,9 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
                ad_manager_added(proxy);
        } else if (!strcmp(interface, "org.bluez.Battery1")) {
                battery_added(proxy);
+       } else if (!strcmp(interface,
+                               "org.bluez.AdvertisementMonitorManager1")) {
+               admon_manager_added(proxy);
        }
 }
 
@@ -652,6 +670,9 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
                ad_unregister(dbus_conn, NULL);
        } else if (!strcmp(interface, "org.bluez.Battery1")) {
                battery_removed(proxy);
+       } else if (!strcmp(interface,
+                       "org.bluez.AdvertisementMonitorManager1")) {
+               adv_monitor_remove_manager(dbus_conn);
        }
 }
 
@@ -938,6 +959,13 @@ static void cmd_show(int argc, char *argv[])
                print_property(adapter->ad_proxy, "SupportedSecondaryChannels");
        }
 
+       if (adapter->adv_monitor_proxy) {
+               bt_shell_printf("Advertisement Monitor Features:\n");
+               print_property(adapter->adv_monitor_proxy,
+                                               "SupportedMonitorTypes");
+               print_property(adapter->adv_monitor_proxy, "SupportedFeatures");
+       }
+
        return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }