linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Arik Nemtsov <arik@wizery.com>
To: <linux-bluetooth@vger.kernel.org>
Cc: Arik Nemtsov <arik@wizery.com>
Subject: [PATCH 8/8] proximity: reporter: implement D-Bus API
Date: Thu,  8 Mar 2012 15:57:12 +0200	[thread overview]
Message-ID: <1331215032-27695-9-git-send-email-arik@wizery.com> (raw)
In-Reply-To: <1331215032-27695-1-git-send-email-arik@wizery.com>

Register a D-Bus interface per remote device. Set a watch on the
"DeviceAdded" signal to add all existing devices. Likewise set watches
on "DeviceCreated" and "DeviceRemoved" to handle dynamic addition and
removal of devices.

Implement the "GetProperties" method of the D-Bus interface by querying
the alert level of the remote device in the link-loss and
immediate-alert proximity profiles. The default values for non-connected
devices are "none".
---
 proximity/reporter.c |  204 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 196 insertions(+), 8 deletions(-)

diff --git a/proximity/reporter.c b/proximity/reporter.c
index 4972aa2..d540233 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -31,8 +31,14 @@
 #include <adapter.h>
 #include <errno.h>
 
+#include <dbus/dbus.h>
+#include <gdbus.h>
+
 #include "log.h"
 
+#include "dbus-common.h"
+#include "error.h"
+#include "device.h"
 #include "hcid.h"
 #include "att.h"
 #include "gattrib.h"
@@ -41,7 +47,18 @@
 #include "linkloss.h"
 #include "immalert.h"
 
-static DBusConnection *connection;
+#define BLUEZ_SERVICE "org.bluez"
+
+struct reporter_adapter {
+	DBusConnection *conn;
+	struct btd_adapter *adapter;
+	guint watch_created;
+	guint watch_added;
+	guint watch_removed;
+	GSList *devices;
+};
+
+static GSList *reporter_adapters;
 
 const char *get_alert_level_string(uint8_t level)
 {
@@ -101,28 +118,199 @@ static void register_tx_power(struct btd_adapter *adapter)
 	g_assert(h - start_handle == svc_size);
 }
 
+static DBusMessage *get_properties(DBusConnection *conn,
+					DBusMessage *msg, void *data)
+{
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	DBusMessage *reply = NULL;
+	const char *linkloss_level, *immalert_level;
+	struct btd_device *device = data;
+
+	reply = dbus_message_new_method_return(msg);
+	if (!reply)
+		return NULL;
+
+	linkloss_level = link_loss_get_alert_level(device);
+	immalert_level = imm_get_alert_level(device);
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	if (!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))
+		goto err;
+
+	dict_append_entry(&dict, "LinkLossAlertLevel",
+			DBUS_TYPE_STRING, &linkloss_level);
+	dict_append_entry(&dict, "ImmediateAlertLevel",
+			DBUS_TYPE_STRING, &immalert_level);
+
+	if (!dbus_message_iter_close_container(&iter, &dict))
+		goto err;
+
+	return reply;
+
+err:
+	if (reply)
+		dbus_message_unref(reply);
+	return btd_error_failed(msg, "not enough memory");
+}
+
+static GDBusMethodTable reporter_methods[] = {
+	{ "GetProperties",	"",	"a{sv}",	get_properties	},
+	{ }
+};
+
+static GDBusSignalTable reporter_signals[] = {
+	{ "PropertyChanged",	"sv"	},
+	{ }
+};
+
+static void unregister_reporter_device(gpointer data, gpointer user_data)
+{
+	struct btd_device *device = data;
+	struct reporter_adapter *radapter = user_data;
+	const char *path = device_get_path(device);
+
+	g_dbus_unregister_interface(radapter->conn, path,
+				    PROXIMITY_REPORTER_INTERFACE);
+
+	radapter->devices = g_slist_remove(radapter->devices, device);
+	btd_device_unref(device);
+}
+
+static void register_reporter_device(struct btd_device *device,
+				     struct reporter_adapter *radapter)
+{
+	const char *path = device_get_path(device);
+
+	DBG("register on device %s", path);
+
+	g_dbus_register_interface(radapter->conn, path,
+				  PROXIMITY_REPORTER_INTERFACE,
+				  reporter_methods, reporter_signals,
+				  NULL, device, NULL);
+
+	btd_device_ref(device);
+	radapter->devices = g_slist_prepend(radapter->devices, device);
+}
+
+static gboolean handle_device_change(DBusConnection *conn,
+				  DBusMessage *msg, void *data)
+{
+	struct reporter_adapter *radapter = data;
+	DBusMessageIter iter;
+	const char *dev_path;
+	struct btd_device *device;
+	gboolean device_removed = FALSE;
+
+	dbus_message_iter_init(msg, &iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH) {
+		error("Unexpected arg %s.%s DeviceCreated/Added/Removed",
+		      dbus_message_get_interface(msg),
+		      dbus_message_get_member(msg));
+		return TRUE;
+	}
+
+	if (g_strcmp0(dbus_message_get_member(msg), "DeviceRemoved") == 0)
+		device_removed = TRUE;
+
+	dbus_message_iter_get_basic(&iter, &dev_path);
+
+	device = adapter_get_device_by_path(radapter->adapter, dev_path);
+	if (!device)
+		return TRUE;
+
+	if (device_removed)
+		unregister_reporter_device(device, radapter);
+	else
+		register_reporter_device(device, radapter);
+
+	return TRUE;
+}
+
 int reporter_init(struct btd_adapter *adapter)
 {
+	struct reporter_adapter *radapter;
+	DBusConnection *conn;
+
 	if (!main_opts.attrib_server) {
 		DBG("Attribute server is disabled");
 		return -1;
 	}
 
-	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
-	if (connection == NULL)
-		return -EIO;
-	DBG("Proximity Reporter for adapter %p", adapter);
+	conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+	if (!conn)
+		return -1;
 
-	register_link_loss(adapter, connection);
+	radapter = g_new0(struct reporter_adapter, 1);
+	radapter->adapter = adapter;
+	radapter->conn = conn;
+
+	register_link_loss(adapter, radapter->conn);
 	register_tx_power(adapter);
-	register_imm_alert(adapter, connection);
+	register_imm_alert(adapter, radapter->conn);
+
+	/*
+	 * Register watches for getting device change events. We watch
+	 * for existing, new and removed devices.
+	 */
+	radapter->watch_added = g_dbus_add_signal_watch(radapter->conn,
+					BLUEZ_SERVICE, NULL, ADAPTER_INTERFACE,
+					"DeviceAdded", handle_device_change,
+					radapter, NULL);
+
+	radapter->watch_created = g_dbus_add_signal_watch(radapter->conn,
+					BLUEZ_SERVICE, NULL, ADAPTER_INTERFACE,
+					"DeviceCreated", handle_device_change,
+					radapter, NULL);
+
+	radapter->watch_removed = g_dbus_add_signal_watch(radapter->conn,
+					BLUEZ_SERVICE, NULL, ADAPTER_INTERFACE,
+					"DeviceRemoved", handle_device_change,
+					radapter, NULL);
+
+	reporter_adapters = g_slist_prepend(reporter_adapters, radapter);
+	DBG("Proximity Reporter for adapter %p", adapter);
 
 	return 0;
 }
 
+static int radapter_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct reporter_adapter *radapter = a;
+	const struct btd_adapter *adapter = b;
+
+	if (radapter->adapter == adapter)
+		return 0;
+
+	return -1;
+}
+
 void reporter_exit(struct btd_adapter *adapter)
 {
+	struct reporter_adapter *radapter;
+	GSList *l = g_slist_find_custom(reporter_adapters, adapter,
+					radapter_cmp);
+	if (!l)
+		return;
+
+	radapter = l->data;
+
+	g_dbus_remove_watch(radapter->conn, radapter->watch_created);
+	g_dbus_remove_watch(radapter->conn, radapter->watch_added);
+	g_dbus_remove_watch(radapter->conn, radapter->watch_removed);
+
+	g_slist_foreach(radapter->devices, unregister_reporter_device,
+			radapter);
+
 	unregister_link_loss(adapter);
 	unregister_imm_alert(adapter);
-	dbus_connection_unref(connection);
+	dbus_connection_unref(radapter->conn);
+
+	reporter_adapters = g_slist_remove(reporter_adapters, radapter);
+	g_free(radapter);
 }
-- 
1.7.5.4


  parent reply	other threads:[~2012-03-08 13:57 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-08 13:57 [PATCH 0/8] Implement ProximityReporter profiles Arik Nemtsov
2012-03-08 13:57 ` [PATCH 1/8] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
2012-03-08 13:57 ` [PATCH 2/8] adapter: add API to find an existing device by D-Bus path Arik Nemtsov
2012-03-08 13:57 ` [PATCH 3/8] adapter: add DeviceAdded signal when existing device is added Arik Nemtsov
2012-03-08 13:57 ` [PATCH 4/8] proximity: reporter: save global D-Bus connection Arik Nemtsov
2012-03-08 13:57 ` [PATCH 5/8] proximity: reporter: move definitions to .h and add util function Arik Nemtsov
2012-03-08 13:57 ` [PATCH 6/8] proximity: link loss: implement link loss server Arik Nemtsov
2012-03-14 13:09   ` Anderson Lizardo
2012-03-14 20:54     ` Arik Nemtsov
2012-03-08 13:57 ` [PATCH 7/8] proximity: immediate alert: implement immediate alert server Arik Nemtsov
2012-03-08 13:57 ` Arik Nemtsov [this message]
2012-03-14 13:19   ` [PATCH 8/8] proximity: reporter: implement D-Bus API Anderson Lizardo
2012-03-14 20:56     ` Arik Nemtsov

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=1331215032-27695-9-git-send-email-arik@wizery.com \
    --to=arik@wizery.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).