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;
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);
}
}
+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)
{
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);
{ }
};
-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)
{
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;
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);
}
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);