[PATCH 04/15] thermometer: Use dedicated handler for Intermediate Temperature

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch replaces global notifications handler with one registered only
for Intermediate Temperature value notifications.
---
 profiles/thermometer/thermometer.c | 345 ++++++++++++++++++-------------------
 1 file changed, 168 insertions(+), 177 deletions(-)

diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index d65fc0d..5ed0553 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -71,7 +71,8 @@ struct thermometer {
 	struct att_range		*svc_range;	/* Thermometer range */
 	guint				attioid;	/* Att watcher id */
 	guint				attindid;	/* Att incications id */
-	guint				attnotid;	/* Att notif id */
+	/* attio id for Intermediate Temperature value notifications */
+	guint				attio_intermediate_id;
 	GSList				*chars;		/* Characteristics */
 	gboolean			intermediate;
 	uint8_t				type;
@@ -179,8 +180,7 @@ 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);
+	g_attrib_unregister(t->attrib, t->attio_intermediate_id);
 
 	if (t->attrib != NULL)
 		g_attrib_unref(t->attrib);
@@ -304,6 +304,162 @@ static void change_property(struct thermometer *t, const char *name,
 	}
 }
 
+static void update_watcher(gpointer data, gpointer user_data)
+{
+	struct watcher *w = data;
+	struct measurement *m = user_data;
+	const gchar *path = device_get_path(m->t->dev);
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call(w->srv, w->path,
+				THERMOMETER_WATCHER_INTERFACE,
+				"MeasurementReceived");
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH , &path);
+
+	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->value);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	dbus_message_set_no_reply(msg, TRUE);
+	g_dbus_send_message(btd_get_dbus_connection(), msg);
+}
+
+static void recv_measurement(struct thermometer *t, struct measurement *m)
+{
+	GSList *wlist;
+
+	m->t = t;
+
+	if (g_strcmp0(m->value, "intermediate") == 0)
+		wlist = t->tadapter->iwatchers;
+	else
+		wlist = t->tadapter->fwatchers;
+
+	g_slist_foreach(wlist, update_watcher, m);
+}
+
+static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
+						uint16_t len, gboolean final)
+{
+	struct measurement m;
+	const char *type = NULL;
+	uint8_t flags;
+	uint32_t raw;
+
+	/* skip opcode and handle */
+	pdu += 3;
+	len -= 3;
+
+	if (len < 1) {
+		DBG("Mandatory flags are not provided");
+		return;
+	}
+
+	memset(&m, 0, sizeof(m));
+
+	flags = *pdu;
+
+	if (flags & TEMP_UNITS)
+		m.unit = "fahrenheit";
+	else
+		m.unit = "celsius";
+
+	pdu++;
+	len--;
+
+	if (len < 4) {
+		DBG("Mandatory temperature measurement value is not provided");
+		return;
+	}
+
+	raw = att_get_u32(pdu);
+	m.mant = raw & 0x00FFFFFF;
+	m.exp = ((int32_t) raw) >> 24;
+
+	if (m.mant & 0x00800000) {
+		/* convert to C2 negative value */
+		m.mant = m.mant - FLOAT_MAX_MANTISSA;
+	}
+
+	pdu += 4;
+	len -= 4;
+
+	if (flags & TEMP_TIME_STAMP) {
+		struct tm ts;
+		time_t time;
+
+		if (len < 7) {
+			DBG("Time stamp is not provided");
+			return;
+		}
+
+		ts.tm_year = att_get_u16(pdu) - 1900;
+		ts.tm_mon = *(pdu + 2) - 1;
+		ts.tm_mday = *(pdu + 3);
+		ts.tm_hour = *(pdu + 4);
+		ts.tm_min = *(pdu + 5);
+		ts.tm_sec = *(pdu + 6);
+		ts.tm_isdst = -1;
+
+		time = mktime(&ts);
+		m.time = (uint64_t) time;
+		m.suptime = TRUE;
+
+		pdu += 7;
+		len -= 7;
+	}
+
+	if (flags & TEMP_TYPE) {
+		if (len < 1) {
+			DBG("Temperature type is not provided");
+			return;
+		}
+
+		type = temptype2str(*pdu);
+	} else if (t->has_type) {
+		type = temptype2str(t->type);
+	}
+
+	m.type = g_strdup(type);
+	m.value = final ? "final" : "intermediate";
+
+	recv_measurement(t, &m);
+	g_free(m.type);
+}
+
+static void intermediate_notify_handler(const uint8_t *pdu, uint16_t len,
+							gpointer user_data)
+{
+	struct thermometer *t = user_data;
+
+	if (len < 3) {
+		DBG("Bad pdu received");
+		return;
+	}
+
+	proc_measurement(t, pdu, len, FALSE);
+}
+
 static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
 							gpointer user_data)
 {
@@ -514,10 +670,15 @@ static void read_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
 
 static void process_thermometer_char(struct characteristic *ch)
 {
+	struct thermometer *t = ch->t;
+
 	if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
 		gboolean intermediate = TRUE;
 		change_property(ch->t, "Intermediate", &intermediate);
-		return;
+
+		t->attio_intermediate_id = g_attrib_register(t->attrib,
+				ATT_OP_HANDLE_NOTIFY, ch->attr.value_handle,
+				intermediate_notify_handler, t, NULL);
 	} else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0) {
 		gatt_read_char(ch->t->attrib, ch->attr.value_handle,
 							read_temp_type_cb, ch);
@@ -941,149 +1102,6 @@ static const GDBusSignalTable thermometer_signals[] = {
 	{ }
 };
 
-static void update_watcher(gpointer data, gpointer user_data)
-{
-	struct watcher *w = data;
-	struct measurement *m = user_data;
-	const gchar *path = device_get_path(m->t->dev);
-	DBusMessageIter iter;
-	DBusMessageIter dict;
-	DBusMessage *msg;
-
-	msg = dbus_message_new_method_call(w->srv, w->path,
-				THERMOMETER_WATCHER_INTERFACE,
-				"MeasurementReceived");
-	if (msg == NULL)
-		return;
-
-	dbus_message_iter_init_append(msg, &iter);
-
-	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH , &path);
-
-	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->value);
-
-	dbus_message_iter_close_container(&iter, &dict);
-
-	dbus_message_set_no_reply(msg, TRUE);
-	g_dbus_send_message(btd_get_dbus_connection(), msg);
-}
-
-static void recv_measurement(struct thermometer *t, struct measurement *m)
-{
-	GSList *wlist;
-
-	m->t = t;
-
-	if (g_strcmp0(m->value, "intermediate") == 0)
-		wlist = t->tadapter->iwatchers;
-	else
-		wlist = t->tadapter->fwatchers;
-
-	g_slist_foreach(wlist, update_watcher, m);
-}
-
-static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
-						uint16_t len, gboolean final)
-{
-	struct measurement m;
-	const char *type = NULL;
-	uint8_t flags;
-	uint32_t raw;
-
-	/* skip opcode and handle */
-	pdu += 3;
-	len -= 3;
-
-	if (len < 1) {
-		DBG("Mandatory flags are not provided");
-		return;
-	}
-
-	memset(&m, 0, sizeof(m));
-
-	flags = *pdu;
-
-	if (flags & TEMP_UNITS)
-		m.unit = "fahrenheit";
-	else
-		m.unit = "celsius";
-
-	pdu++;
-	len--;
-
-	if (len < 4) {
-		DBG("Mandatory temperature measurement value is not provided");
-		return;
-	}
-
-	raw = att_get_u32(pdu);
-	m.mant = raw & 0x00FFFFFF;
-	m.exp = ((int32_t) raw) >> 24;
-
-	if (m.mant & 0x00800000) {
-		/* convert to C2 negative value */
-		m.mant = m.mant - FLOAT_MAX_MANTISSA;
-	}
-
-	pdu += 4;
-	len -= 4;
-
-	if (flags & TEMP_TIME_STAMP) {
-		struct tm ts;
-		time_t time;
-
-		if (len < 7) {
-			DBG("Time stamp is not provided");
-			return;
-		}
-
-		ts.tm_year = att_get_u16(pdu) - 1900;
-		ts.tm_mon = *(pdu + 2) - 1;
-		ts.tm_mday = *(pdu + 3);
-		ts.tm_hour = *(pdu + 4);
-		ts.tm_min = *(pdu + 5);
-		ts.tm_sec = *(pdu + 6);
-		ts.tm_isdst = -1;
-
-		time = mktime(&ts);
-		m.time = (uint64_t) time;
-		m.suptime = TRUE;
-
-		pdu += 7;
-		len -= 7;
-	}
-
-	if (flags & TEMP_TYPE) {
-		if (len < 1) {
-			DBG("Temperature type is not provided");
-			return;
-		}
-
-		type = temptype2str(*pdu);
-	} else if (t->has_type) {
-		type = temptype2str(t->type);
-	}
-
-	m.type = g_strdup(type);
-	m.value = final ? "final" : "intermediate";
-
-	recv_measurement(t, &m);
-	g_free(m.type);
-}
-
 static void proc_measurement_interval(struct thermometer *t, const uint8_t *pdu,
 								uint16_t len)
 {
@@ -1134,30 +1152,6 @@ static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 		g_attrib_send(t->attrib, 0, opdu, olen, NULL, NULL, 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;
@@ -1167,9 +1161,6 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 	t->attindid = g_attrib_register(t->attrib, ATT_OP_HANDLE_IND,
 							GATTRIB_ALL_HANDLES,
 							ind_handler, t, NULL);
-	t->attnotid = g_attrib_register(t->attrib, ATT_OP_HANDLE_NOTIFY,
-							GATTRIB_ALL_HANDLES,
-							notif_handler, t, NULL);
 	gatt_discover_char(t->attrib, t->svc_range->start, t->svc_range->end,
 					NULL, configure_thermometer_cb, t);
 }
@@ -1185,9 +1176,9 @@ 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;
+	if (t->attio_intermediate_id > 0) {
+		g_attrib_unregister(t->attrib, t->attio_intermediate_id);
+		t->attio_intermediate_id = 0;
 	}
 
 	g_attrib_unref(t->attrib);
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux