All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/6] Implement ProximityReporter profiles
@ 2012-03-19  8:58 Arik Nemtsov
  2012-03-19  8:58 ` [PATCH v4 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Arik Nemtsov @ 2012-03-19  8:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Arik Nemtsov

This patch-set implements the Link loss and Immediate Alert GATT
server profiles.

A few API calls are added/changed in preparation, the most notable of
which is the addition of the remote-device to each GATT read/write callback.

The new profiles are separated into their own files for clarity.

A ProximityReporter D-Bus interface is registered for each remote device.
Property queries and PropertyChanged notifications are implemented, in
accordance to doc/proximity-api.txt.

v3->4: More minor function renames

Arik Nemtsov (6):
  att: add remote btd_device to ATT read/write callbacks
  proximity: reporter: save global D-Bus connection
  proximity: reporter: move definitions to .h and add util function
  proximity: link loss: implement link loss server
  proximity: immediate alert: implement immediate alert server
  proximity: reporter: implement D-Bus API

 Makefile.am            |    4 +-
 attrib/att.h           |    6 +-
 plugins/gatt-example.c |    3 +-
 proximity/immalert.c   |  288 +++++++++++++++++++++++++++++++++++++++++
 proximity/immalert.h   |   26 ++++
 proximity/linkloss.c   |  336 ++++++++++++++++++++++++++++++++++++++++++++++++
 proximity/linkloss.h   |   26 ++++
 proximity/reporter.c   |  250 ++++++++++++++++++++++++++----------
 proximity/reporter.h   |   16 +++
 src/attrib-server.c    |   19 ++-
 time/server.c          |    6 +-
 11 files changed, 900 insertions(+), 80 deletions(-)
 create mode 100644 proximity/immalert.c
 create mode 100644 proximity/immalert.h
 create mode 100644 proximity/linkloss.c
 create mode 100644 proximity/linkloss.h

-- 
1.7.5.4


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

* [PATCH v4 1/6] att: add remote btd_device to ATT read/write callbacks
  2012-03-19  8:58 [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov
@ 2012-03-19  8:58 ` Arik Nemtsov
  2012-03-20 17:36   ` Johan Hedberg
  2012-03-19  8:58 ` [PATCH v4 2/6] proximity: reporter: save global D-Bus connection Arik Nemtsov
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 12+ messages in thread
From: Arik Nemtsov @ 2012-03-19  8:58 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.h           |    6 ++++--
 plugins/gatt-example.c |    3 ++-
 src/attrib-server.c    |   19 ++++++++++++++-----
 time/server.c          |    6 ++++--
 4 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/attrib/att.h b/attrib/att.h
index dc266f1..70f3d91 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -130,8 +130,10 @@ struct attribute {
 	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);
+	uint8_t (*read_cb)(struct attribute *a, gpointer user_data,
+				gpointer device);
+	uint8_t (*write_cb)(struct attribute *a, gpointer user_data,
+				gpointer device);
 	gpointer cb_user_data;
 	int len;
 	uint8_t *data;
diff --git a/plugins/gatt-example.c b/plugins/gatt-example.c
index f026761..ad5b844 100644
--- a/plugins/gatt-example.c
+++ b/plugins/gatt-example.c
@@ -92,7 +92,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, gpointer user_data,
+				  struct btd_device *device)
 {
 	struct btd_adapter *adapter = user_data;
 	uint8_t value;
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 5775861..e88eb1c 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -76,6 +76,7 @@ struct gatt_channel {
 	gboolean encrypted;
 	struct gatt_server *server;
 	guint cleanup_id;
+	struct btd_device *device;
 };
 
 struct group_elem {
@@ -112,6 +113,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 +456,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, a->cb_user_data,
+					    channel->device);
 
 		if (status) {
 			g_slist_free_full(groups, g_free);
@@ -541,7 +546,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, a->cb_user_data,
+					    channel->device);
 
 		if (status) {
 			g_slist_free(types);
@@ -753,7 +759,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, a->cb_user_data, channel->device);
 
 	if (status)
 		return enc_error_resp(ATT_OP_READ_REQ, handle, status, pdu,
@@ -796,7 +802,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, a->cb_user_data, channel->device);
 
 	if (status)
 		return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle, status,
@@ -833,7 +839,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, a->cb_user_data,
+					     channel->device);
 			if (status)
 				return enc_error_resp(ATT_OP_WRITE_REQ, handle,
 							status, pdu, len);
@@ -1067,6 +1074,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..4a2e168 100644
--- a/time/server.c
+++ b/time/server.c
@@ -78,7 +78,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, gpointer user_data,
+				 struct btd_device *device)
 {
 	uint8_t value[10];
 
@@ -91,7 +92,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, gpointer user_data,
+				    struct btd_device *device)
 {
 	uint8_t value[2];
 
-- 
1.7.5.4


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

* [PATCH v4 2/6] proximity: reporter: save global D-Bus connection
  2012-03-19  8:58 [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov
  2012-03-19  8:58 ` [PATCH v4 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
@ 2012-03-19  8:58 ` Arik Nemtsov
  2012-03-19  8:58 ` [PATCH v4 3/6] proximity: reporter: move definitions to .h and add util function Arik Nemtsov
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Arik Nemtsov @ 2012-03-19  8:58 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 9777574..f7744f5 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -29,6 +29,7 @@
 #include <glib.h>
 #include <bluetooth/uuid.h>
 #include <adapter.h>
+#include <errno.h>
 
 #include "log.h"
 
@@ -38,6 +39,7 @@
 #include "attrib-server.h"
 #include "reporter.h"
 
+static DBusConnection *connection;
 #define IMMEDIATE_ALERT_SVC_UUID	0x1802
 #define LINK_LOSS_SVC_UUID		0x1803
 #define TX_POWER_SVC_UUID		0x1804
@@ -177,6 +179,9 @@ int reporter_init(struct btd_adapter *adapter)
 		return -1;
 	}
 
+	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+	if (connection == NULL)
+		return -EIO;
 	DBG("Proximity Reporter for adapter %p", adapter);
 
 	register_link_loss(adapter);
@@ -188,4 +193,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] 12+ messages in thread

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

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

diff --git a/proximity/reporter.c b/proximity/reporter.c
index f7744f5..e9dbc9f 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -40,17 +40,20 @@
 #include "reporter.h"
 
 static DBusConnection *connection;
-#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,
-};
+
+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)
 {
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] 12+ messages in thread

* [PATCH v4 4/6] proximity: link loss: implement link loss server
  2012-03-19  8:58 [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov
                   ` (2 preceding siblings ...)
  2012-03-19  8:58 ` [PATCH v4 3/6] proximity: reporter: move definitions to .h and add util function Arik Nemtsov
@ 2012-03-19  8:58 ` Arik Nemtsov
  2012-03-19  8:58 ` [PATCH v4 5/6] proximity: immediate alert: implement immediate alert server Arik Nemtsov
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Arik Nemtsov @ 2012-03-19  8:58 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 |  336 ++++++++++++++++++++++++++++++++++++++++++++++++++
 proximity/linkloss.h |   26 ++++
 proximity/reporter.c |   42 +------
 4 files changed, 367 insertions(+), 40 deletions(-)
 create mode 100644 proximity/linkloss.c
 create mode 100644 proximity/linkloss.h

diff --git a/Makefile.am b/Makefile.am
index bd587eb..0a253af 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -204,7 +204,8 @@ builtin_modules += proximity
 builtin_sources += 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
 
 if SERVICEPLUGIN
diff --git a/proximity/linkloss.c b/proximity/linkloss.c
new file mode 100644
index 0000000..ffea03a
--- /dev/null
+++ b/proximity/linkloss.c
@@ -0,0 +1,336 @@
+/*
+ *
+ *  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 "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, gpointer user_data,
+					struct btd_device *device)
+{
+	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,
+		gpointer user_data, struct btd_device *device)
+{
+	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 e9dbc9f..d362849 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -38,6 +38,7 @@
 #include "gattrib.h"
 #include "attrib-server.h"
 #include "reporter.h"
+#include "linkloss.h"
 
 static DBusConnection *connection;
 
@@ -55,44 +56,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;
@@ -187,7 +150,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);
 
@@ -196,5 +159,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] 12+ messages in thread

* [PATCH v4 5/6] proximity: immediate alert: implement immediate alert server
  2012-03-19  8:58 [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov
                   ` (3 preceding siblings ...)
  2012-03-19  8:58 ` [PATCH v4 4/6] proximity: link loss: implement link loss server Arik Nemtsov
@ 2012-03-19  8:58 ` Arik Nemtsov
  2012-03-19  8:58 ` [PATCH v4 6/6] proximity: reporter: implement D-Bus API Arik Nemtsov
  2012-03-20 16:15 ` Fwd: [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov
  6 siblings, 0 replies; 12+ messages in thread
From: Arik Nemtsov @ 2012-03-19  8:58 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 |  288 ++++++++++++++++++++++++++++++++++++++++++++++++++
 proximity/immalert.h |   26 +++++
 proximity/reporter.c |   42 +-------
 4 files changed, 319 insertions(+), 40 deletions(-)
 create mode 100644 proximity/immalert.c
 create mode 100644 proximity/immalert.h

diff --git a/Makefile.am b/Makefile.am
index 0a253af..0295ce2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -205,7 +205,8 @@ builtin_sources += 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
 
 if SERVICEPLUGIN
diff --git a/proximity/immalert.c b/proximity/immalert.c
new file mode 100644
index 0000000..524376b
--- /dev/null
+++ b/proximity/immalert.c
@@ -0,0 +1,288 @@
+/*
+ *
+ *  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 "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,
+			gpointer user_data, struct btd_device *device)
+{
+	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 (!adapter)
+		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 d362849..e77a6ea 100644
--- a/proximity/reporter.c
+++ b/proximity/reporter.c
@@ -39,6 +39,7 @@
 #include "attrib-server.h"
 #include "reporter.h"
 #include "linkloss.h"
+#include "immalert.h"
 
 static DBusConnection *connection;
 
@@ -100,44 +101,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.attrib_server) {
@@ -152,7 +115,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;
 }
@@ -160,5 +123,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] 12+ messages in thread

* [PATCH v4 6/6] proximity: reporter: implement D-Bus API
  2012-03-19  8:58 [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov
                   ` (4 preceding siblings ...)
  2012-03-19  8:58 ` [PATCH v4 5/6] proximity: immediate alert: implement immediate alert server Arik Nemtsov
@ 2012-03-19  8:58 ` Arik Nemtsov
  2012-03-20 16:15 ` Fwd: [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov
  6 siblings, 0 replies; 12+ messages in thread
From: Arik Nemtsov @ 2012-03-19  8:58 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 e77a6ea..2c2aff0 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,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)
 {
@@ -101,28 +139,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.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;
+
+	radapter = g_new0(struct reporter_adapter, 1);
+	radapter->adapter = adapter;
+	radapter->conn = conn;
 
-	link_loss_register(adapter, connection);
+	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] 12+ messages in thread

* Fwd: [PATCH v4 0/6] Implement ProximityReporter profiles
  2012-03-19  8:58 [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov
                   ` (5 preceding siblings ...)
  2012-03-19  8:58 ` [PATCH v4 6/6] proximity: reporter: implement D-Bus API Arik Nemtsov
@ 2012-03-20 16:15 ` Arik Nemtsov
  6 siblings, 0 replies; 12+ messages in thread
From: Arik Nemtsov @ 2012-03-20 16:15 UTC (permalink / raw)
  To: Gustavo F. Padovan, Johan Hedberg; +Cc: Anderson Lizardo, linux-bluetooth

Johan, Gustavo,

It seems there are no further comments. Is this patch-set good to go?

Regards,
Arik

On Mon, Mar 19, 2012 at 10:58, Arik Nemtsov <arik@wizery.com> wrote:
> This patch-set implements the Link loss and Immediate Alert GATT
> server profiles.
>
> A few API calls are added/changed in preparation, the most notable of
> which is the addition of the remote-device to each GATT read/write callback.
>
> The new profiles are separated into their own files for clarity.
>
> A ProximityReporter D-Bus interface is registered for each remote device.
> Property queries and PropertyChanged notifications are implemented, in
> accordance to doc/proximity-api.txt.
>
> v3->4: More minor function renames
>
> Arik Nemtsov (6):
>  att: add remote btd_device to ATT read/write callbacks
>  proximity: reporter: save global D-Bus connection
>  proximity: reporter: move definitions to .h and add util function
>  proximity: link loss: implement link loss server
>  proximity: immediate alert: implement immediate alert server
>  proximity: reporter: implement D-Bus API
>
>  Makefile.am            |    4 +-
>  attrib/att.h           |    6 +-
>  plugins/gatt-example.c |    3 +-
>  proximity/immalert.c   |  288 +++++++++++++++++++++++++++++++++++++++++
>  proximity/immalert.h   |   26 ++++
>  proximity/linkloss.c   |  336 ++++++++++++++++++++++++++++++++++++++++++++++++
>  proximity/linkloss.h   |   26 ++++
>  proximity/reporter.c   |  250 ++++++++++++++++++++++++++----------
>  proximity/reporter.h   |   16 +++
>  src/attrib-server.c    |   19 ++-
>  time/server.c          |    6 +-
>  11 files changed, 900 insertions(+), 80 deletions(-)
>  create mode 100644 proximity/immalert.c
>  create mode 100644 proximity/immalert.h
>  create mode 100644 proximity/linkloss.c
>  create mode 100644 proximity/linkloss.h
>
> --
> 1.7.5.4
>

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

* Re: [PATCH v4 1/6] att: add remote btd_device to ATT read/write callbacks
  2012-03-19  8:58 ` [PATCH v4 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
@ 2012-03-20 17:36   ` Johan Hedberg
  2012-03-20 17:48     ` Arik Nemtsov
  0 siblings, 1 reply; 12+ messages in thread
From: Johan Hedberg @ 2012-03-20 17:36 UTC (permalink / raw)
  To: Arik Nemtsov; +Cc: linux-bluetooth

Hi Arik,

On Mon, Mar 19, 2012, Arik Nemtsov wrote:
> -	uint8_t (*read_cb)(struct attribute *a, gpointer user_data);
> -	uint8_t (*write_cb)(struct attribute *a, gpointer user_data);
> +	uint8_t (*read_cb)(struct attribute *a, gpointer user_data,
> +				gpointer device);
> +	uint8_t (*write_cb)(struct attribute *a, gpointer user_data,
> +				gpointer device);

Why is device a gpointer and not a struct btd_device *?

Also, user_data should be the last parameter as per GLib conventions.

Johan

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

* Re: [PATCH v4 1/6] att: add remote btd_device to ATT read/write callbacks
  2012-03-20 17:36   ` Johan Hedberg
@ 2012-03-20 17:48     ` Arik Nemtsov
  2012-03-21 12:43       ` Johan Hedberg
  0 siblings, 1 reply; 12+ messages in thread
From: Arik Nemtsov @ 2012-03-20 17:48 UTC (permalink / raw)
  To: linux-bluetooth, Johan Hedberg

On Tue, Mar 20, 2012 at 19:36, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Arik,
>
> On Mon, Mar 19, 2012, Arik Nemtsov wrote:
>> -     uint8_t (*read_cb)(struct attribute *a, gpointer user_data);
>> -     uint8_t (*write_cb)(struct attribute *a, gpointer user_data);
>> +     uint8_t (*read_cb)(struct attribute *a, gpointer user_data,
>> +                             gpointer device);
>> +     uint8_t (*write_cb)(struct attribute *a, gpointer user_data,
>> +                             gpointer device);
>
> Why is device a gpointer and not a struct btd_device *?

Well att.h is a self contained include file (also used in gatttool for
example). That means there would have to be at least a forward
declaration for btd_device.
If we go down that road, it gets tricky, since we depend on the
include order of att.h and device.h. This can maybe be solved with
ifdef tricks, but I thinking leaving att.h self contained is the
better option here.

Thoughts?

>
> Also, user_data should be the last parameter as per GLib conventions.

Sure. I can change this.

Arik

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

* Re: [PATCH v4 1/6] att: add remote btd_device to ATT read/write callbacks
  2012-03-20 17:48     ` Arik Nemtsov
@ 2012-03-21 12:43       ` Johan Hedberg
  2012-03-21 21:01         ` Arik Nemtsov
  0 siblings, 1 reply; 12+ messages in thread
From: Johan Hedberg @ 2012-03-21 12:43 UTC (permalink / raw)
  To: Arik Nemtsov; +Cc: linux-bluetooth

Hi Arik,

On Tue, Mar 20, 2012, Arik Nemtsov wrote:
> On Tue, Mar 20, 2012 at 19:36, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> > Hi Arik,
> >
> > On Mon, Mar 19, 2012, Arik Nemtsov wrote:
> >> -     uint8_t (*read_cb)(struct attribute *a, gpointer user_data);
> >> -     uint8_t (*write_cb)(struct attribute *a, gpointer user_data);
> >> +     uint8_t (*read_cb)(struct attribute *a, gpointer user_data,
> >> +                             gpointer device);
> >> +     uint8_t (*write_cb)(struct attribute *a, gpointer user_data,
> >> +                             gpointer device);
> >
> > Why is device a gpointer and not a struct btd_device *?
> 
> Well att.h is a self contained include file (also used in gatttool for
> example).

How then could any of these callbacks receive a pointer to btd_device
when used in gatttool? And if they're not used in gatttool it seems like
some refactoring may be in place here (i.e. there should be be a
library-like .h file and then something else for stuff which is bound to
bluetoothd-internal constructs (like btd_device).

> That means there would have to be at least a forward declaration for
> btd_device.  If we go down that road, it gets tricky, since we depend
> on the include order of att.h and device.h. This can maybe be solved
> with ifdef tricks, but I thinking leaving att.h self contained is the
> better option here.

In general we try to avoid double-include protections in internal .h
files. The convention is that .c files just have to include the
dependencies.

Johan

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

* Re: [PATCH v4 1/6] att: add remote btd_device to ATT read/write callbacks
  2012-03-21 12:43       ` Johan Hedberg
@ 2012-03-21 21:01         ` Arik Nemtsov
  0 siblings, 0 replies; 12+ messages in thread
From: Arik Nemtsov @ 2012-03-21 21:01 UTC (permalink / raw)
  To: Johan Hedberg, linux-bluetooth

Hey Johan,

On Wed, Mar 21, 2012 at 14:43, Johan Hedberg <johan.hedberg@gmail.com> wrote:
>> > On Mon, Mar 19, 2012, Arik Nemtsov wrote:
>> >> -     uint8_t (*read_cb)(struct attribute *a, gpointer user_data);
>> >> -     uint8_t (*write_cb)(struct attribute *a, gpointer user_data);
>> >> +     uint8_t (*read_cb)(struct attribute *a, gpointer user_data,
>> >> +                             gpointer device);
>> >> +     uint8_t (*write_cb)(struct attribute *a, gpointer user_data,
>> >> +                             gpointer device);
>> >
>> > Why is device a gpointer and not a struct btd_device *?
>>
>> Well att.h is a self contained include file (also used in gatttool for
>> example).
>
> How then could any of these callbacks receive a pointer to btd_device
> when used in gatttool? And if they're not used in gatttool it seems like
> some refactoring may be in place here (i.e. there should be be a
> library-like .h file and then something else for stuff which is bound to
> bluetoothd-internal constructs (like btd_device).

They are not used in gatttool. I guess you're right - we can move the
"struct attribute" definition to some other file, which will include
device.h. Any comments on naming?
How about attrib/att-bluez.h ?

>
>> That means there would have to be at least a forward declaration for
>> btd_device.  If we go down that road, it gets tricky, since we depend
>> on the include order of att.h and device.h. This can maybe be solved
>> with ifdef tricks, but I thinking leaving att.h self contained is the
>> better option here.
>
> In general we try to avoid double-include protections in internal .h
> files. The convention is that .c files just have to include the
> dependencies.

Ok.

Regards,
Arik

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

end of thread, other threads:[~2012-03-21 21:01 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-19  8:58 [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov
2012-03-19  8:58 ` [PATCH v4 1/6] att: add remote btd_device to ATT read/write callbacks Arik Nemtsov
2012-03-20 17:36   ` Johan Hedberg
2012-03-20 17:48     ` Arik Nemtsov
2012-03-21 12:43       ` Johan Hedberg
2012-03-21 21:01         ` Arik Nemtsov
2012-03-19  8:58 ` [PATCH v4 2/6] proximity: reporter: save global D-Bus connection Arik Nemtsov
2012-03-19  8:58 ` [PATCH v4 3/6] proximity: reporter: move definitions to .h and add util function Arik Nemtsov
2012-03-19  8:58 ` [PATCH v4 4/6] proximity: link loss: implement link loss server Arik Nemtsov
2012-03-19  8:58 ` [PATCH v4 5/6] proximity: immediate alert: implement immediate alert server Arik Nemtsov
2012-03-19  8:58 ` [PATCH v4 6/6] proximity: reporter: implement D-Bus API Arik Nemtsov
2012-03-20 16:15 ` Fwd: [PATCH v4 0/6] Implement ProximityReporter profiles Arik Nemtsov

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.