linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks
@ 2012-04-02 19:12 Arik Nemtsov
  2012-04-02 19:12 ` [PATCH v8 2/6] proximity: reporter: save global D-Bus connection Arik Nemtsov
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Arik Nemtsov @ 2012-04-02 19:12 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Arik Nemtsov

This allows us to identify the remote device that made the ATT
read/write.
---
 attrib/att-database.h  |   43 +++++++++++++++++++++++++++++++++++++++++++
 attrib/att.h           |   20 --------------------
 attrib/gatt-service.c  |    1 +
 plugins/gatt-example.c |    4 +++-
 proximity/reporter.c   |    1 +
 src/attrib-server.c    |   20 +++++++++++++++-----
 time/server.c          |    7 +++++--
 7 files changed, 68 insertions(+), 28 deletions(-)
 create mode 100644 attrib/att-database.h

diff --git a/attrib/att-database.h b/attrib/att-database.h
new file mode 100644
index 0000000..3e854aa
--- /dev/null
+++ b/attrib/att-database.h
@@ -0,0 +1,43 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Texas Instruments Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/* Requirements for read/write operations */
+enum {
+	ATT_NONE,		/* No restrictions */
+	ATT_AUTHENTICATION,	/* Authentication required */
+	ATT_AUTHORIZATION,	/* Authorization required */
+	ATT_NOT_PERMITTED,	/* Operation not permitted */
+};
+
+struct attribute {
+	uint16_t handle;
+	bt_uuid_t uuid;
+	int read_reqs;
+	int write_reqs;
+	uint8_t (*read_cb)(struct attribute *a, struct btd_device *device,
+							gpointer user_data);
+	uint8_t (*write_cb)(struct attribute *a, struct btd_device *device,
+							gpointer user_data);
+	gpointer cb_user_data;
+	int len;
+	uint8_t *data;
+};
diff --git a/attrib/att.h b/attrib/att.h
index 09511d2..1e128a7 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -117,26 +117,6 @@
 #define ATT_CID					4
 #define ATT_PSM					31
 
-/* Requirements for read/write operations */
-enum {
-	ATT_NONE,		/* No restrictions */
-	ATT_AUTHENTICATION,	/* Authentication required */
-	ATT_AUTHORIZATION,	/* Authorization required */
-	ATT_NOT_PERMITTED,	/* Operation not permitted */
-};
-
-struct attribute {
-	uint16_t handle;
-	bt_uuid_t uuid;
-	int read_reqs;
-	int write_reqs;
-	uint8_t (*read_cb)(struct attribute *a, gpointer user_data);
-	uint8_t (*write_cb)(struct attribute *a, gpointer user_data);
-	gpointer cb_user_data;
-	int len;
-	uint8_t *data;
-};
-
 struct att_data_list {
 	uint16_t num;
 	uint16_t len;
diff --git a/attrib/gatt-service.c b/attrib/gatt-service.c
index 4592a90..6a44a06 100644
--- a/attrib/gatt-service.c
+++ b/attrib/gatt-service.c
@@ -32,6 +32,7 @@
 #include <adapter.h>
 
 #include "att.h"
+#include "att-database.h"
 #include "gattrib.h"
 #include "attrib-server.h"
 #include "gatt-service.h"
diff --git a/plugins/gatt-example.c b/plugins/gatt-example.c
index 58b222c..482bc2d 100644
--- a/plugins/gatt-example.c
+++ b/plugins/gatt-example.c
@@ -37,6 +37,7 @@
 #include "gattrib.h"
 #include "gatt-service.h"
 #include "att.h"
+#include "att-database.h"
 #include "attrib-server.h"
 
 /* FIXME: Not defined by SIG? UUID128? */
@@ -92,7 +93,8 @@ static gint adapter_cmp(gconstpointer a, gconstpointer b)
 	return -1;
 }
 
-static uint8_t battery_state_read(struct attribute *a, gpointer user_data)
+static uint8_t battery_state_read(struct attribute *a,
+				  struct btd_device *device, gpointer user_data)
 {
 	struct btd_adapter *adapter = user_data;
 	uint8_t value;
diff --git a/proximity/reporter.c b/proximity/reporter.c
index 74e6297..bbb97ea 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -35,6 +35,7 @@
 
 #include "hcid.h"
 #include "att.h"
+#include "att-database.h"
 #include "gattrib.h"
 #include "attrib-server.h"
 #include "reporter.h"
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 5775861..18a0218 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -47,6 +47,7 @@
 #include "device.h"
 #include "manager.h"
 #include "att.h"
+#include "att-database.h"
 #include "gattrib.h"
 #include "storage.h"
 
@@ -76,6 +77,7 @@ struct gatt_channel {
 	gboolean encrypted;
 	struct gatt_server *server;
 	guint cleanup_id;
+	struct btd_device *device;
 };
 
 struct group_elem {
@@ -112,6 +114,9 @@ static void channel_free(struct gatt_channel *channel)
 	if (channel->cleanup_id)
 		g_source_remove(channel->cleanup_id);
 
+	if (channel->device)
+		btd_device_unref(channel->device);
+
 	g_attrib_unref(channel->attrib);
 	g_free(channel);
 }
@@ -452,7 +457,8 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
 								a->read_reqs);
 
 		if (status == 0x00 && a->read_cb)
-			status = a->read_cb(a, a->cb_user_data);
+			status = a->read_cb(a, channel->device,
+							a->cb_user_data);
 
 		if (status) {
 			g_slist_free_full(groups, g_free);
@@ -541,7 +547,8 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
 								a->read_reqs);
 
 		if (status == 0x00 && a->read_cb)
-			status = a->read_cb(a, a->cb_user_data);
+			status = a->read_cb(a, channel->device,
+							a->cb_user_data);
 
 		if (status) {
 			g_slist_free(types);
@@ -753,7 +760,7 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 	status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
 
 	if (status == 0x00 && a->read_cb)
-		status = a->read_cb(a, a->cb_user_data);
+		status = a->read_cb(a, channel->device, a->cb_user_data);
 
 	if (status)
 		return enc_error_resp(ATT_OP_READ_REQ, handle, status, pdu,
@@ -796,7 +803,7 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
 	status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
 
 	if (status == 0x00 && a->read_cb)
-		status = a->read_cb(a, a->cb_user_data);
+		status = a->read_cb(a, channel->device, a->cb_user_data);
 
 	if (status)
 		return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle, status,
@@ -833,7 +840,8 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
 							value, vlen, NULL);
 
 		if (a->write_cb) {
-			status = a->write_cb(a, a->cb_user_data);
+			status = a->write_cb(a, channel->device,
+							a->cb_user_data);
 			if (status)
 				return enc_error_resp(ATT_OP_WRITE_REQ, handle,
 							status, pdu, len);
@@ -1067,6 +1075,8 @@ guint attrib_channel_attach(GAttrib *attrib)
 	channel->cleanup_id = g_io_add_watch(io, G_IO_HUP, channel_watch_cb,
 								channel);
 
+	channel->device = btd_device_ref(device);
+
 	server->clients = g_slist_append(server->clients, channel);
 
 	return channel->id;
diff --git a/time/server.c b/time/server.c
index 42b12e2..58d0bcc 100644
--- a/time/server.c
+++ b/time/server.c
@@ -33,6 +33,7 @@
 #include <adapter.h>
 
 #include "att.h"
+#include "att-database.h"
 #include "gattrib.h"
 #include "attrib-server.h"
 #include "gatt-service.h"
@@ -78,7 +79,8 @@ static int encode_current_time(uint8_t value[10])
 	return 0;
 }
 
-static uint8_t current_time_read(struct attribute *a, gpointer user_data)
+static uint8_t current_time_read(struct attribute *a,
+				 struct btd_device *device, gpointer user_data)
 {
 	uint8_t value[10];
 
@@ -91,7 +93,8 @@ static uint8_t current_time_read(struct attribute *a, gpointer user_data)
 	return 0;
 }
 
-static uint8_t local_time_info_read(struct attribute *a, gpointer user_data)
+static uint8_t local_time_info_read(struct attribute *a,
+				struct btd_device *device, gpointer user_data)
 {
 	uint8_t value[2];
 
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v8 2/6] proximity: reporter: save global D-Bus connection
  2012-04-02 19:12 [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
@ 2012-04-02 19:12 ` Arik Nemtsov
  2012-04-02 19:12 ` [PATCH v8 3/6] proximity: reporter: move definitions to .h and add util function Arik Nemtsov
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Arik Nemtsov @ 2012-04-02 19:12 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Arik Nemtsov

This connection will be used by reporter GATT sub-profiles.
---
 proximity/reporter.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/proximity/reporter.c b/proximity/reporter.c
index bbb97ea..c5a3bb8 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -52,6 +52,8 @@ enum {
 	HIGH_ALERT = 0x02,
 };
 
+static DBusConnection *connection;
+
 static void register_link_loss(struct btd_adapter *adapter)
 {
 	uint16_t start_handle, h;
@@ -179,6 +181,9 @@ int reporter_init(struct btd_adapter *adapter)
 		return -ENOTSUP;
 	}
 
+	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+	if (connection == NULL)
+		return -EIO;
 	DBG("Proximity Reporter for adapter %p", adapter);
 
 	register_link_loss(adapter);
@@ -190,4 +195,5 @@ int reporter_init(struct btd_adapter *adapter)
 
 void reporter_exit(struct btd_adapter *adapter)
 {
+	dbus_connection_unref(connection);
 }
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v8 3/6] proximity: reporter: move definitions to .h and add util function
  2012-04-02 19:12 [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
  2012-04-02 19:12 ` [PATCH v8 2/6] proximity: reporter: save global D-Bus connection Arik Nemtsov
@ 2012-04-02 19:12 ` Arik Nemtsov
  2012-04-02 19:12 ` [PATCH v8 4/6] proximity: link loss: implement link loss server Arik Nemtsov
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Arik Nemtsov @ 2012-04-02 19:12 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Arik Nemtsov

This allows us to re-use these definitions in GATT sub-profiles.
---
 proximity/reporter.c |   24 +++++++++++++-----------
 proximity/reporter.h |   16 ++++++++++++++++
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/proximity/reporter.c b/proximity/reporter.c
index c5a3bb8..2474fea 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -40,20 +40,22 @@
 #include "attrib-server.h"
 #include "reporter.h"
 
-#define IMMEDIATE_ALERT_SVC_UUID	0x1802
-#define LINK_LOSS_SVC_UUID		0x1803
-#define TX_POWER_SVC_UUID		0x1804
-#define ALERT_LEVEL_CHR_UUID		0x2A06
-#define POWER_LEVEL_CHR_UUID		0x2A07
-
-enum {
-	NO_ALERT = 0x00,
-	MILD_ALERT = 0x01,
-	HIGH_ALERT = 0x02,
-};
-
 static DBusConnection *connection;
 
+const char *get_alert_level_string(uint8_t level)
+{
+	switch (level) {
+	case NO_ALERT:
+		return "none";
+	case MILD_ALERT:
+		return "mild";
+	case HIGH_ALERT:
+		return "high";
+	}
+
+	return "unknown";
+}
+
 static void register_link_loss(struct btd_adapter *adapter)
 {
 	uint16_t start_handle, h;
diff --git a/proximity/reporter.h b/proximity/reporter.h
index 2b18446..5ae0eb2 100644
--- a/proximity/reporter.h
+++ b/proximity/reporter.h
@@ -22,5 +22,21 @@
  *
  */
 
+#define PROXIMITY_REPORTER_INTERFACE "org.bluez.ProximityReporter"
+
+#define IMMEDIATE_ALERT_SVC_UUID	0x1802
+#define LINK_LOSS_SVC_UUID		0x1803
+#define TX_POWER_SVC_UUID		0x1804
+#define ALERT_LEVEL_CHR_UUID		0x2A06
+#define POWER_LEVEL_CHR_UUID		0x2A07
+
+enum {
+	NO_ALERT = 0x00,
+	MILD_ALERT = 0x01,
+	HIGH_ALERT = 0x02,
+};
+
 int reporter_init(struct btd_adapter *adapter);
 void reporter_exit(struct btd_adapter *adapter);
+
+const char *get_alert_level_string(uint8_t level);
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v8 4/6] proximity: link loss: implement link loss server
  2012-04-02 19:12 [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
  2012-04-02 19:12 ` [PATCH v8 2/6] proximity: reporter: save global D-Bus connection Arik Nemtsov
  2012-04-02 19:12 ` [PATCH v8 3/6] proximity: reporter: move definitions to .h and add util function Arik Nemtsov
@ 2012-04-02 19:12 ` Arik Nemtsov
  2012-04-02 19:12 ` [PATCH v8 5/6] proximity: immediate alert: implement immediate alert server Arik Nemtsov
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Arik Nemtsov @ 2012-04-02 19:12 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Arik Nemtsov

The profile is implemented in linkloss.[ch]. A GATT service is
registered with read/write callbacks on the link-loss alert level
attribute. The alert level is maintained per device. It is returned
on read and updated on write.

When the alert level is non-zero, a callback is registered on the
disconnection of the remote device. If a device with non-zero alert
state is disconnected, an appropriate PropertyChanged signal is emitted
with the alert level previously set by the device. We avoid emitting
a signal when the disconnection was requested by us.
---
 Makefile.am          |    3 +-
 proximity/linkloss.c |  337 ++++++++++++++++++++++++++++++++++++++++++++++++++
 proximity/linkloss.h |   26 ++++
 proximity/reporter.c |   42 +------
 4 files changed, 368 insertions(+), 40 deletions(-)
 create mode 100644 proximity/linkloss.c
 create mode 100644 proximity/linkloss.h

diff --git a/Makefile.am b/Makefile.am
index ddc28d2..12b3d81 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -222,7 +222,8 @@ builtin_sources += thermometer/main.c \
             plugins/gatt-example.c \
             proximity/main.c proximity/manager.h proximity/manager.c \
 			proximity/monitor.h proximity/monitor.c \
-			proximity/reporter.h proximity/reporter.c
+			proximity/reporter.h proximity/reporter.c \
+			proximity/linkloss.h proximity/linkloss.c
 endif
 
 
diff --git a/proximity/linkloss.c b/proximity/linkloss.c
new file mode 100644
index 0000000..79631eb
--- /dev/null
+++ b/proximity/linkloss.c
@@ -0,0 +1,337 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Texas Instruments Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <bluetooth/uuid.h>
+#include <adapter.h>
+
+#include <dbus/dbus.h>
+#include <gdbus.h>
+
+#include "log.h"
+#include "att.h"
+#include "att-database.h"
+#include "gattrib.h"
+#include "gatt-service.h"
+#include "attrib-server.h"
+#include "device.h"
+#include "attio.h"
+#include "dbus-common.h"
+#include "reporter.h"
+#include "linkloss.h"
+
+#define BLUEZ_SERVICE "org.bluez"
+
+struct link_loss_adapter {
+	struct btd_adapter *adapter;
+	uint16_t alert_lvl_value_handle;
+	DBusConnection *conn;
+	GSList *connected_devices;
+};
+
+struct connected_device {
+	struct btd_device *device;
+	struct link_loss_adapter *adapter;
+	uint8_t alert_level;
+	guint callback_id;
+	guint local_disc_id;
+};
+
+static GSList *link_loss_adapters;
+
+static int lldevice_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct connected_device *llcondev = a;
+	const struct btd_device *device = b;
+
+	if (llcondev->device == device)
+		return 0;
+
+	return -1;
+}
+
+static struct connected_device *
+find_connected_device(struct link_loss_adapter *la, struct btd_device *device)
+{
+	GSList *l = g_slist_find_custom(la->connected_devices, device,
+								lldevice_cmp);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
+
+static int lladapter_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct link_loss_adapter *lladapter = a;
+	const struct btd_adapter *adapter = b;
+
+	if (lladapter->adapter == adapter)
+		return 0;
+
+	return -1;
+}
+
+static struct link_loss_adapter *
+find_link_loss_adapter(struct btd_adapter *adapter)
+{
+	GSList *l = g_slist_find_custom(link_loss_adapters, adapter,
+							lladapter_cmp);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
+
+const char *link_loss_get_alert_level(struct btd_device *device)
+{
+	struct link_loss_adapter *lladapter;
+	struct connected_device *condev;
+
+	if (!device)
+		return get_alert_level_string(NO_ALERT);
+
+	lladapter = find_link_loss_adapter(device_get_adapter(device));
+	if (!lladapter)
+		return get_alert_level_string(NO_ALERT);
+
+	condev = find_connected_device(lladapter, device);
+	if (!condev)
+		return get_alert_level_string(NO_ALERT);
+
+	return get_alert_level_string(condev->alert_level);
+}
+
+static void link_loss_emit_alert_signal(struct connected_device *condev)
+{
+	struct link_loss_adapter *adapter = condev->adapter;
+	const char *alert_level_str, *path;
+
+	if (!condev->device)
+		return;
+
+	path = device_get_path(condev->device);
+	alert_level_str = get_alert_level_string(condev->alert_level);
+
+	DBG("alert %s remote %s", alert_level_str, path);
+
+	emit_property_changed(adapter->conn, path,
+			PROXIMITY_REPORTER_INTERFACE, "LinkLossAlertLevel",
+			DBUS_TYPE_STRING, &alert_level_str);
+}
+
+static uint8_t link_loss_alert_lvl_read(struct attribute *a,
+				struct btd_device *device, gpointer user_data)
+{
+	struct link_loss_adapter *la = user_data;
+	struct connected_device *condev;
+	uint8_t alert_level = NO_ALERT;
+
+	if (!device)
+		goto out;
+
+	condev = find_connected_device(la, device);
+	if (!condev)
+		goto out;
+
+	alert_level = condev->alert_level;
+
+out:
+	DBG("return alert level %d for dev %p", alert_level, device);
+
+	/* update the alert level according to the requesting device */
+	attrib_db_update(la->adapter, a->handle, NULL, &alert_level,
+						sizeof(alert_level), NULL);
+
+	return 0;
+}
+
+/* condev can be NULL */
+static void link_loss_remove_condev(struct connected_device *condev)
+{
+	struct link_loss_adapter *la;
+
+	if (!condev)
+		return;
+
+	la = condev->adapter;
+
+	if (condev->callback_id && condev->device)
+		btd_device_remove_attio_callback(condev->device,
+							condev->callback_id);
+
+	if (condev->local_disc_id && condev->device)
+		device_remove_disconnect_watch(condev->device,
+							condev->local_disc_id);
+
+	if (condev->device)
+		btd_device_unref(condev->device);
+
+	la->connected_devices = g_slist_remove(la->connected_devices, condev);
+	g_free(condev);
+}
+
+static void link_loss_disc_cb(gpointer user_data)
+{
+	struct connected_device *condev = user_data;
+
+	DBG("alert loss disconnect device %p", condev->device);
+
+	/* if an alert-level is set, emit a signal */
+	if (condev->alert_level != NO_ALERT)
+		link_loss_emit_alert_signal(condev);
+
+	/* we are open for more changes now */
+	link_loss_remove_condev(condev);
+}
+
+static void link_loss_local_disc(struct btd_device *device,
+					gboolean removal, void *user_data)
+{
+	struct connected_device *condev = user_data;
+
+	/* no need to alert on this device - we requested disconnection */
+	link_loss_remove_condev(condev);
+
+	DBG("alert level zeroed for locally disconnecting dev %p", device);
+}
+
+static uint8_t link_loss_alert_lvl_write(struct attribute *a,
+				struct btd_device *device, gpointer user_data)
+{
+	uint8_t value;
+	struct link_loss_adapter *la = user_data;
+	struct connected_device *condev = NULL;
+
+	if (!device)
+		goto set_error;
+
+	/* condev might remain NULL here if nothing is found */
+	condev = find_connected_device(la, device);
+
+	if (a->len == 0) {
+		DBG("Illegal alert level length");
+		goto set_error;
+	}
+
+	value = a->data[0];
+	if (value != NO_ALERT && value != MILD_ALERT && value != HIGH_ALERT) {
+		DBG("Illegal alert value");
+		goto set_error;
+	}
+
+	/* Register a disconnect cb if the alert level is non-zero */
+	if (value != NO_ALERT && !condev) {
+		condev = g_new0(struct connected_device, 1);
+		condev->device = btd_device_ref(device);
+		condev->adapter = la;
+		condev->callback_id = btd_device_add_attio_callback(device,
+					NULL, link_loss_disc_cb, condev);
+		condev->local_disc_id = device_add_disconnect_watch(device,
+					link_loss_local_disc, condev, NULL);
+
+		la->connected_devices = g_slist_append(la->connected_devices,
+								condev);
+	} else if (value == NO_ALERT && condev) {
+		link_loss_remove_condev(condev);
+		condev = NULL;
+	}
+
+	DBG("alert level set to %d by device %p", value, device);
+
+	if (condev)
+		condev->alert_level = value;
+
+	return 0;
+
+set_error:
+	error("Set link loss alert level for dev %p", device);
+	/* reset alert level on erroneous devices */
+	link_loss_remove_condev(condev);
+	return ATT_ECODE_IO;
+}
+
+void link_loss_register(struct btd_adapter *adapter, DBusConnection *conn)
+{
+	gboolean svc_added;
+	bt_uuid_t uuid;
+	struct link_loss_adapter *lladapter;
+
+	bt_uuid16_create(&uuid, LINK_LOSS_SVC_UUID);
+
+	lladapter = g_new0(struct link_loss_adapter, 1);
+	lladapter->adapter = adapter;
+	lladapter->conn = dbus_connection_ref(conn);
+
+	link_loss_adapters = g_slist_append(link_loss_adapters, lladapter);
+
+	/* Link Loss Service */
+	svc_added = gatt_service_add(adapter,
+		GATT_PRIM_SVC_UUID, &uuid,
+		/* Alert level characteristic */
+		GATT_OPT_CHR_UUID, ALERT_LEVEL_CHR_UUID,
+		GATT_OPT_CHR_PROPS,
+			ATT_CHAR_PROPER_READ | ATT_CHAR_PROPER_WRITE,
+		GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+			link_loss_alert_lvl_read, lladapter,
+		GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
+			link_loss_alert_lvl_write, lladapter,
+		GATT_OPT_CHR_VALUE_GET_HANDLE,
+			&lladapter->alert_lvl_value_handle,
+		GATT_OPT_INVALID);
+
+	if (!svc_added)
+		goto err;
+
+	DBG("Link Loss service added");
+	return;
+
+err:
+	error("Error adding Link Loss service");
+	link_loss_unregister(adapter);
+}
+
+static void remove_condev_list_item(gpointer data, gpointer user_data)
+{
+	struct connected_device *condev = data;
+
+	link_loss_remove_condev(condev);
+}
+
+void link_loss_unregister(struct btd_adapter *adapter)
+{
+	struct link_loss_adapter *lladapter;
+	lladapter = find_link_loss_adapter(adapter);
+	if (!lladapter)
+		return;
+
+	g_slist_foreach(lladapter->connected_devices, remove_condev_list_item,
+			NULL);
+	dbus_connection_unref(lladapter->conn);
+
+	link_loss_adapters = g_slist_remove(link_loss_adapters, lladapter);
+	g_free(lladapter);
+}
diff --git a/proximity/linkloss.h b/proximity/linkloss.h
new file mode 100644
index 0000000..a7d83d0
--- /dev/null
+++ b/proximity/linkloss.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Texas Instruments Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+void link_loss_register(struct btd_adapter *adapter, DBusConnection *conn);
+void link_loss_unregister(struct btd_adapter *adapter);
+const char *link_loss_get_alert_level(struct btd_device *device);
diff --git a/proximity/reporter.c b/proximity/reporter.c
index 2474fea..cc371f2 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -39,6 +39,7 @@
 #include "gattrib.h"
 #include "attrib-server.h"
 #include "reporter.h"
+#include "linkloss.h"
 
 static DBusConnection *connection;
 
@@ -56,44 +57,6 @@ const char *get_alert_level_string(uint8_t level)
 	return "unknown";
 }
 
-static void register_link_loss(struct btd_adapter *adapter)
-{
-	uint16_t start_handle, h;
-	const int svc_size = 3;
-	uint8_t atval[256];
-	bt_uuid_t uuid;
-
-	bt_uuid16_create(&uuid, LINK_LOSS_SVC_UUID);
-	start_handle = attrib_db_find_avail(adapter, &uuid, svc_size);
-	if (start_handle == 0) {
-		error("Not enough free handles to register service");
-		return;
-	}
-
-	DBG("start_handle=0x%04x", start_handle);
-
-	h = start_handle;
-
-	/* Primary service definition */
-	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
-	att_put_u16(LINK_LOSS_SVC_UUID, &atval[0]);
-	attrib_db_add(adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
-
-	/* Alert level characteristic */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ | ATT_CHAR_PROPER_WRITE;
-	att_put_u16(h + 1, &atval[1]);
-	att_put_u16(ALERT_LEVEL_CHR_UUID, &atval[3]);
-	attrib_db_add(adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Alert level value */
-	bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID);
-	att_put_u8(NO_ALERT, &atval[0]);
-	attrib_db_add(adapter, h++, &uuid, ATT_NONE, ATT_NONE, atval, 1);
-
-	g_assert(h - start_handle == svc_size);
-}
-
 static void register_tx_power(struct btd_adapter *adapter)
 {
 	uint16_t start_handle, h;
@@ -188,7 +151,7 @@ int reporter_init(struct btd_adapter *adapter)
 		return -EIO;
 	DBG("Proximity Reporter for adapter %p", adapter);
 
-	register_link_loss(adapter);
+	link_loss_register(adapter, connection);
 	register_tx_power(adapter);
 	register_immediate_alert(adapter);
 
@@ -197,5 +160,6 @@ int reporter_init(struct btd_adapter *adapter)
 
 void reporter_exit(struct btd_adapter *adapter)
 {
+	link_loss_unregister(adapter);
 	dbus_connection_unref(connection);
 }
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v8 5/6] proximity: immediate alert: implement immediate alert server
  2012-04-02 19:12 [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
                   ` (2 preceding siblings ...)
  2012-04-02 19:12 ` [PATCH v8 4/6] proximity: link loss: implement link loss server Arik Nemtsov
@ 2012-04-02 19:12 ` Arik Nemtsov
  2012-04-02 19:12 ` [PATCH v8 6/6] proximity: reporter: implement D-Bus API Arik Nemtsov
  2012-04-03 10:52 ` [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Johan Hedberg
  5 siblings, 0 replies; 7+ messages in thread
From: Arik Nemtsov @ 2012-04-02 19:12 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Arik Nemtsov

The profile is implemented in immalert.[ch]. A GATT service is
registered with a write callback on the immediate alert level attribute.
This attribute is write-only and is maintained per remote device.

When a remote device write a raises or lowers the alert level,
an appropriate PropertyChanged signal is emitted. When the alert level
of a device is non-zero, a callback is registered on its disconnection.
When the callback is called, the alert level of the device is reset to
zero and an appropriate signal is emitted.
---
 Makefile.am          |    3 +-
 proximity/immalert.c |  289 ++++++++++++++++++++++++++++++++++++++++++++++++++
 proximity/immalert.h |   26 +++++
 proximity/reporter.c |   42 +-------
 4 files changed, 320 insertions(+), 40 deletions(-)
 create mode 100644 proximity/immalert.c
 create mode 100644 proximity/immalert.h

diff --git a/Makefile.am b/Makefile.am
index 12b3d81..d475555 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -223,7 +223,8 @@ builtin_sources += thermometer/main.c \
             proximity/main.c proximity/manager.h proximity/manager.c \
 			proximity/monitor.h proximity/monitor.c \
 			proximity/reporter.h proximity/reporter.c \
-			proximity/linkloss.h proximity/linkloss.c
+			proximity/linkloss.h proximity/linkloss.c \
+			proximity/immalert.h proximity/immalert.c
 endif
 
 
diff --git a/proximity/immalert.c b/proximity/immalert.c
new file mode 100644
index 0000000..8e2e50b
--- /dev/null
+++ b/proximity/immalert.c
@@ -0,0 +1,289 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Texas Instruments Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <bluetooth/uuid.h>
+#include <adapter.h>
+
+#include <dbus/dbus.h>
+#include <gdbus.h>
+
+#include "log.h"
+#include "att.h"
+#include "att-database.h"
+#include "gattrib.h"
+#include "gatt-service.h"
+#include "attrib-server.h"
+#include "device.h"
+#include "attio.h"
+#include "dbus-common.h"
+#include "reporter.h"
+#include "immalert.h"
+
+struct imm_alert_adapter {
+	struct btd_adapter *adapter;
+	DBusConnection *conn;
+	GSList *connected_devices;
+};
+
+struct connected_device {
+	struct btd_device *device;
+	struct imm_alert_adapter *adapter;
+	uint8_t alert_level;
+	guint callback_id;
+};
+
+static GSList *imm_alert_adapters;
+
+static int imdevice_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct connected_device *condev = a;
+	const struct btd_device *device = b;
+
+	if (condev->device == device)
+		return 0;
+
+	return -1;
+}
+
+static struct connected_device *
+find_connected_device(struct imm_alert_adapter *ia, struct btd_device *device)
+{
+	GSList *l = g_slist_find_custom(ia->connected_devices, device,
+								imdevice_cmp);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
+
+static int imadapter_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct imm_alert_adapter *imadapter = a;
+	const struct btd_adapter *adapter = b;
+
+	if (imadapter->adapter == adapter)
+		return 0;
+
+	return -1;
+}
+
+static struct imm_alert_adapter *
+find_imm_alert_adapter(struct btd_adapter *adapter)
+{
+	GSList *l = g_slist_find_custom(imm_alert_adapters, adapter,
+								imadapter_cmp);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
+
+const char *imm_alert_get_level(struct btd_device *device)
+{
+	struct imm_alert_adapter *imadapter;
+	struct connected_device *condev;
+
+	if (!device)
+		return get_alert_level_string(NO_ALERT);
+
+	imadapter = find_imm_alert_adapter(device_get_adapter(device));
+	if (!imadapter)
+		return get_alert_level_string(NO_ALERT);
+
+	condev = find_connected_device(imadapter, device);
+	if (!condev)
+		return get_alert_level_string(NO_ALERT);
+
+	return get_alert_level_string(condev->alert_level);
+}
+
+static void imm_alert_emit_alert_signal(struct connected_device *condev,
+							uint8_t alert_level)
+{
+	struct imm_alert_adapter *adapter;
+	const char *path, *alert_level_str;
+
+	if (!condev)
+		return;
+
+	adapter = condev->adapter;
+	path = device_get_path(condev->device);
+	alert_level_str = get_alert_level_string(alert_level);
+
+	DBG("alert %s remote %s", alert_level_str, path);
+
+	emit_property_changed(adapter->conn, path,
+			PROXIMITY_REPORTER_INTERFACE, "ImmediateAlertLevel",
+			DBUS_TYPE_STRING, &alert_level_str);
+}
+
+static void imm_alert_remove_condev(struct connected_device *condev)
+{
+	struct imm_alert_adapter *ia;
+
+	if (!condev)
+		return;
+
+	ia = condev->adapter;
+
+	if (condev->callback_id && condev->device)
+		btd_device_remove_attio_callback(condev->device,
+							condev->callback_id);
+
+	if (condev->device)
+		btd_device_unref(condev->device);
+
+	ia->connected_devices = g_slist_remove(ia->connected_devices, condev);
+	g_free(condev);
+}
+
+/* condev can be NULL */
+static void imm_alert_disc_cb(gpointer user_data)
+{
+	struct connected_device *condev = user_data;
+
+	if (!condev)
+		return;
+
+	DBG("immediate alert remove device %p", condev->device);
+
+	imm_alert_emit_alert_signal(condev, NO_ALERT);
+	imm_alert_remove_condev(condev);
+}
+
+static uint8_t imm_alert_alert_lvl_write(struct attribute *a,
+				struct btd_device *device, gpointer user_data)
+{
+	uint8_t value;
+	struct imm_alert_adapter *ia = user_data;
+	struct connected_device *condev = NULL;
+
+	if (!device)
+		goto set_error;
+
+	condev = find_connected_device(ia, device);
+
+	if (a->len == 0) {
+		DBG("Illegal alert level length");
+		goto set_error;
+	}
+
+	value = a->data[0];
+	if (value != NO_ALERT && value != MILD_ALERT && value != HIGH_ALERT) {
+		DBG("Illegal alert value");
+		goto set_error;
+	}
+
+	/* Register a disconnect cb if the alert level is non-zero */
+	if (value != NO_ALERT && !condev) {
+		condev = g_new0(struct connected_device, 1);
+		condev->device = btd_device_ref(device);
+		condev->adapter = ia;
+		condev->callback_id = btd_device_add_attio_callback(device,
+					NULL, imm_alert_disc_cb, condev);
+		ia->connected_devices = g_slist_append(ia->connected_devices,
+								condev);
+		DBG("added connected dev %p", device);
+	}
+
+	if (value != NO_ALERT) {
+		condev->alert_level = value;
+		imm_alert_emit_alert_signal(condev, value);
+	}
+
+	/*
+	 * Emit NO_ALERT if the alert level was non-zero before. This is
+	 * guaranteed when there's a condev.
+	 */
+	if (value == NO_ALERT && condev)
+		imm_alert_disc_cb(condev);
+
+	DBG("alert level set to %d by device %p", value, device);
+	return 0;
+
+set_error:
+	error("Set immediate alert level for dev %p", device);
+	/* remove alerts by erroneous devices */
+	imm_alert_disc_cb(condev);
+	return ATT_ECODE_IO;
+}
+
+void imm_alert_register(struct btd_adapter *adapter, DBusConnection *conn)
+{
+	gboolean svc_added;
+	bt_uuid_t uuid;
+	struct imm_alert_adapter *imadapter;
+
+	bt_uuid16_create(&uuid, IMMEDIATE_ALERT_SVC_UUID);
+
+	imadapter = g_new0(struct imm_alert_adapter, 1);
+	imadapter->adapter = adapter;
+	imadapter->conn = dbus_connection_ref(conn);
+
+	imm_alert_adapters = g_slist_append(imm_alert_adapters, imadapter);
+
+	/* Immediate Alert Service */
+	svc_added = gatt_service_add(adapter,
+		GATT_PRIM_SVC_UUID, &uuid,
+		/* Alert level characteristic */
+		GATT_OPT_CHR_UUID, ALERT_LEVEL_CHR_UUID,
+		GATT_OPT_CHR_PROPS,
+			ATT_CHAR_PROPER_WRITE_WITHOUT_RESP,
+		GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
+			imm_alert_alert_lvl_write, imadapter,
+		GATT_OPT_INVALID);
+
+	if (!svc_added) {
+		imm_alert_unregister(adapter);
+		return;
+	}
+
+	DBG("Immediate Alert service added");
+}
+
+static void remove_condev_list_item(gpointer data, gpointer user_data)
+{
+	struct connected_device *condev = data;
+
+	imm_alert_remove_condev(condev);
+}
+
+void imm_alert_unregister(struct btd_adapter *adapter)
+{
+	struct imm_alert_adapter *imadapter;
+
+	imadapter = find_imm_alert_adapter(adapter);
+	if (!imadapter)
+		return;
+
+	g_slist_foreach(imadapter->connected_devices, remove_condev_list_item,
+									NULL);
+	dbus_connection_unref(imadapter->conn);
+
+	imm_alert_adapters = g_slist_remove(imm_alert_adapters, imadapter);
+	g_free(imadapter);
+}
diff --git a/proximity/immalert.h b/proximity/immalert.h
new file mode 100644
index 0000000..dd28eaa
--- /dev/null
+++ b/proximity/immalert.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Texas Instruments Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+void imm_alert_register(struct btd_adapter *adapter, DBusConnection *conn);
+void imm_alert_unregister(struct btd_adapter *adapter);
+const char *imm_alert_get_level(struct btd_device *device);
diff --git a/proximity/reporter.c b/proximity/reporter.c
index cc371f2..4768e5f 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -40,6 +40,7 @@
 #include "attrib-server.h"
 #include "reporter.h"
 #include "linkloss.h"
+#include "immalert.h"
 
 static DBusConnection *connection;
 
@@ -101,44 +102,6 @@ static void register_tx_power(struct btd_adapter *adapter)
 	g_assert(h - start_handle == svc_size);
 }
 
-static void register_immediate_alert(struct btd_adapter *adapter)
-{
-	uint16_t start_handle, h;
-	const int svc_size = 3;
-	uint8_t atval[256];
-	bt_uuid_t uuid;
-
-	bt_uuid16_create(&uuid, IMMEDIATE_ALERT_SVC_UUID);
-	start_handle = attrib_db_find_avail(adapter, &uuid, svc_size);
-	if (start_handle == 0) {
-		error("Not enough free handles to register service");
-		return;
-	}
-
-	DBG("start_handle=0x%04x", start_handle);
-
-	h = start_handle;
-
-	/* Primary service definition */
-	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
-	att_put_u16(IMMEDIATE_ALERT_SVC_UUID, &atval[0]);
-	attrib_db_add(adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
-
-	/* Alert level characteristic */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_WRITE_WITHOUT_RESP;
-	att_put_u16(h + 1, &atval[1]);
-	att_put_u16(ALERT_LEVEL_CHR_UUID, &atval[3]);
-	attrib_db_add(adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Alert level value */
-	bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID);
-	att_put_u8(NO_ALERT, &atval[0]);
-	attrib_db_add(adapter, h++, &uuid, ATT_NONE, ATT_NONE, atval, 1);
-
-	g_assert(h - start_handle == svc_size);
-}
-
 int reporter_init(struct btd_adapter *adapter)
 {
 	if (!main_opts.gatt_enabled) {
@@ -153,7 +116,7 @@ int reporter_init(struct btd_adapter *adapter)
 
 	link_loss_register(adapter, connection);
 	register_tx_power(adapter);
-	register_immediate_alert(adapter);
+	imm_alert_register(adapter, connection);
 
 	return 0;
 }
@@ -161,5 +124,6 @@ int reporter_init(struct btd_adapter *adapter)
 void reporter_exit(struct btd_adapter *adapter)
 {
 	link_loss_unregister(adapter);
+	imm_alert_unregister(adapter);
 	dbus_connection_unref(connection);
 }
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v8 6/6] proximity: reporter: implement D-Bus API
  2012-04-02 19:12 [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
                   ` (3 preceding siblings ...)
  2012-04-02 19:12 ` [PATCH v8 5/6] proximity: immediate alert: implement immediate alert server Arik Nemtsov
@ 2012-04-02 19:12 ` Arik Nemtsov
  2012-04-03 10:52 ` [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Johan Hedberg
  5 siblings, 0 replies; 7+ messages in thread
From: Arik Nemtsov @ 2012-04-02 19:12 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Arik Nemtsov

Use a device driver to track all GATT supporting devices and register
a D-Bus interface per remote device.

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 alert level values for
non-connected devices are "none".
---
 proximity/reporter.c |  191 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 183 insertions(+), 8 deletions(-)

diff --git a/proximity/reporter.c b/proximity/reporter.c
index 4768e5f..cb30da5 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 "att-database.h"
@@ -42,7 +48,39 @@
 #include "linkloss.h"
 #include "immalert.h"
 
-static DBusConnection *connection;
+#define BLUEZ_SERVICE "org.bluez"
+
+#define GATT_UUID     "00001801-0000-1000-8000-00805f9b34fb"
+
+struct reporter_adapter {
+	DBusConnection *conn;
+	struct btd_adapter *adapter;
+	GSList *devices;
+};
+
+static GSList *reporter_adapters;
+
+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;
+}
+
+static struct reporter_adapter *
+find_reporter_adapter(struct btd_adapter *adapter)
+{
+	GSList *l = g_slist_find_custom(reporter_adapters, adapter,
+								radapter_cmp);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
 
 const char *get_alert_level_string(uint8_t level)
 {
@@ -102,28 +140,165 @@ 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_alert_get_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);
+
+	DBG("unregister on device %s", path);
+
+	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 int reporter_device_probe(struct btd_device *device, GSList *uuids)
+{
+	struct reporter_adapter *radapter;
+	struct btd_adapter *adapter = device_get_adapter(device);
+
+	radapter = find_reporter_adapter(adapter);
+	if (!radapter)
+		return -1;
+
+	register_reporter_device(device, radapter);
+	return 0;
+}
+
+static void reporter_device_remove(struct btd_device *device)
+{
+	struct reporter_adapter *radapter;
+	struct btd_adapter *adapter = device_get_adapter(device);
+
+	radapter = find_reporter_adapter(adapter);
+	if (!radapter)
+		return;
+
+	unregister_reporter_device(device, radapter);
+}
+
+/* device driver for tracking remote GATT client devices */
+static struct btd_device_driver reporter_device_driver = {
+	.name = "Proximity GATT Reporter Device Tracker Driver",
+	.uuids = BTD_UUIDS(GATT_UUID),
+	.probe = reporter_device_probe,
+	.remove = reporter_device_remove,
+};
+
 int reporter_init(struct btd_adapter *adapter)
 {
+	struct reporter_adapter *radapter;
+	DBusConnection *conn;
+
 	if (!main_opts.gatt_enabled) {
 		DBG("GATT is disabled");
 		return -ENOTSUP;
 	}
 
-	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;
 
-	link_loss_register(adapter, connection);
+	radapter = g_new0(struct reporter_adapter, 1);
+	radapter->adapter = adapter;
+	radapter->conn = conn;
+
+	link_loss_register(adapter, radapter->conn);
 	register_tx_power(adapter);
-	imm_alert_register(adapter, connection);
+	imm_alert_register(adapter, radapter->conn);
+
+	btd_register_device_driver(&reporter_device_driver);
+
+	reporter_adapters = g_slist_prepend(reporter_adapters, radapter);
+	DBG("Proximity Reporter for adapter %p", adapter);
 
 	return 0;
 }
 
 void reporter_exit(struct btd_adapter *adapter)
 {
+	struct reporter_adapter *radapter = find_reporter_adapter(adapter);
+	if (!radapter)
+		return;
+
+	btd_unregister_device_driver(&reporter_device_driver);
+
+	g_slist_foreach(radapter->devices, unregister_reporter_device,
+								radapter);
+
 	link_loss_unregister(adapter);
 	imm_alert_unregister(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


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks
  2012-04-02 19:12 [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
                   ` (4 preceding siblings ...)
  2012-04-02 19:12 ` [PATCH v8 6/6] proximity: reporter: implement D-Bus API Arik Nemtsov
@ 2012-04-03 10:52 ` Johan Hedberg
  5 siblings, 0 replies; 7+ messages in thread
From: Johan Hedberg @ 2012-04-03 10:52 UTC (permalink / raw)
  To: Arik Nemtsov; +Cc: linux-bluetooth

Hi Arik,

On Mon, Apr 02, 2012, Arik Nemtsov wrote:
> This allows us to identify the remote device that made the ATT
> read/write.
> ---
>  attrib/att-database.h  |   43 +++++++++++++++++++++++++++++++++++++++++++
>  attrib/att.h           |   20 --------------------
>  attrib/gatt-service.c  |    1 +
>  plugins/gatt-example.c |    4 +++-
>  proximity/reporter.c   |    1 +
>  src/attrib-server.c    |   20 +++++++++++++++-----
>  time/server.c          |    7 +++++--
>  7 files changed, 68 insertions(+), 28 deletions(-)
>  create mode 100644 attrib/att-database.h

All patches in this set have been applied. Thanks.

Johan

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-04-03 10:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-02 19:12 [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
2012-04-02 19:12 ` [PATCH v8 2/6] proximity: reporter: save global D-Bus connection Arik Nemtsov
2012-04-02 19:12 ` [PATCH v8 3/6] proximity: reporter: move definitions to .h and add util function Arik Nemtsov
2012-04-02 19:12 ` [PATCH v8 4/6] proximity: link loss: implement link loss server Arik Nemtsov
2012-04-02 19:12 ` [PATCH v8 5/6] proximity: immediate alert: implement immediate alert server Arik Nemtsov
2012-04-02 19:12 ` [PATCH v8 6/6] proximity: reporter: implement D-Bus API Arik Nemtsov
2012-04-03 10:52 ` [PATCH v8 1/6] att: add remote btd_device to ATT read/write callbacks Johan Hedberg

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).