linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Health Thermometer Profile
@ 2011-10-20  9:46 Santiago Carot-Nemesio
  2011-10-20  9:46 ` [PATCH 1/8] Process characteristic descriptors in thermometer service Santiago Carot-Nemesio
  0 siblings, 1 reply; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-20  9:46 UTC (permalink / raw)
  To: linux-bluetooth

This set of patches enable applications to register watchers in order to
receive final measurements.

[PATCH 1/8] Process characteristic descriptors in thermometer service.
[PATCH 2/8] Get valid range descriptor if it is supported
[PATCH 3/8] Implement D-Bus register watcher function
[PATCH 4/8] Implement D-Bus unregister watcher function
[PATCH 5/8] Enable final measurement indications when first watcher
[PATCH 6/8] Disable final measurements indication when last watcher
[PATCH 7/8] Manage watcher's disconnections from the bus
[PATCH 8/8] Implement D-Bus get properties function

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

* [PATCH 1/8] Process characteristic descriptors in thermometer service.
  2011-10-20  9:46 Health Thermometer Profile Santiago Carot-Nemesio
@ 2011-10-20  9:46 ` Santiago Carot-Nemesio
  2011-10-20  9:46   ` [PATCH 2/8] Get valid range descriptor if it is supported Santiago Carot-Nemesio
  2011-10-20 11:11   ` [PATCH 1/8] Process characteristic descriptors in thermometer service Anderson Lizardo
  0 siblings, 2 replies; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-20  9:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   77 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 76 insertions(+), 1 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 0d85102..854a157 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -42,6 +42,7 @@
 
 #define THERMOMETER_INTERFACE "org.bluez.Thermometer"
 
+#define TEMPERATURE_MEASUREMENT_UUID	"00002a1c-0000-1000-8000-00805f9b34fb"
 #define TEMPERATURE_TYPE_UUID		"00002a1d-0000-1000-8000-00805f9b34fb"
 #define INTERMEDIATE_TEMPERATURE_UUID	"00002a1e-0000-1000-8000-00805f9b34fb"
 #define MEASUREMENT_INTERVAL_UUID	"00002a21-0000-1000-8000-00805f9b34fb"
@@ -161,10 +162,84 @@ static void change_property(struct thermometer *t, const gchar *name,
 		DBG("%s is not a thermometer property", name);
 }
 
+static void process_thermometer_desc(struct descriptor *desc)
+{
+	char uuidstr[MAX_LEN_UUID_STR];
+	bt_uuid_t btuuid;
+
+	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+
+	if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0) {
+		if (g_strcmp0(desc->ch->attr.uuid,
+					TEMPERATURE_MEASUREMENT_UUID) == 0) {
+			/* TODO: Check if we have to enable it */
+			DBG("C.C.C in Temperature Measurement");
+		} else if (g_strcmp0(desc->ch->attr.uuid,
+					INTERMEDIATE_TEMPERATURE_UUID) == 0) {
+			/* TODO: Check if we have to enable it */
+			DBG("C.C.C in Intermediate Temperature");
+		} else if (g_strcmp0(desc->ch->attr.uuid,
+					MEASUREMENT_INTERVAL_UUID) == 0) {
+			/* TODO: Enable indications */
+			DBG("C.C.C in Measurement Interval");
+		} else
+			goto end;
+
+		return;
+	}
+
+	bt_uuid16_create(&btuuid, GATT_CHARAC_VALID_RANGE_UUID);
+
+	if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0)
+		if (g_strcmp0(desc->ch->attr.uuid,
+					MEASUREMENT_INTERVAL_UUID) == 0) {
+			/* TODO: Process Measurement Interval */
+			return;
+		}
+
+end:
+	bt_uuid_to_string(&desc->uuid, uuidstr, MAX_LEN_UUID_STR);
+	DBG("Ignored descriptor %s in characteristic %s", uuidstr,
+							desc->ch->attr.uuid);
+}
+
 static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
 							gpointer user_data)
 {
-	/* TODO */
+	struct characteristic *ch = user_data;
+	struct att_data_list *list;
+	guint8 format;
+	int i;
+
+	if (status != 0) {
+		error("Discover all characteristic descriptors failed [%s]: %s",
+					ch->attr.uuid, att_ecode2str(status));
+		return;
+	}
+
+	list = dec_find_info_resp(pdu, len, &format);
+	if (list == NULL)
+		return;
+
+	for (i = 0; i < list->num; i++) {
+		struct descriptor *desc;
+		uint8_t *value;
+
+		value = list->data[i];
+		desc = g_new0(struct descriptor, 1);
+		desc->handle = att_get_u16(value);
+		desc->ch = ch;
+
+		if (format == 0x01)
+			desc->uuid = att_get_uuid16(&value[2]);
+		else
+			desc->uuid = att_get_uuid128(&value[2]);
+
+		ch->desc = g_slist_append(ch->desc, desc);
+		process_thermometer_desc(desc);
+	}
+
+	att_data_list_free(list);
 }
 
 static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
-- 
1.7.6.1


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

* [PATCH 2/8] Get valid range descriptor if it is supported
  2011-10-20  9:46 ` [PATCH 1/8] Process characteristic descriptors in thermometer service Santiago Carot-Nemesio
@ 2011-10-20  9:46   ` Santiago Carot-Nemesio
  2011-10-20  9:46     ` [PATCH 3/8] Implement D-Bus register watcher function Santiago Carot-Nemesio
  2011-10-20 11:07     ` [PATCH 2/8] Get valid range descriptor if it is supported Anderson Lizardo
  2011-10-20 11:11   ` [PATCH 1/8] Process characteristic descriptors in thermometer service Anderson Lizardo
  1 sibling, 2 replies; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-20  9:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   41 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 40 insertions(+), 1 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 854a157..343d72a 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -162,6 +162,44 @@ static void change_property(struct thermometer *t, const gchar *name,
 		DBG("%s is not a thermometer property", name);
 }
 
+static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
+							gpointer user_data)
+{
+	struct descriptor *desc = user_data;
+	uint8_t value[ATT_MAX_MTU];
+	uint16_t *p, max, min;
+	int vlen;
+
+	if (status != 0) {
+		DBG("Valid Range descriptor read failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	if (!dec_read_resp(pdu, len, value, &vlen)) {
+		DBG("Protocol error\n");
+		return;
+	}
+
+	if (vlen < 4) {
+		DBG("Invalid range received");
+		return;
+	}
+
+	p = (uint16_t *) value;
+	min = btohs(bt_get_unaligned(p));
+	p = (uint16_t *) &value[2];
+	max = btohs(bt_get_unaligned(p));
+
+	if (min == 0 || min > max) {
+		DBG("Invalid range");
+		return;
+	}
+
+	change_property(desc->ch->t, "Maximum", &max);
+	change_property(desc->ch->t, "Minimum", &min);
+}
+
 static void process_thermometer_desc(struct descriptor *desc)
 {
 	char uuidstr[MAX_LEN_UUID_STR];
@@ -193,7 +231,8 @@ static void process_thermometer_desc(struct descriptor *desc)
 	if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0)
 		if (g_strcmp0(desc->ch->attr.uuid,
 					MEASUREMENT_INTERVAL_UUID) == 0) {
-			/* TODO: Process Measurement Interval */
+			gatt_read_char(desc->ch->t->attrib, desc->handle, 0,
+						valid_range_desc_cb, desc);
 			return;
 		}
 
-- 
1.7.6.1


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

* [PATCH 3/8] Implement D-Bus register watcher function
  2011-10-20  9:46   ` [PATCH 2/8] Get valid range descriptor if it is supported Santiago Carot-Nemesio
@ 2011-10-20  9:46     ` Santiago Carot-Nemesio
  2011-10-20  9:46       ` [PATCH 4/8] Implement D-Bus unregister " Santiago Carot-Nemesio
  2011-10-20 11:07     ` [PATCH 2/8] Get valid range descriptor if it is supported Anderson Lizardo
  1 sibling, 1 reply; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-20  9:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   96 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 343d72a..05c6ef6 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -55,6 +55,7 @@ struct thermometer {
 	guint			attioid;	/* Att watcher id */
 	guint			attindid;	/* Att incications id */
 	GSList			*chars;		/* Characteristics */
+	GSList			*fwatchers;     /* Final measurements */
 	gboolean		intermediate;
 	guint8			type;
 	guint16			interval;
@@ -76,8 +77,27 @@ struct descriptor {
 	bt_uuid_t		uuid;
 };
 
+struct watcher {
+	struct thermometer	*t;
+	guint			id;
+	gchar			*srv;
+	gchar			*path;
+};
+
 static GSList *thermometers = NULL;
 
+static void destroy_watcher(gpointer user_data)
+{
+	struct watcher *watcher = user_data;
+
+	if (watcher->id > 0)
+		g_dbus_remove_watch(watcher->t->conn, watcher->id);
+
+	g_free(watcher->path);
+	g_free(watcher->srv);
+	g_free(watcher);
+}
+
 static void destroy_char(gpointer user_data)
 {
 	struct characteristic *c = user_data;
@@ -102,6 +122,9 @@ static void destroy_thermometer(gpointer user_data)
 	if (t->chars != NULL)
 		g_slist_free_full(t->chars, destroy_char);
 
+	if (t->fwatchers != NULL)
+		g_slist_free_full(t->fwatchers, destroy_watcher);
+
 	dbus_connection_unref(t->conn);
 	btd_device_unref(t->dev);
 	g_free(t->svc_range);
@@ -119,6 +142,19 @@ static gint cmp_device(gconstpointer a, gconstpointer b)
 	return -1;
 }
 
+static gint cmp_watcher(gconstpointer a, gconstpointer b)
+{
+	const struct watcher *watcher = a;
+	const struct watcher *match = b;
+	int ret;
+
+	ret = g_strcmp0(watcher->srv, match->srv);
+	if (ret != 0)
+		return ret;
+
+	return g_strcmp0(watcher->path, match->path);
+}
+
 static void change_property(struct thermometer *t, const gchar *name,
 							gpointer value) {
 	if (g_strcmp0(name, "Intermediate") == 0) {
@@ -413,12 +449,66 @@ static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
 						"Function not implemented.");
 }
 
+static void enable_final_measurement(struct thermometer *t)
+{
+	/* TODO: enable final measurements */
+}
+
+static void watcher_exit(DBusConnection *conn, void *user_data)
+{
+	/* TODO: Watcher disconnected */
+}
+
+static struct watcher *find_watcher(struct thermometer *t, const gchar *sender,
+							const gchar *path)
+{
+	struct watcher *match;
+	GSList *l;
+
+	match = g_new0(struct watcher, 1);
+	match->srv = g_strdup(sender);
+	match->path = g_strdup(path);
+
+	l = g_slist_find_custom(t->fwatchers, match, cmp_watcher);
+	destroy_watcher(match);
+
+	if (l != NULL)
+		return l->data;
+
+	return NULL;
+}
+
 static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
-	/* TODO: */
-	return g_dbus_create_error(msg, ERROR_INTERFACE ".ThermometerError",
-						"Function not implemented.");
+	const gchar *sender = dbus_message_get_sender(msg);
+	struct thermometer *t = data;
+	struct watcher *watcher;
+	gchar *path;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	watcher = find_watcher(t, sender, path);
+	if (watcher != NULL)
+		return btd_error_already_exists(msg);
+
+	DBG("Thermometer watcher %s registered", path);
+
+	watcher = g_new0(struct watcher, 1);
+	watcher->srv = g_strdup(sender);
+	watcher->path = g_strdup(path);
+	watcher->t = t;
+	watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit,
+						watcher, destroy_watcher);
+
+	if (g_slist_length(t->fwatchers) == 0)
+		enable_final_measurement(t);
+
+	t->fwatchers = g_slist_prepend(t->fwatchers, watcher);
+
+	return dbus_message_new_method_return(msg);
 }
 
 static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
-- 
1.7.6.1


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

* [PATCH 4/8] Implement D-Bus unregister watcher function
  2011-10-20  9:46     ` [PATCH 3/8] Implement D-Bus register watcher function Santiago Carot-Nemesio
@ 2011-10-20  9:46       ` Santiago Carot-Nemesio
  2011-10-20  9:46         ` [PATCH 5/8] Enable final measurement indications when first watcher is enabled Santiago Carot-Nemesio
  0 siblings, 1 reply; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-20  9:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   30 +++++++++++++++++++++++++++---
 1 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 05c6ef6..d6afe17 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -454,6 +454,11 @@ static void enable_final_measurement(struct thermometer *t)
 	/* TODO: enable final measurements */
 }
 
+static void disable_final_measurement(struct thermometer *t)
+{
+	/* TODO: disable final measurements */
+}
+
 static void watcher_exit(DBusConnection *conn, void *user_data)
 {
 	/* TODO: Watcher disconnected */
@@ -514,9 +519,28 @@ static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
 static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
-	/* TODO: */
-	return g_dbus_create_error(msg, ERROR_INTERFACE ".ThermometerError",
-						"Function not implemented.");
+	const gchar *sender = dbus_message_get_sender(msg);
+	struct thermometer *t = data;
+	struct watcher *watcher;
+	gchar *path;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	watcher = find_watcher(t, sender, path);
+	if (watcher == NULL)
+		return btd_error_does_not_exist(msg);
+
+	DBG("Thermometer watcher %s unregistered", path);
+
+	t->fwatchers = g_slist_remove(t->fwatchers, watcher);
+	destroy_watcher(watcher);
+
+	if (g_slist_length(t->fwatchers) == 0)
+		disable_final_measurement(t);
+
+	return dbus_message_new_method_return(msg);
 }
 
 static DBusMessage *enable_intermediate(DBusConnection *conn, DBusMessage *msg,
-- 
1.7.6.1


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

* [PATCH 5/8] Enable final measurement indications when first watcher is enabled
  2011-10-20  9:46       ` [PATCH 4/8] Implement D-Bus unregister " Santiago Carot-Nemesio
@ 2011-10-20  9:46         ` Santiago Carot-Nemesio
  2011-10-20  9:46           ` [PATCH 6/8] Disable final measurements indication when last watcher is removed Santiago Carot-Nemesio
  2011-10-20 11:18           ` [PATCH 5/8] Enable final measurement indications when first watcher is enabled Anderson Lizardo
  0 siblings, 2 replies; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-20  9:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   78 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 77 insertions(+), 1 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index d6afe17..4a03fc6 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -155,6 +155,22 @@ static gint cmp_watcher(gconstpointer a, gconstpointer b)
 	return g_strcmp0(watcher->path, match->path);
 }
 
+static gint cmp_char_uuid(gconstpointer a, gconstpointer b)
+{
+	const struct characteristic *ch = a;
+	const gchar *uuid = b;
+
+	return g_strcmp0(ch->attr.uuid, uuid);
+}
+
+static gint cmp_descriptor(gconstpointer a, gconstpointer b)
+{
+	const struct descriptor *desc = a;
+	const bt_uuid_t *uuid = b;
+
+	return bt_uuid_cmp(&desc->uuid, uuid);
+}
+
 static void change_property(struct thermometer *t, const gchar *name,
 							gpointer value) {
 	if (g_strcmp0(name, "Intermediate") == 0) {
@@ -449,9 +465,69 @@ static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
 						"Function not implemented.");
 }
 
+static struct characteristic *get_characteristic(struct thermometer *t,
+							const gchar *uuid)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(t->chars, uuid, cmp_char_uuid);
+	if (l == NULL)
+		return NULL;
+
+	return l->data;
+}
+
+static struct descriptor *get_descriptor(struct characteristic *ch,
+							const bt_uuid_t *uuid)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(ch->desc, uuid, cmp_descriptor);
+	if (l == NULL)
+		return NULL;
+
+	return l->data;
+}
+
+static void final_measurement_cb (guint8 status, const guint8 *pdu,
+						guint16 len, gpointer user_data)
+{
+	gchar *msg = user_data;
+
+	if (status != 0) {
+		error("%s failed", msg);
+		return;
+	}
+
+	g_free(msg);
+}
+
 static void enable_final_measurement(struct thermometer *t)
 {
-	/* TODO: enable final measurements */
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	gchar *msg;
+
+	ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
+	if (ch == NULL) {
+		DBG("Temperature measurement characteristic not found");
+		return;
+	}
+
+	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+	desc = get_descriptor(ch, &btuuid);
+	if (desc == NULL) {
+		DBG("Client characteristic configuration descriptor not found");
+		return;
+	}
+
+	atval[0] = 0x02;
+	atval[1] = 0x00;
+	msg = g_strdup("Enable final measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2,
+						final_measurement_cb, msg);
 }
 
 static void disable_final_measurement(struct thermometer *t)
-- 
1.7.6.1


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

* [PATCH 6/8] Disable final measurements indication when last watcher is removed
  2011-10-20  9:46         ` [PATCH 5/8] Enable final measurement indications when first watcher is enabled Santiago Carot-Nemesio
@ 2011-10-20  9:46           ` Santiago Carot-Nemesio
  2011-10-20  9:46             ` [PATCH 7/8] Manage watcher's disconnections from the bus Santiago Carot-Nemesio
  2011-10-20 11:18           ` [PATCH 5/8] Enable final measurement indications when first watcher is enabled Anderson Lizardo
  1 sibling, 1 reply; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-20  9:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   25 ++++++++++++++++++++++++-
 1 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 4a03fc6..9b14e6f 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -532,7 +532,30 @@ static void enable_final_measurement(struct thermometer *t)
 
 static void disable_final_measurement(struct thermometer *t)
 {
-	/* TODO: disable final measurements */
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	gchar *msg;
+
+	ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
+	if (ch == NULL) {
+		DBG("Temperature measurement characteristic not found");
+		return;
+	}
+
+	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+	desc = get_descriptor(ch, &btuuid);
+	if (desc == NULL) {
+		DBG("Client characteristic configuration descriptor not found");
+		return;
+	}
+
+	atval[0] = 0x00;
+	atval[1] = 0x00;
+	msg = g_strdup("Disable final measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2,
+						final_measurement_cb, msg);
 }
 
 static void watcher_exit(DBusConnection *conn, void *user_data)
-- 
1.7.6.1


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

* [PATCH 7/8] Manage watcher's disconnections from the bus
  2011-10-20  9:46           ` [PATCH 6/8] Disable final measurements indication when last watcher is removed Santiago Carot-Nemesio
@ 2011-10-20  9:46             ` Santiago Carot-Nemesio
  2011-10-20  9:46               ` [PATCH 8/8] Implement D-Bus get properties function Santiago Carot-Nemesio
  0 siblings, 1 reply; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-20  9:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 9b14e6f..4a2b9c8 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -560,7 +560,16 @@ static void disable_final_measurement(struct thermometer *t)
 
 static void watcher_exit(DBusConnection *conn, void *user_data)
 {
-	/* TODO: Watcher disconnected */
+	struct watcher *watcher = user_data;
+	struct thermometer *t = watcher->t;
+
+	DBG("Thermometer watcher %s disconnected", watcher->path);
+
+	t->fwatchers = g_slist_remove(t->fwatchers, watcher);
+	watcher->id = 0;
+
+	if (g_slist_length(t->fwatchers) == 0)
+		disable_final_measurement(t);
 }
 
 static struct watcher *find_watcher(struct thermometer *t, const gchar *sender,
-- 
1.7.6.1


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

* [PATCH 8/8] Implement D-Bus get properties function
  2011-10-20  9:46             ` [PATCH 7/8] Manage watcher's disconnections from the bus Santiago Carot-Nemesio
@ 2011-10-20  9:46               ` Santiago Carot-Nemesio
  0 siblings, 0 replies; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-20  9:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   32 +++++++++++++++++++++++++++++---
 1 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 4a2b9c8..99bfe43 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -452,9 +452,35 @@ static void configure_thermometer_cb(GSList *characteristics, guint8 status,
 static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
-	/* TODO: */
-	return g_dbus_create_error(msg, ERROR_INTERFACE ".ThermometerError",
-						"Function not implemented.");
+	struct thermometer *t = data;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	DBusMessage *reply;
+
+	reply = dbus_message_new_method_return(msg);
+	if (reply == NULL)
+		return NULL;
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	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);
+
+	dict_append_entry(&dict, "Intermediate", DBUS_TYPE_BOOLEAN,
+							&t->intermediate);
+
+	if (t->has_interval) {
+		dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT16,
+								&t->interval);
+		dict_append_entry(&dict, "Maximum", DBUS_TYPE_UINT16, &t->max);
+		dict_append_entry(&dict, "Minimum", DBUS_TYPE_UINT16, &t->min);
+	}
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	return reply;
 }
 
 static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
-- 
1.7.6.1


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

* Re: [PATCH 2/8] Get valid range descriptor if it is supported
  2011-10-20  9:46   ` [PATCH 2/8] Get valid range descriptor if it is supported Santiago Carot-Nemesio
  2011-10-20  9:46     ` [PATCH 3/8] Implement D-Bus register watcher function Santiago Carot-Nemesio
@ 2011-10-20 11:07     ` Anderson Lizardo
  1 sibling, 0 replies; 14+ messages in thread
From: Anderson Lizardo @ 2011-10-20 11:07 UTC (permalink / raw)
  To: Santiago Carot-Nemesio; +Cc: linux-bluetooth

Hi Santiago,

On Thu, Oct 20, 2011 at 6:46 AM, Santiago Carot-Nemesio
<sancane@gmail.com> wrote:
> +       p = (uint16_t *) value;
> +       min = btohs(bt_get_unaligned(p));
> +       p = (uint16_t *) &value[2];
> +       max = btohs(bt_get_unaligned(p));

Why not use att_get_u16() here? it does exactly what you want (and no
casting is necessary).

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

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

* Re: [PATCH 1/8] Process characteristic descriptors in thermometer service.
  2011-10-20  9:46 ` [PATCH 1/8] Process characteristic descriptors in thermometer service Santiago Carot-Nemesio
  2011-10-20  9:46   ` [PATCH 2/8] Get valid range descriptor if it is supported Santiago Carot-Nemesio
@ 2011-10-20 11:11   ` Anderson Lizardo
  1 sibling, 0 replies; 14+ messages in thread
From: Anderson Lizardo @ 2011-10-20 11:11 UTC (permalink / raw)
  To: Santiago Carot-Nemesio; +Cc: linux-bluetooth

Hi Santiago,

On Thu, Oct 20, 2011 at 6:46 AM, Santiago Carot-Nemesio
<sancane@gmail.com> wrote:
> +               } else
> +                       goto end;

We usually call this label "done".

> +
> +               return;
> +       }
> +
> +       bt_uuid16_create(&btuuid, GATT_CHARAC_VALID_RANGE_UUID);
> +
> +       if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0)
> +               if (g_strcmp0(desc->ch->attr.uuid,
> +                                       MEASUREMENT_INTERVAL_UUID) == 0) {

You can join these nested if()'s in a single one and use &&.

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

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

* Re: [PATCH 5/8] Enable final measurement indications when first watcher is enabled
  2011-10-20  9:46         ` [PATCH 5/8] Enable final measurement indications when first watcher is enabled Santiago Carot-Nemesio
  2011-10-20  9:46           ` [PATCH 6/8] Disable final measurements indication when last watcher is removed Santiago Carot-Nemesio
@ 2011-10-20 11:18           ` Anderson Lizardo
  2011-10-20 12:54             ` Santiago Carot
  1 sibling, 1 reply; 14+ messages in thread
From: Anderson Lizardo @ 2011-10-20 11:18 UTC (permalink / raw)
  To: Santiago Carot-Nemesio; +Cc: linux-bluetooth

Hi Santiago,

On Thu, Oct 20, 2011 at 6:46 AM, Santiago Carot-Nemesio
<sancane@gmail.com> wrote:
> +static void final_measurement_cb (guint8 status, const guint8 *pdu,
> +                                               guint16 len, gpointer user_data)

There should be no space before "(" in function definitions/declarations.

> +{
> +       gchar *msg = user_data;
> +
> +       if (status != 0) {
> +               error("%s failed", msg);

You don't need to g_free(msg) in case of error?

> +               return;
> +       }
> +
> +       g_free(msg);
> +}
> +

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

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

* Re: [PATCH 5/8] Enable final measurement indications when first watcher is enabled
  2011-10-20 11:18           ` [PATCH 5/8] Enable final measurement indications when first watcher is enabled Anderson Lizardo
@ 2011-10-20 12:54             ` Santiago Carot
  0 siblings, 0 replies; 14+ messages in thread
From: Santiago Carot @ 2011-10-20 12:54 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth

Hi Anderson,

2011/10/20 Anderson Lizardo <anderson.lizardo@openbossa.org>:
> Hi Santiago,
>
> On Thu, Oct 20, 2011 at 6:46 AM, Santiago Carot-Nemesio
> <sancane@gmail.com> wrote:
>> +static void final_measurement_cb (guint8 status, const guint8 *pdu,
>> +                                               guint16 len, gpointer user_data)
>
> There should be no space before "(" in function definitions/declarations.
>
>> +{
>> +       gchar *msg = user_data;
>> +
>> +       if (status != 0) {
>> +               error("%s failed", msg);
>
> You don't need to g_free(msg) in case of error?

Yes I do, good catch!, I'll work in a new set of patches.
Thank for your comments.

>
>> +               return;
>> +       }
>> +
>> +       g_free(msg);
>> +}
>> +
>
> Regards,
> --
> Anderson Lizardo
> Instituto Nokia de Tecnologia - INdT
> Manaus - Brazil
>

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

* [PATCH 5/8] Enable final measurement indications when first watcher is enabled
  2011-10-24 17:04       ` [PATCH 4/8] Implement D-Bus unregister " Santiago Carot-Nemesio
@ 2011-10-24 17:04         ` Santiago Carot-Nemesio
  0 siblings, 0 replies; 14+ messages in thread
From: Santiago Carot-Nemesio @ 2011-10-24 17:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   76 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 75 insertions(+), 1 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 6ff5da3..acb7747 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -150,6 +150,22 @@ static gint cmp_watcher(gconstpointer a, gconstpointer b)
 	return g_strcmp0(watcher->path, match->path);
 }
 
+static gint cmp_char_uuid(gconstpointer a, gconstpointer b)
+{
+	const struct characteristic *ch = a;
+	const gchar *uuid = b;
+
+	return g_strcmp0(ch->attr.uuid, uuid);
+}
+
+static gint cmp_descriptor(gconstpointer a, gconstpointer b)
+{
+	const struct descriptor *desc = a;
+	const bt_uuid_t *uuid = b;
+
+	return bt_uuid_cmp(&desc->uuid, uuid);
+}
+
 static void change_property(struct thermometer *t, const gchar *name,
 							gpointer value) {
 	if (g_strcmp0(name, "Intermediate") == 0) {
@@ -446,9 +462,67 @@ static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
 						"Function not implemented.");
 }
 
+static struct characteristic *get_characteristic(struct thermometer *t,
+							const gchar *uuid)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(t->chars, uuid, cmp_char_uuid);
+	if (l == NULL)
+		return NULL;
+
+	return l->data;
+}
+
+static struct descriptor *get_descriptor(struct characteristic *ch,
+							const bt_uuid_t *uuid)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(ch->desc, uuid, cmp_descriptor);
+	if (l == NULL)
+		return NULL;
+
+	return l->data;
+}
+
+static void final_measurement_cb(guint8 status, const guint8 *pdu,
+						guint16 len, gpointer user_data)
+{
+	gchar *msg = user_data;
+
+	if (status != 0)
+		error("%s failed", msg);
+
+	g_free(msg);
+}
+
 static void enable_final_measurement(struct thermometer *t)
 {
-	/* TODO: enable final measurements */
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	gchar *msg;
+
+	ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
+	if (ch == NULL) {
+		DBG("Temperature measurement characteristic not found");
+		return;
+	}
+
+	bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+	desc = get_descriptor(ch, &btuuid);
+	if (desc == NULL) {
+		DBG("Client characteristic configuration descriptor not found");
+		return;
+	}
+
+	atval[0] = 0x02;
+	atval[1] = 0x00;
+	msg = g_strdup("Enable final measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2,
+						final_measurement_cb, msg);
 }
 
 static void disable_final_measurement(struct thermometer *t)
-- 
1.7.6.1


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

end of thread, other threads:[~2011-10-24 17:04 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-20  9:46 Health Thermometer Profile Santiago Carot-Nemesio
2011-10-20  9:46 ` [PATCH 1/8] Process characteristic descriptors in thermometer service Santiago Carot-Nemesio
2011-10-20  9:46   ` [PATCH 2/8] Get valid range descriptor if it is supported Santiago Carot-Nemesio
2011-10-20  9:46     ` [PATCH 3/8] Implement D-Bus register watcher function Santiago Carot-Nemesio
2011-10-20  9:46       ` [PATCH 4/8] Implement D-Bus unregister " Santiago Carot-Nemesio
2011-10-20  9:46         ` [PATCH 5/8] Enable final measurement indications when first watcher is enabled Santiago Carot-Nemesio
2011-10-20  9:46           ` [PATCH 6/8] Disable final measurements indication when last watcher is removed Santiago Carot-Nemesio
2011-10-20  9:46             ` [PATCH 7/8] Manage watcher's disconnections from the bus Santiago Carot-Nemesio
2011-10-20  9:46               ` [PATCH 8/8] Implement D-Bus get properties function Santiago Carot-Nemesio
2011-10-20 11:18           ` [PATCH 5/8] Enable final measurement indications when first watcher is enabled Anderson Lizardo
2011-10-20 12:54             ` Santiago Carot
2011-10-20 11:07     ` [PATCH 2/8] Get valid range descriptor if it is supported Anderson Lizardo
2011-10-20 11:11   ` [PATCH 1/8] Process characteristic descriptors in thermometer service Anderson Lizardo
  -- strict thread matches above, loose matches on Subject: below --
2011-10-24 17:04 Health Thermometer Profile Santiago Carot-Nemesio
2011-10-24 17:04 ` [PATCH 1/8] Process characteristic descriptors in the thermometer service Santiago Carot-Nemesio
2011-10-24 17:04   ` [PATCH 2/8] Get valid range descriptor if it is supported Santiago Carot-Nemesio
2011-10-24 17:04     ` [PATCH 3/8] Implement D-Bus register watcher function Santiago Carot-Nemesio
2011-10-24 17:04       ` [PATCH 4/8] Implement D-Bus unregister " Santiago Carot-Nemesio
2011-10-24 17:04         ` [PATCH 5/8] Enable final measurement indications when first watcher is enabled Santiago Carot-Nemesio

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