client: Expose ADV monitor objects
authorHoward Chung <howardchung@google.com>
Wed, 16 Sep 2020 07:16:51 +0000 (15:16 +0800)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 11 Mar 2022 13:38:32 +0000 (19:08 +0530)
This adds logic to expose user-defined advertisement monitor to dbus and
also implements methods for exposed objects.

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
client/adv_monitor.c

index d4914b7..22bb3c6 100644 (file)
@@ -53,6 +53,7 @@ struct pattern {
 
 struct adv_monitor {
        uint8_t idx;
+       char *path;
        char *type;
        struct rssi_setting *rssi;
        GSList *patterns;
@@ -68,6 +69,163 @@ static struct adv_monitor_manager {
 static uint8_t adv_mon_idx;
 static GSList *adv_mons;
 
+static void remove_adv_monitor(void *data, void *user_data);
+
+static DBusMessage *release_adv_monitor(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct adv_monitor *adv_monitor = user_data;
+
+       bt_shell_printf("Advertisement monitor %d released\n",
+                                                       adv_monitor->idx);
+       remove_adv_monitor(adv_monitor, conn);
+
+       return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *activate_adv_monitor(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct adv_monitor *adv_monitor = user_data;
+
+       bt_shell_printf("Advertisement monitor %d activated\n",
+                                                       adv_monitor->idx);
+       return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *device_found_adv_monitor(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct adv_monitor *adv_monitor = user_data;
+       const char *device;
+
+       dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device,
+                                                       DBUS_TYPE_INVALID);
+       bt_shell_printf("Advertisement monitor %d found device %s\n",
+                                               adv_monitor->idx, device);
+       return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *device_lost_adv_monitor(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct adv_monitor *adv_monitor = user_data;
+       const char *device;
+
+       dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device,
+                                                       DBUS_TYPE_INVALID);
+       bt_shell_printf("Advertisement monitor %d lost device %s\n",
+                                               adv_monitor->idx, device);
+       return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable adv_monitor_methods[] = {
+       { GDBUS_ASYNC_METHOD("Release", NULL, NULL, release_adv_monitor) },
+       { GDBUS_ASYNC_METHOD("Activate", NULL, NULL, activate_adv_monitor) },
+       { GDBUS_ASYNC_METHOD("DeviceFound", GDBUS_ARGS({ "device", "o" }),
+                       NULL, device_found_adv_monitor) },
+       { GDBUS_ASYNC_METHOD("DeviceLost", GDBUS_ARGS({ "device", "o" }),
+                       NULL, device_lost_adv_monitor) },
+       { }
+};
+
+
+static gboolean get_type(const GDBusPropertyTable *property,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct adv_monitor *adv_monitor = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+                                                       &adv_monitor->type);
+       return TRUE;
+}
+
+static gboolean get_rssi(const GDBusPropertyTable *property,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct adv_monitor *adv_monitor = user_data;
+       struct rssi_setting *rssi = adv_monitor->rssi;
+       DBusMessageIter data_iter;
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
+                                                       NULL, &data_iter);
+       dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_INT16,
+                                                       &rssi->high_threshold);
+       dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_UINT16,
+                                                       &rssi->high_timer);
+       dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_INT16,
+                                                       &rssi->low_threshold);
+       dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_UINT16,
+                                                       &rssi->low_timer);
+       dbus_message_iter_close_container(iter, &data_iter);
+       return TRUE;
+}
+
+static gboolean rssi_exists(const GDBusPropertyTable *property, void *data)
+{
+       struct adv_monitor *adv_monitor = data;
+
+       return adv_monitor->rssi != NULL;
+}
+
+static void append_pattern_content_to_dbus(DBusMessageIter *iter,
+                                                       struct pattern *pattern)
+{
+       DBusMessageIter data_iter;
+       int idx;
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+                                       DBUS_TYPE_BYTE_AS_STRING, &data_iter);
+       for (idx = 0; idx < pattern->content_len; idx++)
+               dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_BYTE,
+                                                       &pattern->content[idx]);
+       dbus_message_iter_close_container(iter, &data_iter);
+}
+
+static void append_pattern_to_dbus(void *data, void *user_data)
+{
+       struct pattern *pattern = data;
+       DBusMessageIter *array_iter = user_data;
+       DBusMessageIter data_iter;
+
+       dbus_message_iter_open_container(array_iter, DBUS_TYPE_STRUCT,
+                                                       NULL, &data_iter);
+       dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_BYTE,
+                                                       &pattern->start_pos);
+       dbus_message_iter_append_basic(&data_iter, DBUS_TYPE_BYTE,
+                                                       &pattern->ad_data_type);
+       append_pattern_content_to_dbus(&data_iter, pattern);
+       dbus_message_iter_close_container(array_iter, &data_iter);
+}
+
+static gboolean get_patterns(const GDBusPropertyTable *property,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct adv_monitor *adv_monitor = user_data;
+       DBusMessageIter array_iter;
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(yyay)",
+                                                               &array_iter);
+       g_slist_foreach(adv_monitor->patterns, append_pattern_to_dbus,
+                                                               &array_iter);
+       dbus_message_iter_close_container(iter, &array_iter);
+       return TRUE;
+}
+
+static gboolean pattern_exists(const GDBusPropertyTable *property, void *data)
+{
+       struct adv_monitor *adv_monitor = data;
+
+       return adv_monitor->patterns != NULL;
+}
+
+static const GDBusPropertyTable adv_monitor_props[] = {
+       { "Type", "s", get_type },
+       { "RSSIThresholdsAndTimers", "(nqnq)", get_rssi, NULL, rssi_exists },
+       { "Patterns", "a(yyay)", get_patterns, NULL, pattern_exists },
+       { }
+};
+
 static void set_supported_list(GSList **list, DBusMessageIter *iter)
 {
        char *str;
@@ -200,6 +358,7 @@ static void free_adv_monitor(void *user_data)
 {
        struct adv_monitor *adv_monitor = user_data;
 
+       g_free(adv_monitor->path);
        g_free(adv_monitor->type);
        g_free(adv_monitor->rssi);
        g_slist_free_full(adv_monitor->patterns, free_pattern);
@@ -324,6 +483,16 @@ static GSList *parse_patterns(char *pattern_list[], int num)
        return patterns;
 }
 
+static void remove_adv_monitor(void *data, void *user_data)
+{
+       struct adv_monitor *adv_monitor = data;
+       DBusConnection *conn = user_data;
+
+       adv_mons = g_slist_remove(adv_mons, adv_monitor);
+       g_dbus_unregister_interface(conn, adv_monitor->path,
+                                                       ADV_MONITOR_INTERFACE);
+}
+
 static gint cmp_adv_monitor_with_idx(gconstpointer a, gconstpointer b)
 {
        const struct adv_monitor *adv_monitor = a;
@@ -359,6 +528,7 @@ static void print_adv_monitor(struct adv_monitor *adv_monitor)
        GSList *l;
 
        bt_shell_printf("Advertisement Monitor %d\n", adv_monitor->idx);
+       bt_shell_printf("\tpath: %s\n", adv_monitor->path);
        bt_shell_printf("\ttype: %s\n", adv_monitor->type);
        if (adv_monitor->rssi) {
                bt_shell_printf("\trssi:\n");
@@ -433,6 +603,16 @@ void adv_monitor_add_monitor(DBusConnection *conn, char *type,
        adv_monitor->type = g_strdup(type);
        adv_monitor->rssi = rssi;
        adv_monitor->patterns = patterns;
+       adv_monitor->path = g_strdup_printf("%s/%hhu", ADV_MONITOR_APP_PATH,
+                                                               adv_mon_idx);
+       if (g_dbus_register_interface(conn, adv_monitor->path,
+                                       ADV_MONITOR_INTERFACE,
+                                       adv_monitor_methods, NULL,
+                                       adv_monitor_props, adv_monitor,
+                                       free_adv_monitor) == FALSE) {
+               bt_shell_printf("Failed to register advertisement monitor\n");
+               return bt_shell_noninteractive_quit(EXIT_FAILURE);
+       }
 
        adv_mons = g_slist_append(adv_mons, adv_monitor);
        bt_shell_printf("Advertisement Monitor %d added\n", adv_monitor->idx);
@@ -467,7 +647,7 @@ void adv_monitor_remove_monitor(DBusConnection *conn, int monitor_idx)
        struct adv_monitor *adv_monitor;
 
        if (monitor_idx < 0) {
-               g_slist_free_full(g_steal_pointer(&adv_mons), free_adv_monitor);
+               g_slist_foreach(adv_mons, remove_adv_monitor, conn);
                return;
        }
 
@@ -478,8 +658,7 @@ void adv_monitor_remove_monitor(DBusConnection *conn, int monitor_idx)
                return;
        }
 
-       adv_mons = g_slist_remove(adv_mons, adv_monitor);
-       free_adv_monitor(adv_monitor);
+       remove_adv_monitor(adv_monitor, conn);
        bt_shell_printf("Monitor %d deleted\n", monitor_idx);
 }