@@ -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;
@@ -201,6 +359,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);
@@ -325,6 +484,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;
@@ -360,6 +529,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");
@@ -434,6 +604,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);
@@ -468,7 +648,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;
}
@@ -479,8 +659,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);
}