linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 4/6] Implement EnableIntermediateMeasurement D-Bus method
  2011-11-09 10:52     ` [PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default policy Santiago Carot-Nemesio
@ 2011-11-09 10:52       ` Santiago Carot-Nemesio
  0 siblings, 0 replies; 11+ messages in thread
From: Santiago Carot-Nemesio @ 2011-11-09 10:52 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   74 +++++++++++++++++++++++++++++++++++++-------
 1 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 3a82e20..2472f1e 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -63,6 +63,7 @@ struct thermometer {
 	guint			attindid;	/* Att incications id */
 	GSList			*chars;		/* Characteristics */
 	GSList			*fwatchers;     /* Final measurements */
+	GSList			*iwatchers;     /* Intermediate measurements */
 	gboolean		intermediate;
 	guint8			type;
 	guint16			interval;
@@ -557,7 +558,7 @@ static struct descriptor *get_descriptor(struct characteristic *ch,
 	return l->data;
 }
 
-static void final_measurement_cb(guint8 status, const guint8 *pdu,
+static void measurement_cb(guint8 status, const guint8 *pdu,
 						guint16 len, gpointer user_data)
 {
 	gchar *msg = user_data;
@@ -592,8 +593,34 @@ static void enable_final_measurement(struct thermometer *t)
 	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);
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void enable_intermediate_measurement(struct thermometer *t)
+{
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	gchar *msg;
+
+	ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
+	if (ch == NULL) {
+		DBG("Intermediate 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] = 0x01;
+	atval[1] = 0x00;
+	msg = g_strdup("Enable intermediate measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
 }
 
 static void disable_final_measurement(struct thermometer *t)
@@ -620,8 +647,7 @@ static void disable_final_measurement(struct thermometer *t)
 	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);
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
 }
 
 static void watcher_exit(DBusConnection *conn, void *user_data)
@@ -638,7 +664,7 @@ static void watcher_exit(DBusConnection *conn, void *user_data)
 		disable_final_measurement(t);
 }
 
-static struct watcher *find_watcher(struct thermometer *t, const gchar *sender,
+static struct watcher *find_watcher(GSList *list, const gchar *sender,
 							const gchar *path)
 {
 	struct watcher *match;
@@ -648,7 +674,7 @@ static struct watcher *find_watcher(struct thermometer *t, const gchar *sender,
 	match->srv = g_strdup(sender);
 	match->path = g_strdup(path);
 
-	l = g_slist_find_custom(t->fwatchers, match, cmp_watcher);
+	l = g_slist_find_custom(list, match, cmp_watcher);
 	destroy_watcher(match);
 
 	if (l != NULL)
@@ -669,7 +695,7 @@ static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
 							DBUS_TYPE_INVALID))
 		return btd_error_invalid_args(msg);
 
-	watcher = find_watcher(t, sender, path);
+	watcher = find_watcher(t->fwatchers, sender, path);
 	if (watcher != NULL)
 		return btd_error_already_exists(msg);
 
@@ -702,7 +728,7 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
 							DBUS_TYPE_INVALID))
 		return btd_error_invalid_args(msg);
 
-	watcher = find_watcher(t, sender, path);
+	watcher = find_watcher(t->fwatchers, sender, path);
 	if (watcher == NULL)
 		return btd_error_does_not_exist(msg);
 
@@ -720,9 +746,33 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
 static DBusMessage *enable_intermediate(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 (!t->intermediate)
+		return btd_error_not_supported(msg);
+
+	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->fwatchers, sender, path);
+	if (watcher == NULL)
+		return btd_error_does_not_exist(msg);
+
+	if (find_watcher(t->iwatchers, sender, path))
+		return btd_error_already_exists(msg);
+
+	DBG("Intermediate measurement watcher %s registered", path);
+
+	if (g_slist_length(t->iwatchers) == 0)
+		enable_intermediate_measurement(t);
+
+	t->iwatchers = g_slist_prepend(t->iwatchers, watcher);
+
+	return dbus_message_new_method_return(msg);
 }
 
 static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
-- 
1.7.7.2


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

* Health Thermometer Profile (HTP)
@ 2011-11-10 11:36 Santiago Carot-Nemesio
  2011-11-10 11:36 ` [PATCH 1/6] Manage GATT attribute indications in handle callback Santiago Carot-Nemesio
  0 siblings, 1 reply; 11+ messages in thread
From: Santiago Carot-Nemesio @ 2011-11-10 11:36 UTC (permalink / raw)
  To: linux-bluetooth

This is a new set of patches to enhance thermometer plugin fuctionality.
These patches enable watchers to receiave final/intermediate measurements
from thermometers devices. They also includes latest changes suggested
in the list.

[PATCH 1/6] Manage GATT attribute indications in handle callback.
[PATCH 2/6] Parse final measurement indication
[PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default
[PATCH 4/6] Implement EnableIntermediateMeasurement D-Bus method
[PATCH 5/6] Implement DisableIntermediateMeasurement D-Bus method
[PATCH 6/6] Notify intermediate measurements

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

* [PATCH 1/6] Manage GATT attribute indications in handle callback.
  2011-11-10 11:36 Health Thermometer Profile (HTP) Santiago Carot-Nemesio
@ 2011-11-10 11:36 ` Santiago Carot-Nemesio
  2011-11-10 11:36   ` [PATCH 2/6] Parse final measurement indication Santiago Carot-Nemesio
  0 siblings, 1 reply; 11+ messages in thread
From: Santiago Carot-Nemesio @ 2011-11-10 11:36 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   51 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 50 insertions(+), 1 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 5b0e30a..69ae708 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -163,6 +163,14 @@ static gint cmp_char_uuid(gconstpointer a, gconstpointer b)
 	return g_strcmp0(ch->attr.uuid, uuid);
 }
 
+static gint cmp_char_val_handle(gconstpointer a, gconstpointer b)
+{
+	const struct characteristic *ch = a;
+	const uint16_t *handle = b;
+
+	return ch->attr.value_handle - *handle;
+}
+
 static gint cmp_descriptor(gconstpointer a, gconstpointer b)
 {
 	const struct descriptor *desc = a;
@@ -703,9 +711,50 @@ static GDBusSignalTable thermometer_signals[] = {
 	{ }
 };
 
+static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
+						uint16_t len, gboolean final)
+{
+	DBG("TODO: Process measurement indication");
+}
+
+static void proc_measurement_interval(struct thermometer *t, const uint8_t *pdu,
+								uint16_t len)
+{
+	DBG("TODO: Process measurements interval indication");
+}
+
 static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 {
-	/* TODO: Process indication */
+	struct thermometer *t = user_data;
+	const struct characteristic *ch;
+	uint8_t opdu[ATT_MAX_MTU];
+	uint16_t handle, olen;
+	GSList *l;
+
+	if (len < 3) {
+		DBG("Bad pdu received");
+		return;
+	}
+
+	handle = att_get_u16(&pdu[1]);
+	l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
+	if (l == NULL) {
+		DBG("Unexpected handle: 0x%04x", handle);
+		return;
+	}
+
+	ch = l->data;
+
+	if (g_strcmp0(ch->attr.uuid, TEMPERATURE_MEASUREMENT_UUID) == 0)
+		proc_measurement(t, pdu, len, TRUE);
+	else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
+		proc_measurement_interval(t, pdu, len);
+
+	olen = enc_confirmation(opdu, sizeof(opdu));
+
+	if (olen > 0)
+		g_attrib_send(t->attrib, 0, opdu[0], opdu, olen, NULL, NULL,
+									NULL);
 }
 
 static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
-- 
1.7.7.3


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

* [PATCH 2/6] Parse final measurement indication
  2011-11-10 11:36 ` [PATCH 1/6] Manage GATT attribute indications in handle callback Santiago Carot-Nemesio
@ 2011-11-10 11:36   ` Santiago Carot-Nemesio
  2011-11-10 11:36     ` [PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default policy Santiago Carot-Nemesio
  2011-11-12 18:37     ` [PATCH 2/6] Parse final measurement indication Johan Hedberg
  0 siblings, 2 replies; 11+ messages in thread
From: Santiago Carot-Nemesio @ 2011-11-10 11:36 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |  153 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 152 insertions(+), 1 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 69ae708..616c21d 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -47,6 +47,13 @@
 #define INTERMEDIATE_TEMPERATURE_UUID	"00002a1e-0000-1000-8000-00805f9b34fb"
 #define MEASUREMENT_INTERVAL_UUID	"00002a21-0000-1000-8000-00805f9b34fb"
 
+/* Temperature measurement flag fields */
+#define TEMP_UNITS		0x01
+#define TEMP_TIME_STAMP		0x02
+#define TEMP_TYPE		0x04
+
+#define FLOAT_MAX_MANTISSA	16777216 /* 2^24 */
+
 struct thermometer {
 	DBusConnection		*conn;		/* The connection to the bus */
 	struct btd_device	*dev;		/* Device reference */
@@ -84,8 +91,36 @@ struct watcher {
 	gchar			*path;
 };
 
+struct measurement {
+	gint16		exp;
+	gint32		mant;
+	guint64		time;
+	gboolean	suptime;
+	gchar		*unit;
+	gchar		*type;
+	gchar		*msmnt;
+};
+
 static GSList *thermometers = NULL;
 
+static gchar *temptype2str(uint8_t value)
+{
+	switch (value) {
+	case 1: return "Armpit";
+	case 2: return "Body";
+	case 3: return "Ear";
+	case 4: return "Finger";
+	case 5: return "Intestines";
+	case 6: return "Mouth";
+	case 7: return "Rectum";
+	case 8: return "Toe";
+	case 9: return "Tympanum";
+	default:
+		error("Temperature type %d reserved for future use", value);
+		return NULL;
+	};
+}
+
 static void destroy_watcher(gpointer user_data)
 {
 	struct watcher *watcher = user_data;
@@ -711,10 +746,126 @@ static GDBusSignalTable thermometer_signals[] = {
 	{ }
 };
 
+static void update_watcher(gpointer data, gpointer user_data)
+{
+	struct watcher *w = data;
+	struct measurement *m = user_data;
+	DBusConnection *conn = w->t->conn;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call(w->srv, w->path,
+				"org.bluez.ThermometerWatcher",
+				"MeasurementReceived");
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &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, "Exponent", DBUS_TYPE_INT16, &m->exp);
+	dict_append_entry(&dict, "Mantissa", DBUS_TYPE_INT32, &m->mant);
+	dict_append_entry(&dict, "Unit", DBUS_TYPE_STRING, &m->unit);
+
+	if (m->suptime)
+		dict_append_entry(&dict, "Time", DBUS_TYPE_UINT64, &m->time);
+
+	dict_append_entry(&dict, "Type", DBUS_TYPE_STRING, &m->type);
+	dict_append_entry(&dict, "Measurement", DBUS_TYPE_STRING, &m->msmnt);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	dbus_message_set_no_reply(msg, TRUE);
+	g_dbus_send_message(conn, msg);
+}
+
+static void recv_measurement(struct thermometer *t, struct measurement *msmt)
+{
+	if (g_strcmp0(msmt->msmnt, "Intermediate") == 0) {
+		DBG("Notification of intermediate measurement not implemented");
+		return;
+	}
+
+	g_slist_foreach(t->fwatchers, update_watcher, msmt);
+}
+
 static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
 						uint16_t len, gboolean final)
 {
-	DBG("TODO: Process measurement indication");
+	struct measurement msmt;
+	uint8_t flags;
+	uint32_t raw;
+
+	if (len < 4) {
+		DBG("Mandatory flags are not provided");
+		return;
+	}
+
+	flags = pdu[3];
+	if (flags & TEMP_UNITS)
+		msmt.unit = "Fahrenheit";
+	else
+		msmt.unit = "Celsius";
+
+	if (len < 8) {
+		DBG("Temperature measurement value is not provided");
+		return;
+	}
+
+	raw = att_get_u32(&pdu[4]);
+	msmt.mant = raw & 0x00FFFFFF;
+	msmt.exp = ((gint32) raw) >> 24;
+
+	if (msmt.mant & 0x00800000) {
+		/* convert to C2 negative value */
+		msmt.mant = msmt.mant - FLOAT_MAX_MANTISSA;
+	}
+
+	if (flags & TEMP_TIME_STAMP) {
+		struct tm ts;
+		time_t time;
+
+		if (len < 15) {
+			DBG("Can't get time stamp value");
+			return;
+		}
+
+		ts.tm_year = att_get_u16(&pdu[8]) - 1900;
+		ts.tm_mon = pdu[10];
+		ts.tm_mday = pdu[11];
+		ts.tm_hour = pdu[12];
+		ts.tm_min = pdu[13];
+		ts.tm_sec = pdu[14];
+		ts.tm_isdst = -1;
+
+		time = mktime(&ts);
+		msmt.time = (guint64) time;
+		msmt.suptime = TRUE;
+	} else
+		msmt.suptime = FALSE;
+
+	if (flags & TEMP_TYPE) {
+		if (len < 16) {
+			DBG("Can't get temperature type");
+			return;
+		}
+
+		msmt.type = temptype2str(pdu[15]);
+	} else if (t->has_type)
+		msmt.type = temptype2str(t->type);
+	else {
+		DBG("Can't get temperature type");
+		return;
+	}
+
+	msmt.msmnt = final ? "Final" : "Intermediate";
+
+	recv_measurement(t, &msmt);
 }
 
 static void proc_measurement_interval(struct thermometer *t, const uint8_t *pdu,
-- 
1.7.7.3


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

* [PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default policy
  2011-11-10 11:36   ` [PATCH 2/6] Parse final measurement indication Santiago Carot-Nemesio
@ 2011-11-10 11:36     ` Santiago Carot-Nemesio
  2011-11-10 11:37       ` [PATCH 4/6] Implement EnableIntermediateMeasurement D-Bus method Santiago Carot-Nemesio
  2011-11-12 18:37     ` [PATCH 2/6] Parse final measurement indication Johan Hedberg
  1 sibling, 1 reply; 11+ messages in thread
From: Santiago Carot-Nemesio @ 2011-11-10 11:36 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 src/bluetooth.conf |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index b5a6af3..664dbd9 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -15,6 +15,7 @@
     <allow send_interface="org.bluez.MediaEndpoint"/>
     <allow send_interface="org.bluez.MediaPlayer"/>
     <allow send_interface="org.bluez.Watcher"/>
+    <allow send_interface="org.bluez.ThermometerWatcher"/>
   </policy>
 
   <policy at_console="true">
-- 
1.7.7.3


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

* [PATCH 4/6] Implement EnableIntermediateMeasurement D-Bus method
  2011-11-10 11:36     ` [PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default policy Santiago Carot-Nemesio
@ 2011-11-10 11:37       ` Santiago Carot-Nemesio
  2011-11-10 11:37         ` [PATCH 5/6] Implement DisableIntermediateMeasurement " Santiago Carot-Nemesio
  0 siblings, 1 reply; 11+ messages in thread
From: Santiago Carot-Nemesio @ 2011-11-10 11:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   74 +++++++++++++++++++++++++++++++++++++-------
 1 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 616c21d..49e6372 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -63,6 +63,7 @@ struct thermometer {
 	guint			attindid;	/* Att incications id */
 	GSList			*chars;		/* Characteristics */
 	GSList			*fwatchers;     /* Final measurements */
+	GSList			*iwatchers;     /* Intermediate measurements */
 	gboolean		intermediate;
 	guint8			type;
 	guint16			interval;
@@ -554,7 +555,7 @@ static struct descriptor *get_descriptor(struct characteristic *ch,
 	return l->data;
 }
 
-static void final_measurement_cb(guint8 status, const guint8 *pdu,
+static void measurement_cb(guint8 status, const guint8 *pdu,
 						guint16 len, gpointer user_data)
 {
 	gchar *msg = user_data;
@@ -589,8 +590,34 @@ static void enable_final_measurement(struct thermometer *t)
 	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);
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void enable_intermediate_measurement(struct thermometer *t)
+{
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	gchar *msg;
+
+	ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
+	if (ch == NULL) {
+		DBG("Intermediate 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] = 0x01;
+	atval[1] = 0x00;
+	msg = g_strdup("Enable intermediate measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
 }
 
 static void disable_final_measurement(struct thermometer *t)
@@ -617,8 +644,7 @@ static void disable_final_measurement(struct thermometer *t)
 	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);
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
 }
 
 static void watcher_exit(DBusConnection *conn, void *user_data)
@@ -635,7 +661,7 @@ static void watcher_exit(DBusConnection *conn, void *user_data)
 		disable_final_measurement(t);
 }
 
-static struct watcher *find_watcher(struct thermometer *t, const gchar *sender,
+static struct watcher *find_watcher(GSList *list, const gchar *sender,
 							const gchar *path)
 {
 	struct watcher *match;
@@ -645,7 +671,7 @@ static struct watcher *find_watcher(struct thermometer *t, const gchar *sender,
 	match->srv = g_strdup(sender);
 	match->path = g_strdup(path);
 
-	l = g_slist_find_custom(t->fwatchers, match, cmp_watcher);
+	l = g_slist_find_custom(list, match, cmp_watcher);
 	destroy_watcher(match);
 
 	if (l != NULL)
@@ -666,7 +692,7 @@ static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
 							DBUS_TYPE_INVALID))
 		return btd_error_invalid_args(msg);
 
-	watcher = find_watcher(t, sender, path);
+	watcher = find_watcher(t->fwatchers, sender, path);
 	if (watcher != NULL)
 		return btd_error_already_exists(msg);
 
@@ -699,7 +725,7 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
 							DBUS_TYPE_INVALID))
 		return btd_error_invalid_args(msg);
 
-	watcher = find_watcher(t, sender, path);
+	watcher = find_watcher(t->fwatchers, sender, path);
 	if (watcher == NULL)
 		return btd_error_does_not_exist(msg);
 
@@ -717,9 +743,33 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
 static DBusMessage *enable_intermediate(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 (!t->intermediate)
+		return btd_error_not_supported(msg);
+
+	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->fwatchers, sender, path);
+	if (watcher == NULL)
+		return btd_error_does_not_exist(msg);
+
+	if (find_watcher(t->iwatchers, sender, path))
+		return btd_error_already_exists(msg);
+
+	DBG("Intermediate measurement watcher %s registered", path);
+
+	if (g_slist_length(t->iwatchers) == 0)
+		enable_intermediate_measurement(t);
+
+	t->iwatchers = g_slist_prepend(t->iwatchers, watcher);
+
+	return dbus_message_new_method_return(msg);
 }
 
 static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
-- 
1.7.7.3


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

* [PATCH 5/6] Implement DisableIntermediateMeasurement D-Bus method
  2011-11-10 11:37       ` [PATCH 4/6] Implement EnableIntermediateMeasurement D-Bus method Santiago Carot-Nemesio
@ 2011-11-10 11:37         ` Santiago Carot-Nemesio
  2011-11-10 11:37           ` [PATCH 6/6] Notify intermediate measurements Santiago Carot-Nemesio
  0 siblings, 1 reply; 11+ messages in thread
From: Santiago Carot-Nemesio @ 2011-11-10 11:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

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

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 49e6372..0663b3c 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -647,6 +647,44 @@ static void disable_final_measurement(struct thermometer *t)
 	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
 }
 
+static void disable_intermediate_measurement(struct thermometer *t)
+{
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	gchar *msg;
+
+	ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
+	if (ch == NULL) {
+		DBG("Intermediate 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 intermediate measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void remove_int_watcher(struct thermometer *t, struct watcher *w)
+{
+	if (!g_slist_find(t->iwatchers, w))
+		return;
+
+	t->iwatchers = g_slist_remove(t->iwatchers, w);
+
+	if (g_slist_length(t->iwatchers) == 0)
+		disable_intermediate_measurement(t);
+}
+
 static void watcher_exit(DBusConnection *conn, void *user_data)
 {
 	struct watcher *watcher = user_data;
@@ -654,6 +692,8 @@ static void watcher_exit(DBusConnection *conn, void *user_data)
 
 	DBG("Thermometer watcher %s disconnected", watcher->path);
 
+	remove_int_watcher(t, watcher);
+
 	t->fwatchers = g_slist_remove(t->fwatchers, watcher);
 	watcher->id = 0;
 
@@ -731,6 +771,8 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
 
 	DBG("Thermometer watcher %s unregistered", path);
 
+	remove_int_watcher(t, watcher);
+
 	t->fwatchers = g_slist_remove(t->fwatchers, watcher);
 	destroy_watcher(watcher);
 
@@ -775,9 +817,24 @@ static DBusMessage *enable_intermediate(DBusConnection *conn, DBusMessage *msg,
 static DBusMessage *disable_intermediate(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->iwatchers, sender, path);
+	if (watcher == NULL)
+		return btd_error_does_not_exist(msg);
+
+	DBG("Intermediate measurement %s unregistered", path);
+
+	remove_int_watcher(t, watcher);
+
+	return dbus_message_new_method_return(msg);
 }
 
 static GDBusMethodTable thermometer_methods[] = {
-- 
1.7.7.3


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

* [PATCH 6/6] Notify intermediate measurements
  2011-11-10 11:37         ` [PATCH 5/6] Implement DisableIntermediateMeasurement " Santiago Carot-Nemesio
@ 2011-11-10 11:37           ` Santiago Carot-Nemesio
  0 siblings, 0 replies; 11+ messages in thread
From: Santiago Carot-Nemesio @ 2011-11-10 11:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   47 ++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 0663b3c..fb03b8d 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -61,6 +61,7 @@ struct thermometer {
 	struct att_range	*svc_range;	/* Thermometer range */
 	guint			attioid;	/* Att watcher id */
 	guint			attindid;	/* Att incications id */
+	guint			attnotid;	/* Att notifications id */
 	GSList			*chars;		/* Characteristics */
 	GSList			*fwatchers;     /* Final measurements */
 	GSList			*iwatchers;     /* Intermediate measurements */
@@ -152,6 +153,9 @@ static void destroy_thermometer(gpointer user_data)
 	if (t->attindid > 0)
 		g_attrib_unregister(t->attrib, t->attindid);
 
+	if (t->attnotid > 0)
+		g_attrib_unregister(t->attrib, t->attnotid);
+
 	if (t->attrib != NULL)
 		g_attrib_unref(t->attrib);
 
@@ -893,12 +897,14 @@ static void update_watcher(gpointer data, gpointer user_data)
 
 static void recv_measurement(struct thermometer *t, struct measurement *msmt)
 {
-	if (g_strcmp0(msmt->msmnt, "Intermediate") == 0) {
-		DBG("Notification of intermediate measurement not implemented");
-		return;
-	}
+	GSList *wlist;
 
-	g_slist_foreach(t->fwatchers, update_watcher, msmt);
+	if (g_strcmp0(msmt->msmnt, "Intermediate") == 0)
+		wlist = t->iwatchers;
+	else
+		wlist = t->fwatchers;
+
+	g_slist_foreach(wlist, update_watcher, msmt);
 }
 
 static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
@@ -1015,6 +1021,30 @@ static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 									NULL);
 }
 
+static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+	struct thermometer *t = user_data;
+	const struct characteristic *ch;
+	uint16_t handle;
+	GSList *l;
+
+	if (len < 3) {
+		DBG("Bad pdu received");
+		return;
+	}
+
+	handle = att_get_u16(&pdu[1]);
+	l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
+	if (l == NULL) {
+		DBG("Unexpected handle: 0x%04x", handle);
+		return;
+	}
+
+	ch = l->data;
+	if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0)
+		proc_measurement(t, pdu, len, FALSE);
+}
+
 static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 {
 	struct thermometer *t = user_data;
@@ -1023,6 +1053,8 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 
 	t->attindid = g_attrib_register(t->attrib, ATT_OP_HANDLE_IND,
 							ind_handler, t, NULL);
+	t->attnotid = g_attrib_register(t->attrib, ATT_OP_HANDLE_NOTIFY,
+							notif_handler, t, NULL);
 	gatt_discover_char(t->attrib, t->svc_range->start, t->svc_range->end,
 					NULL, configure_thermometer_cb, t);
 }
@@ -1038,6 +1070,11 @@ static void attio_disconnected_cb(gpointer user_data)
 		t->attindid = 0;
 	}
 
+	if (t->attnotid > 0) {
+		g_attrib_unregister(t->attrib, t->attnotid);
+		t->attnotid = 0;
+	}
+
 	g_attrib_unref(t->attrib);
 	t->attrib = NULL;
 }
-- 
1.7.7.3


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

* Re: [PATCH 2/6] Parse final measurement indication
  2011-11-10 11:36   ` [PATCH 2/6] Parse final measurement indication Santiago Carot-Nemesio
  2011-11-10 11:36     ` [PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default policy Santiago Carot-Nemesio
@ 2011-11-12 18:37     ` Johan Hedberg
  2011-11-13  9:18       ` Santiago Carot
  1 sibling, 1 reply; 11+ messages in thread
From: Johan Hedberg @ 2011-11-12 18:37 UTC (permalink / raw)
  To: Santiago Carot-Nemesio; +Cc: linux-bluetooth

Hi Santiago,

On Thu, Nov 10, 2011, Santiago Carot-Nemesio wrote:
> +struct measurement {
> +	gint16		exp;
> +	gint32		mant;
> +	guint64		time;
> +	gboolean	suptime;
> +	gchar		*unit;
> +	gchar		*type;
> +	gchar		*msmnt;

Is msmnt supposed to be short for measurement? Could you just spell it
out please since to me that short version is far from obvious. Or would
"value" be a more suitable name?

Also, please avoid usage of g* types where you're not directly accessing
some GLib API that expects them (even then it's mostly fine to go ahead
with uint16_t, char, etc). I can see that there are other places in
thermometer.c using the g types too which should be fixed in a separate
patch.

> +static gchar *temptype2str(uint8_t value)
> +{
> +	switch (value) {
> +	case 1: return "Armpit";
> +	case 2: return "Body";
> +	case 3: return "Ear";
> +	case 4: return "Finger";
> +	case 5: return "Intestines";
> +	case 6: return "Mouth";
> +	case 7: return "Rectum";
> +	case 8: return "Toe";
> +	case 9: return "Tympanum";
> +	default:
> +		error("Temperature type %d reserved for future use", value);
> +		return NULL;
> +	};

Please follow the coding style with switch statements. All those return
statements should be on their own line. However, in this case I think
it'd be just easier to make a lookup table for those values, i.e.

const char *temp_type[] {
	"<unknown>",
	"Armpit",
	"Body",
	...

And then in the temptype2str function:

	if (type > 0 && val < G_N_ELEMENTS(temp_type))
		return temp_type[type];


Johan

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

* Re: [PATCH 2/6] Parse final measurement indication
  2011-11-12 18:37     ` [PATCH 2/6] Parse final measurement indication Johan Hedberg
@ 2011-11-13  9:18       ` Santiago Carot
  0 siblings, 0 replies; 11+ messages in thread
From: Santiago Carot @ 2011-11-13  9:18 UTC (permalink / raw)
  To: johan.hedberg, linux-bluetooth

Hi Johan,

2011/11/12 Johan Hedberg <johan.hedberg@gmail.com>:
> Hi Santiago,
>
> On Thu, Nov 10, 2011, Santiago Carot-Nemesio wrote:
>> +struct measurement {
>> +     gint16          exp;
>> +     gint32          mant;
>> +     guint64         time;
>> +     gboolean        suptime;
>> +     gchar           *unit;
>> +     gchar           *type;
>> +     gchar           *msmnt;
>
> Is msmnt supposed to be short for measurement? Could you just spell it
> out please since to me that short version is far from obvious. Or would
> "value" be a more suitable name?
>

Yes, that's supposed to be a kind of short for measurement, There's
not problem to me in changing the name. The reason why I set that name
was because I wanted to keep consistancy with the thermomether
documentation in which we called it measurement.

> Also, please avoid usage of g* types where you're not directly accessing
> some GLib API that expects them (even then it's mostly fine to go ahead
> with uint16_t, char, etc). I can see that there are other places in
> thermometer.c using the g types too which should be fixed in a separate
> patch.
>

Ok, I used only glib types because I was confused about when I should
use these or the other types, Having a look at some parts in BlueZ it
seemed a little mess, but now It's clear to me. Thank you for your
explanation,
If you dont mind I would preffer to send a separate patch fixing that
issue at the end of the new set in order to avoid too many conflicts
rebasing in my local tree.

>> +static gchar *temptype2str(uint8_t value)
>> +{
>> +     switch (value) {
>> +     case 1: return "Armpit";
>> +     case 2: return "Body";
>> +     case 3: return "Ear";
>> +     case 4: return "Finger";
>> +     case 5: return "Intestines";
>> +     case 6: return "Mouth";
>> +     case 7: return "Rectum";
>> +     case 8: return "Toe";
>> +     case 9: return "Tympanum";
>> +     default:
>> +             error("Temperature type %d reserved for future use", value);
>> +             return NULL;
>> +     };
>
> Please follow the coding style with switch statements. All those return
> statements should be on their own line. However, in this case I think
> it'd be just easier to make a lookup table for those values, i.e.
>
> const char *temp_type[] {
>        "<unknown>",
>        "Armpit",
>        "Body",
>        ...
>
> And then in the temptype2str function:
>
>        if (type > 0 && val < G_N_ELEMENTS(temp_type))
>                return temp_type[type];
>
>
> Johan
>

Ok, I'll redo these patches.
Thanks a lot for your comments.

Santiago

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

* [PATCH 4/6] Implement EnableIntermediateMeasurement D-Bus method
  2011-11-14 12:11     ` [PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default policy Santiago Carot-Nemesio
@ 2011-11-14 12:11       ` Santiago Carot-Nemesio
  0 siblings, 0 replies; 11+ messages in thread
From: Santiago Carot-Nemesio @ 2011-11-14 12:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

---
 thermometer/thermometer.c |   74 +++++++++++++++++++++++++++++++++++++-------
 1 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index b35c3aa..64b6aa6 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -63,6 +63,7 @@ struct thermometer {
 	guint			attindid;	/* Att incications id */
 	GSList			*chars;		/* Characteristics */
 	GSList			*fwatchers;     /* Final measurements */
+	GSList			*iwatchers;     /* Intermediate measurements */
 	gboolean		intermediate;
 	guint8			type;
 	guint16			interval;
@@ -558,7 +559,7 @@ static struct descriptor *get_descriptor(struct characteristic *ch,
 	return l->data;
 }
 
-static void final_measurement_cb(guint8 status, const guint8 *pdu,
+static void measurement_cb(guint8 status, const guint8 *pdu,
 						guint16 len, gpointer user_data)
 {
 	gchar *msg = user_data;
@@ -593,8 +594,34 @@ static void enable_final_measurement(struct thermometer *t)
 	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);
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void enable_intermediate_measurement(struct thermometer *t)
+{
+	struct characteristic *ch;
+	struct descriptor *desc;
+	bt_uuid_t btuuid;
+	uint8_t atval[2];
+	gchar *msg;
+
+	ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
+	if (ch == NULL) {
+		DBG("Intermediate 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] = 0x01;
+	atval[1] = 0x00;
+	msg = g_strdup("Enable intermediate measurement");
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
 }
 
 static void disable_final_measurement(struct thermometer *t)
@@ -621,8 +648,7 @@ static void disable_final_measurement(struct thermometer *t)
 	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);
+	gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
 }
 
 static void watcher_exit(DBusConnection *conn, void *user_data)
@@ -639,7 +665,7 @@ static void watcher_exit(DBusConnection *conn, void *user_data)
 		disable_final_measurement(t);
 }
 
-static struct watcher *find_watcher(struct thermometer *t, const gchar *sender,
+static struct watcher *find_watcher(GSList *list, const gchar *sender,
 							const gchar *path)
 {
 	struct watcher *match;
@@ -649,7 +675,7 @@ static struct watcher *find_watcher(struct thermometer *t, const gchar *sender,
 	match->srv = g_strdup(sender);
 	match->path = g_strdup(path);
 
-	l = g_slist_find_custom(t->fwatchers, match, cmp_watcher);
+	l = g_slist_find_custom(list, match, cmp_watcher);
 	destroy_watcher(match);
 
 	if (l != NULL)
@@ -670,7 +696,7 @@ static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
 							DBUS_TYPE_INVALID))
 		return btd_error_invalid_args(msg);
 
-	watcher = find_watcher(t, sender, path);
+	watcher = find_watcher(t->fwatchers, sender, path);
 	if (watcher != NULL)
 		return btd_error_already_exists(msg);
 
@@ -703,7 +729,7 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
 							DBUS_TYPE_INVALID))
 		return btd_error_invalid_args(msg);
 
-	watcher = find_watcher(t, sender, path);
+	watcher = find_watcher(t->fwatchers, sender, path);
 	if (watcher == NULL)
 		return btd_error_does_not_exist(msg);
 
@@ -721,9 +747,33 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
 static DBusMessage *enable_intermediate(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 (!t->intermediate)
+		return btd_error_not_supported(msg);
+
+	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->fwatchers, sender, path);
+	if (watcher == NULL)
+		return btd_error_does_not_exist(msg);
+
+	if (find_watcher(t->iwatchers, sender, path))
+		return btd_error_already_exists(msg);
+
+	DBG("Intermediate measurement watcher %s registered", path);
+
+	if (g_slist_length(t->iwatchers) == 0)
+		enable_intermediate_measurement(t);
+
+	t->iwatchers = g_slist_prepend(t->iwatchers, watcher);
+
+	return dbus_message_new_method_return(msg);
 }
 
 static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
-- 
1.7.7.3


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

end of thread, other threads:[~2011-11-14 12:11 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-10 11:36 Health Thermometer Profile (HTP) Santiago Carot-Nemesio
2011-11-10 11:36 ` [PATCH 1/6] Manage GATT attribute indications in handle callback Santiago Carot-Nemesio
2011-11-10 11:36   ` [PATCH 2/6] Parse final measurement indication Santiago Carot-Nemesio
2011-11-10 11:36     ` [PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default policy Santiago Carot-Nemesio
2011-11-10 11:37       ` [PATCH 4/6] Implement EnableIntermediateMeasurement D-Bus method Santiago Carot-Nemesio
2011-11-10 11:37         ` [PATCH 5/6] Implement DisableIntermediateMeasurement " Santiago Carot-Nemesio
2011-11-10 11:37           ` [PATCH 6/6] Notify intermediate measurements Santiago Carot-Nemesio
2011-11-12 18:37     ` [PATCH 2/6] Parse final measurement indication Johan Hedberg
2011-11-13  9:18       ` Santiago Carot
  -- strict thread matches above, loose matches on Subject: below --
2011-11-14 12:11 Health Thermometer Profile (HTP) Santiago Carot-Nemesio
2011-11-14 12:11 ` [PATCH 1/6] Manage GATT attribute indications in handle callback Santiago Carot-Nemesio
2011-11-14 12:11   ` [PATCH 2/6] Parse final measurement indication Santiago Carot-Nemesio
2011-11-14 12:11     ` [PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default policy Santiago Carot-Nemesio
2011-11-14 12:11       ` [PATCH 4/6] Implement EnableIntermediateMeasurement D-Bus method Santiago Carot-Nemesio
2011-11-09 10:51 Health Thermometer Profile (HTP) Santiago Carot-Nemesio
2011-11-09 10:51 ` [PATCH 1/6] Manage GATT attribute indications in handle callback Santiago Carot-Nemesio
2011-11-09 10:51   ` [PATCH 2/6] Parse final measurement indication Santiago Carot-Nemesio
2011-11-09 10:52     ` [PATCH 3/6] Add org.bluez.ThermometerWatcher interface to default policy Santiago Carot-Nemesio
2011-11-09 10:52       ` [PATCH 4/6] Implement EnableIntermediateMeasurement D-Bus method 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).