@@ -28,11 +28,16 @@
#define ADV_MONITOR_APP_PATH "/org/bluez/adv_monitor_app"
#define ADV_MONITOR_INTERFACE "org.bluez.AdvertisementMonitor1"
+#define RSSI_UNSET_THRESHOLD 127
+#define RSSI_UNSET_TIMEOUT 0
+#define RSSI_UNSET_SAMPLING_PERIOD 256
+
struct rssi_setting {
int16_t high_threshold;
- uint16_t high_timer;
+ uint16_t high_timeout;
int16_t low_threshold;
- uint16_t low_timer;
+ uint16_t low_timeout;
+ uint16_t sampling_period;
};
struct pattern {
@@ -59,6 +64,7 @@ static struct adv_monitor_manager {
static uint8_t adv_mon_idx;
static GSList *adv_mons;
+static struct rssi_setting *current_rssi;
static void remove_adv_monitor(void *data, void *user_data);
@@ -131,32 +137,105 @@ static gboolean get_type(const GDBusPropertyTable *property,
return TRUE;
}
-static gboolean get_rssi(const GDBusPropertyTable *property,
+static gboolean get_low_threshold(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,
+ dbus_message_iter_append_basic(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)
+static gboolean get_high_threshold(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct adv_monitor *adv_monitor = user_data;
+ struct rssi_setting *rssi = adv_monitor->rssi;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16,
+ &rssi->high_threshold);
+ return TRUE;
+}
+
+static gboolean get_low_timeout(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct adv_monitor *adv_monitor = user_data;
+ struct rssi_setting *rssi = adv_monitor->rssi;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+ &rssi->low_timeout);
+ return TRUE;
+}
+
+static gboolean get_high_timeout(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct adv_monitor *adv_monitor = user_data;
+ struct rssi_setting *rssi = adv_monitor->rssi;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+ &rssi->high_timeout);
+ return TRUE;
+}
+
+static gboolean get_sampling_period(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct adv_monitor *adv_monitor = user_data;
+ struct rssi_setting *rssi = adv_monitor->rssi;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+ &rssi->sampling_period);
+ return TRUE;
+}
+
+static gboolean low_threshold_exists(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct adv_monitor *adv_monitor = data;
+
+ return adv_monitor->rssi != NULL &&
+ adv_monitor->rssi->low_threshold != RSSI_UNSET_THRESHOLD;
+}
+
+static gboolean high_threshold_exists(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct adv_monitor *adv_monitor = data;
+
+ return adv_monitor->rssi != NULL &&
+ adv_monitor->rssi->high_threshold != RSSI_UNSET_THRESHOLD;
+}
+
+static gboolean low_timeout_exists(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct adv_monitor *adv_monitor = data;
+
+ return adv_monitor->rssi != NULL &&
+ adv_monitor->rssi->low_timeout != RSSI_UNSET_TIMEOUT;
+}
+
+static gboolean high_timeout_exists(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct adv_monitor *adv_monitor = data;
+
+ return adv_monitor->rssi != NULL &&
+ adv_monitor->rssi->high_timeout != RSSI_UNSET_TIMEOUT;
+}
+
+static gboolean sampling_period_exists(const GDBusPropertyTable *property,
+ void *data)
{
struct adv_monitor *adv_monitor = data;
- return adv_monitor->rssi != NULL;
+ return adv_monitor->rssi != NULL &&
+ adv_monitor->rssi->sampling_period !=
+ RSSI_UNSET_SAMPLING_PERIOD;
}
static void append_pattern_content_to_dbus(DBusMessageIter *iter,
@@ -212,7 +291,14 @@ static gboolean pattern_exists(const GDBusPropertyTable *property, void *data)
static const GDBusPropertyTable adv_monitor_props[] = {
{ "Type", "s", get_type },
- { "RSSIThresholdsAndTimers", "(nqnq)", get_rssi, NULL, rssi_exists },
+ { "RSSILowThreshold", "n", get_low_threshold, NULL,
+ low_threshold_exists },
+ { "RSSIHighThreshold", "n", get_high_threshold, NULL,
+ high_threshold_exists },
+ { "RSSILowTimeout", "q", get_low_timeout, NULL, low_timeout_exists },
+ { "RSSIHighTimeout", "q", get_high_timeout, NULL, high_timeout_exists },
+ { "RSSISamplingPeriod", "q", get_sampling_period, NULL,
+ sampling_period_exists },
{ "Patterns", "a(yyay)", get_patterns, NULL, pattern_exists },
{ }
};
@@ -266,6 +352,9 @@ void adv_monitor_remove_manager(DBusConnection *conn)
manager.proxy = NULL;
manager.app_registered = FALSE;
+
+ g_free(current_rssi);
+ current_rssi = NULL;
}
static void register_setup(DBusMessageIter *iter, void *user_data)
@@ -376,58 +465,6 @@ static uint8_t str2bytearray(char *str, uint8_t *arr)
return arr_len;
}
-static void parse_rssi_value_pair(char *value_pair, int *low, int *high)
-{
- char *val1, *val2;
- bool flag = value_pair[0] == ',';
-
- val1 = strtok(value_pair, ",");
-
- if (!val1)
- return;
-
- val2 = strtok(NULL, ",");
-
- if (!val2) {
- if (!flag)
- *low = atoi(val1);
- else
- *high = atoi(val1);
- } else {
- *low = atoi(val1);
- *high = atoi(val2);
- }
-}
-
-static struct rssi_setting *parse_rssi(char *range, char *timeout)
-{
- struct rssi_setting *rssi;
- int high_threshold, low_threshold, high_timer, low_timer;
-
- high_threshold = RSSI_DEFAULT_HIGH_THRESHOLD;
- low_threshold = RSSI_DEFAULT_LOW_THRESHOLD;
- high_timer = RSSI_DEFAULT_HIGH_TIMEOUT;
- low_timer = RSSI_DEFAULT_LOW_TIMEOUT;
-
- parse_rssi_value_pair(range, &low_threshold, &high_threshold);
- parse_rssi_value_pair(timeout, &low_timer, &high_timer);
-
- rssi = g_malloc0(sizeof(struct rssi_setting));
-
- if (!rssi) {
- bt_shell_printf("Failed to allocate rssi_setting");
- bt_shell_noninteractive_quit(EXIT_FAILURE);
- return NULL;
- }
-
- rssi->high_threshold = high_threshold;
- rssi->high_timer = high_timer;
- rssi->low_threshold = low_threshold;
- rssi->low_timer = low_timer;
-
- return rssi;
-}
-
static struct pattern *parse_pattern(char *parameter_list[])
{
struct pattern *pat;
@@ -435,7 +472,7 @@ static struct pattern *parse_pattern(char *parameter_list[])
pat = g_malloc0(sizeof(struct pattern));
if (!pat) {
- bt_shell_printf("Failed to allocate pattern");
+ bt_shell_printf("Failed to allocate pattern\n");
bt_shell_noninteractive_quit(EXIT_FAILURE);
return NULL;
}
@@ -531,12 +568,14 @@ static void print_adv_monitor(struct adv_monitor *adv_monitor)
bt_shell_printf("\trssi:\n");
bt_shell_printf("\t\thigh threshold: %hd\n",
adv_monitor->rssi->high_threshold);
- bt_shell_printf("\t\thigh threshold timer: %hu\n",
- adv_monitor->rssi->high_timer);
+ bt_shell_printf("\t\thigh threshold timeout: %hu\n",
+ adv_monitor->rssi->high_timeout);
bt_shell_printf("\t\tlow threshold: %hd\n",
adv_monitor->rssi->low_threshold);
- bt_shell_printf("\t\tlow threshold timer: %hu\n",
- adv_monitor->rssi->low_timer);
+ bt_shell_printf("\t\tlow threshold timeout: %hu\n",
+ adv_monitor->rssi->low_timeout);
+ bt_shell_printf("\t\tsampling period: %hu\n",
+ adv_monitor->rssi->sampling_period);
}
if (adv_monitor->patterns) {
@@ -556,11 +595,62 @@ static void print_adv_monitor(struct adv_monitor *adv_monitor)
}
}
+static struct rssi_setting *get_current_rssi(void)
+{
+ if (current_rssi)
+ return current_rssi;
+
+ current_rssi = g_malloc0(sizeof(struct rssi_setting));
+
+ if (!current_rssi)
+ bt_shell_printf("Failed to allocate rssi setting");
+
+ current_rssi->low_threshold = RSSI_UNSET_THRESHOLD;
+ current_rssi->high_threshold = RSSI_UNSET_THRESHOLD;
+ current_rssi->low_timeout = RSSI_UNSET_TIMEOUT;
+ current_rssi->high_timeout = RSSI_UNSET_TIMEOUT;
+ current_rssi->sampling_period = RSSI_UNSET_SAMPLING_PERIOD;
+
+ return current_rssi;
+}
+
+void adv_monitor_set_rssi_threshold(int16_t low_threshold,
+ int16_t high_threshold)
+{
+ struct rssi_setting *rssi = get_current_rssi();
+
+ if (!rssi)
+ return;
+
+ rssi->low_threshold = low_threshold;
+ rssi->high_threshold = high_threshold;
+}
+
+void adv_monitor_set_rssi_timeout(uint16_t low_timeout, uint16_t high_timeout)
+{
+ struct rssi_setting *rssi = get_current_rssi();
+
+ if (!rssi)
+ return;
+
+ rssi->low_timeout = low_timeout;
+ rssi->high_timeout = high_timeout;
+}
+
+void adv_monitor_set_rssi_sampling_period(uint16_t sampling)
+{
+ struct rssi_setting *rssi = get_current_rssi();
+
+ if (!rssi)
+ return;
+
+ rssi->sampling_period = sampling;
+}
+
void adv_monitor_add_monitor(DBusConnection *conn, char *type,
- gboolean rssi_enabled, int argc, char *argv[])
+ int argc, char *argv[])
{
struct adv_monitor *adv_monitor;
- struct rssi_setting *rssi;
GSList *patterns = NULL;
if (g_slist_length(adv_mons) >= UINT8_MAX) {
@@ -572,17 +662,6 @@ void adv_monitor_add_monitor(DBusConnection *conn, char *type,
while (find_adv_monitor_with_idx(adv_mon_idx))
adv_mon_idx += 1;
- if (rssi_enabled == FALSE)
- rssi = NULL;
- else {
- rssi = parse_rssi(argv[1], argv[2]);
- if (rssi == NULL)
- return;
-
- argv += 2;
- argc -= 2;
- }
-
patterns = parse_patterns(argv+1, argc-1);
if (patterns == NULL) {
bt_shell_printf("pattern-list malformed\n");
@@ -598,16 +677,19 @@ void adv_monitor_add_monitor(DBusConnection *conn, char *type,
adv_monitor->idx = adv_mon_idx;
adv_monitor->type = g_strdup(type);
- adv_monitor->rssi = rssi;
+ adv_monitor->rssi = current_rssi;
adv_monitor->patterns = patterns;
adv_monitor->path = g_strdup_printf("%s/%hhu", ADV_MONITOR_APP_PATH,
adv_mon_idx);
+ current_rssi = NULL;
+
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");
+ free_adv_monitor(adv_monitor);
return bt_shell_noninteractive_quit(EXIT_FAILURE);
}
@@ -8,17 +8,16 @@
*
*/
-#define RSSI_DEFAULT_HIGH_THRESHOLD -50
-#define RSSI_DEFAULT_LOW_THRESHOLD -70
-#define RSSI_DEFAULT_HIGH_TIMEOUT 10
-#define RSSI_DEFAULT_LOW_TIMEOUT 5
-
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);
+void adv_monitor_set_rssi_threshold(int16_t low_threshold,
+ int16_t high_threshold);
+void adv_monitor_set_rssi_timeout(uint16_t low_timeout, uint16_t high_timeout);
+void adv_monitor_set_rssi_sampling_period(uint16_t sampling);
void adv_monitor_add_monitor(DBusConnection *conn, char *type,
- gboolean rssi_enabled, int argc, char *argv[]);
+ int argc, char *argv[]);
void adv_monitor_print_monitor(DBusConnection *conn, int monitor_idx);
void adv_monitor_remove_monitor(DBusConnection *conn, int monitor_idx);
void adv_monitor_get_supported_info(void);
@@ -2707,30 +2707,6 @@ static void cmd_ad_clear(int argc, char *argv[])
return bt_shell_noninteractive_quit(EXIT_FAILURE);
}
-static void print_add_or_pattern_with_rssi_usage(void)
-{
- bt_shell_printf("rssi-range format:\n"
- "\t<low-rssi>,<high-rssi>\n"
- "\tBoth parameters can be skipped, in that case the\n"
- "\tparamter will be set to its pre-defined value\n");
- bt_shell_printf("\tPre-defined low-rssi,high-rssi: %d,%d\n",
- RSSI_DEFAULT_LOW_THRESHOLD,
- RSSI_DEFAULT_HIGH_THRESHOLD);
- bt_shell_printf("timeout format:\n"
- "\t<low-rssi>,<high-rssi>\n"
- "\tBoth parameters can be skipped, in that case the\n"
- "\tparamter will be set to its pre-defined value\n");
- bt_shell_printf("\tPre-defined low-timeout,high-timeout: %d,%d\n",
- RSSI_DEFAULT_LOW_TIMEOUT,
- RSSI_DEFAULT_HIGH_TIMEOUT);
- bt_shell_printf("pattern format:\n"
- "\t<start_position> <ad_data_type> <content_of_pattern>\n");
- bt_shell_printf("e.g.\n"
- "\tadd-or-pattern-rssi -10, ,10 1 2 01ab55\n");
- bt_shell_printf("or\n"
- "\tadd-or-pattern-rssi -50,-30 , 1 2 01ab55 3 4 23cd66\n");
-}
-
static void print_add_or_pattern_usage(void)
{
bt_shell_printf("pattern format:\n"
@@ -2743,20 +2719,38 @@ static void cmd_adv_monitor_print_usage(int argc, char *argv[])
{
if (strcmp(argv[1], "add-or-pattern") == 0)
print_add_or_pattern_usage();
- else if (strcmp(argv[1], "add-or-pattern-rssi") == 0)
- print_add_or_pattern_with_rssi_usage();
else
bt_shell_printf("Invalid argument %s", argv[1]);
}
-static void cmd_adv_monitor_add_or_monitor_with_rssi(int argc, char *argv[])
+static void cmd_adv_monitor_set_rssi_threshold(int argc, char *argv[])
+{
+ int low_threshold, high_threshold;
+
+ low_threshold = atoi(argv[1]);
+ high_threshold = atoi(argv[2]);
+ adv_monitor_set_rssi_threshold(low_threshold, high_threshold);
+}
+
+static void cmd_adv_monitor_set_rssi_timeout(int argc, char *argv[])
{
- adv_monitor_add_monitor(dbus_conn, "or_patterns", TRUE, argc, argv);
+ int low_timeout, high_timeout;
+
+ low_timeout = atoi(argv[1]);
+ high_timeout = atoi(argv[2]);
+ adv_monitor_set_rssi_timeout(low_timeout, high_timeout);
+}
+
+static void cmd_adv_monitor_set_rssi_sampling_period(int argc, char *argv[])
+{
+ int sampling = atoi(argv[1]);
+
+ adv_monitor_set_rssi_sampling_period(sampling);
}
static void cmd_adv_monitor_add_or_monitor(int argc, char *argv[])
{
- adv_monitor_add_monitor(dbus_conn, "or_patterns", FALSE, argc, argv);
+ adv_monitor_add_monitor(dbus_conn, "or_patterns", argc, argv);
}
static void cmd_adv_monitor_print_monitor(int argc, char *argv[])
@@ -2826,15 +2820,19 @@ static const struct bt_shell_menu advertise_monitor_menu = {
.name = "monitor",
.desc = "Advertisement Monitor Options Submenu",
.entries = {
- { "add-or-pattern-rssi", "<rssi-range=low,high> <timeout=low,high> "
- "[patterns=pattern1 pattern2 ...]",
- cmd_adv_monitor_add_or_monitor_with_rssi,
- "Add 'or pattern' type monitor with RSSI "
- "filter" },
+ { "set-rssi-threshold", "<low_threshold> <high_threshold>",
+ cmd_adv_monitor_set_rssi_threshold,
+ "Set RSSI threshold parameter" },
+ { "set-rssi-timeout", "<low_timeout> <high_timeout>",
+ cmd_adv_monitor_set_rssi_timeout,
+ "Set RSSI timeout parameter" },
+ { "set-rssi-sampling-period", "<sampling_period>",
+ cmd_adv_monitor_set_rssi_sampling_period,
+ "Set RSSI sampling period parameter" },
{ "add-or-pattern", "[patterns=pattern1 pattern2 ...]",
cmd_adv_monitor_add_or_monitor,
- "Add 'or pattern' type monitor without RSSI "
- "filter" },
+ "Register 'or pattern' type monitor with the "
+ "specified RSSI parameters" },
{ "get-pattern", "<monitor-id/all>",
cmd_adv_monitor_print_monitor,
"Get advertisement monitor" },
@@ -2845,7 +2843,7 @@ static const struct bt_shell_menu advertise_monitor_menu = {
cmd_adv_monitor_get_supported_info,
"Get advertisement manager supported "
"features and supported monitor types" },
- { "print-usage", "<add-or-pattern/add-or-pattern-rssi>",
+ { "print-usage", "<add-or-pattern>",
cmd_adv_monitor_print_usage,
"Print the command usage"},
{ } },
From: Archie Pusaka <apusaka@chromium.org> Using the new opcode MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI to monitor advertisement according to some RSSI criteria. --- Changes in v4: * split the add-or-pattern-rssi command Changes in v3: * split the struct RSSIThresholdsAndTimers client/adv_monitor.c | 258 ++++++++++++++++++++++++++++--------------- client/adv_monitor.h | 11 +- client/main.c | 72 ++++++------ 3 files changed, 210 insertions(+), 131 deletions(-)