All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jakub Pawlowski <jpawlowski@google.com>
To: linux-bluetooth@vger.kernel.org
Cc: Jakub Pawlowski <jpawlowski@google.com>
Subject: [PATCH v5 8/8] client: main: add support for SetDiscoveryFilter
Date: Wed, 25 Mar 2015 01:19:01 -0700	[thread overview]
Message-ID: <1427271541-7509-8-git-send-email-jpawlowski@google.com> (raw)
In-Reply-To: <1427271541-7509-1-git-send-email-jpawlowski@google.com>

This patch adds filtered-scan command to sample DBus client that might
be used to call SetDiscoveryFilter.
---
 client/main.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 244 insertions(+)

diff --git a/client/main.c b/client/main.c
index 7f1c903..90ae734 100644
--- a/client/main.c
+++ b/client/main.c
@@ -891,6 +891,248 @@ static void cmd_scan(const char *arg)
 	}
 }
 
+static void append_variant(DBusMessageIter *iter, int type, void *val)
+{
+	DBusMessageIter value;
+	char sig[2] = { type, '\0' };
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, &value);
+
+	dbus_message_iter_append_basic(&value, type, val);
+
+	dbus_message_iter_close_container(iter, &value);
+}
+
+static void dict_append_entry(DBusMessageIter *dict, const char *key,
+							int type, void *val)
+{
+	DBusMessageIter entry;
+
+	if (type == DBUS_TYPE_STRING) {
+		const char *str = *((const char **) val);
+
+		if (str == NULL)
+			return;
+	}
+
+	dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+							NULL, &entry);
+
+	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+	append_variant(&entry, type, val);
+
+	dbus_message_iter_close_container(dict, &entry);
+}
+
+#define	DISTANCE_VAL_INVALID	0x7FFF
+
+struct set_discovery_filter_args {
+	char *transport;
+	dbus_uint16_t rssi;
+	dbus_int16_t pathloss;
+	GList *uuids;
+};
+
+static void set_discovery_filter_setup(DBusMessageIter *iter,
+					   void *user_data)
+{
+	struct set_discovery_filter_args *args = user_data;
+	DBusMessageIter dict;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+			    DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+			    DBUS_TYPE_STRING_AS_STRING
+			    DBUS_TYPE_VARIANT_AS_STRING
+			    DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+	if (args->uuids != NULL) {
+		DBusMessageIter entry, value, arrayIter;
+		char *uuids = "UUIDs";
+		GList *list;
+
+		dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
+						 NULL, &entry);
+		/* dict key */
+		dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
+					       &uuids);
+
+		dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+						 "as", &value);
+
+		dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, "s",
+						 &arrayIter);
+
+		for (list = g_list_first(args->uuids); list;
+						      list = g_list_next(list))
+			/* list->data contains string representation of uuid */
+			dbus_message_iter_append_basic(&arrayIter,
+						       DBUS_TYPE_STRING,
+						       &list->data);
+
+		dbus_message_iter_close_container(&value, &arrayIter);
+
+		/* close vararg*/
+		dbus_message_iter_close_container(&entry, &value);
+
+		/* close entry */
+		dbus_message_iter_close_container(&dict, &entry);
+	}
+
+	if (args->pathloss != DISTANCE_VAL_INVALID)
+		dict_append_entry(&dict, "Pathloss", DBUS_TYPE_UINT16,
+				  &args->pathloss);
+
+	if (args->rssi != DISTANCE_VAL_INVALID)
+		dict_append_entry(&dict, "RSSI", DBUS_TYPE_INT16, &args->rssi);
+
+	if (args->transport != NULL)
+		dict_append_entry(&dict, "Transport", DBUS_TYPE_STRING,
+				  &args->transport);
+
+	dbus_message_iter_close_container(iter, &dict);
+}
+
+
+static void set_discovery_filter_reply(DBusMessage *message,
+				       void *user_data)
+{
+	DBusError error;
+
+	dbus_error_init(&error);
+	if (dbus_set_error_from_message(&error, message) == TRUE) {
+		rl_printf("SetDiscoveryFilter failed: %s\n", error.name);
+		dbus_error_free(&error);
+		return;
+	}
+
+	rl_printf("SetDiscoveryFilter success\n");
+}
+
+static gint filtered_scan_rssi, filtered_scan_pathloss;
+static char **filtered_scan_uuids;
+static gboolean filtered_scan_help;
+static char *filtered_scan_transport;
+
+static GOptionEntry filtered_discovery_options[] = {
+	{ "rssi", 'r', 0, G_OPTION_ARG_INT, &filtered_scan_rssi,
+				"RSSI filter" },
+	{ "pathloss", 'p', 0, G_OPTION_ARG_INT, &filtered_scan_pathloss,
+				"pathloss filter" },
+	{ "transport", 't', 0, G_OPTION_ARG_STRING, &filtered_scan_transport,
+				"transport" },
+	{ "uuids", 'u', 0, G_OPTION_ARG_STRING_ARRAY, &filtered_scan_uuids,
+				"uuid to filter by" },
+	{ "help", 'h', 0, G_OPTION_ARG_NONE, &filtered_scan_help,
+				"show help" },
+	{ NULL },
+};
+
+static bool parse_set_discovery_filter_params(const char *arg,
+					struct set_discovery_filter_args *args)
+{
+	int argc, loop;
+	GOptionContext *context;
+	GError *error = NULL;
+
+	gchar **arguments = NULL, **argv, *cmdline_arg;
+
+	/* add fake program name at beginning for g_shell_parse_argv */
+	cmdline_arg = g_strconcat("set-discovery-filter ", arg, NULL);
+	if (g_shell_parse_argv(cmdline_arg, &argc, &arguments, &error)
+								    == FALSE) {
+		if (error != NULL) {
+			g_printerr("error when parsing arguments: %s\n",
+				   error->message);
+			g_error_free(error);
+		} else
+			g_printerr("An unknown error occurred\n");
+
+		g_strfreev(arguments);
+		g_free(cmdline_arg);
+		return false;
+	}
+	g_free(cmdline_arg);
+
+	argc = g_strv_length(arguments);
+
+	/* Rewrite arguments to argv, argv is not null-terminated and will be
+	 * passed to g_option_context_parse.
+	 */
+	argv = g_new(gchar *, argc);
+	for (loop = 0; loop < argc; loop++)
+		argv[loop] = arguments[loop];
+
+	context = g_option_context_new(NULL);
+	g_option_context_add_main_entries(context, filtered_discovery_options,
+									 NULL);
+	/* set default values for all options */
+	filtered_scan_rssi = DISTANCE_VAL_INVALID;
+	filtered_scan_pathloss = DISTANCE_VAL_INVALID;
+	filtered_scan_uuids = NULL;
+	filtered_scan_transport = NULL;
+	filtered_scan_help = FALSE;
+
+	g_option_context_set_help_enabled(context, FALSE);
+	if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
+		if (error != NULL) {
+			g_printerr("error in g_option_context_parse: %s\n",
+							       error->message);
+			g_error_free(error);
+		} else
+			g_printerr("An unknown error occurred\n");
+
+		g_strfreev(arguments);
+		g_free(argv);
+		return false;
+	}
+
+	if (filtered_scan_help) {
+		printf("Set discovery filter. Usage:\n");
+		printf("	set-discovery-filter [-r rssi | -p pathlos] ");
+		printf("[-t transport] -u <uuid1> [-u <uuid2> ...]\n");
+		printf("\n");
+		printf("Example: set-discovery-filter -p 65 -u baba -u 1900\n");
+		return false;
+	}
+
+	args->uuids = NULL;
+	args->pathloss = filtered_scan_pathloss;
+	args->rssi = filtered_scan_rssi;
+	args->transport = filtered_scan_transport;
+
+	if (filtered_scan_uuids != NULL)
+		for (loop = 0; filtered_scan_uuids[loop] != NULL; loop++) {
+			args->uuids = g_list_append(args->uuids,
+					    strdup(filtered_scan_uuids[loop]));
+		}
+
+	g_strfreev(arguments);
+	g_free(argv);
+	g_strfreev(filtered_scan_uuids);
+
+	g_option_context_free(context);
+	return true;
+}
+
+static void cmd_set_discovery_filter(const char *arg)
+{
+	struct set_discovery_filter_args args;
+
+	if (!parse_set_discovery_filter_params(arg, &args))
+		return;
+
+	if (check_default_ctrl() == FALSE)
+		return;
+
+	if (g_dbus_proxy_method_call(default_ctrl, "SetDiscoveryFilter",
+		set_discovery_filter_setup, set_discovery_filter_reply,
+		&args, NULL /* TODO: proper freeing method here */) == FALSE) {
+		rl_printf("Failed to set discovery filter\n");
+		return;
+	}
+}
+
 static struct GDBusProxy *find_device(const char *arg)
 {
 	GDBusProxy *proxy;
@@ -1433,6 +1675,8 @@ static const struct {
 							capability_generator},
 	{ "default-agent",NULL,       cmd_default_agent,
 				"Set agent as the default one" },
+	{ "set-discovery-filter", "", cmd_set_discovery_filter,
+		"Set discovery filter. Run discovery-filter -h for help" },
 	{ "scan",         "<on/off>", cmd_scan, "Scan for devices" },
 	{ "info",         "[dev]",    cmd_info, "Device information",
 							dev_generator },
-- 
2.2.0.rc0.207.ga3a616c


  parent reply	other threads:[~2015-03-25  8:19 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-25  8:18 [PATCH v5 1/8] core: device: add device_set_rssi_no_delta Jakub Pawlowski
2015-03-25  8:18 ` [PATCH v5 2/8] core/adapter: Refactor of scan type Jakub Pawlowski
2015-03-25  8:18 ` [PATCH v5 3/8] core: adapter: Add SetDiscoveryFilter method Jakub Pawlowski
2015-03-25  8:18 ` [PATCH v5 4/8] core: adapter: Add parameter parsing to SetDiscoveryFilter Jakub Pawlowski
2015-03-25  8:18 ` [PATCH v5 5/8] core: adapter: set the filter for each discovery client Jakub Pawlowski
2015-03-25  8:18 ` [PATCH v5 6/8] core: adapter: start proper discovery depending on filter type Jakub Pawlowski
2015-03-26  5:25   ` Arman Uguray
2015-03-26  8:28     ` Jakub Pawlowski
2015-03-25  8:19 ` [PATCH v5 7/8] core: adapter: filter discovery results when filered discovery is used Jakub Pawlowski
2015-03-25  8:19 ` Jakub Pawlowski [this message]
2015-03-26  5:29 ` [PATCH v5 1/8] core: device: add device_set_rssi_no_delta Arman Uguray

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1427271541-7509-8-git-send-email-jpawlowski@google.com \
    --to=jpawlowski@google.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.