guint attio_intermediate_id;
/* attio id for Measurement Interval value indications */
guint attio_interval_id;
- GSList *chars; /* Characteristics */
gboolean intermediate;
uint8_t type;
uint16_t interval;
};
struct characteristic {
- struct gatt_char attr; /* Characteristic */
struct thermometer *t; /* Thermometer where the char belongs */
+ char uuid[MAX_LEN_UUID_STR + 1];
};
struct watcher {
g_dbus_remove_watch(btd_get_dbus_connection(), watcher->id);
}
-static void destroy_char(gpointer user_data)
-{
- struct characteristic *c = user_data;
-
- g_free(c);
-}
-
static void destroy_thermometer(gpointer user_data)
{
struct thermometer *t = user_data;
if (t->attrib != NULL)
g_attrib_unref(t->attrib);
- if (t->chars != NULL)
- g_slist_free_full(t->chars, destroy_char);
-
btd_device_unref(t->dev);
g_free(t->svc_range);
g_free(t);
char *msg;
if (uuid == GATT_CHARAC_VALID_RANGE_UUID) {
- if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
+ if (g_strcmp0(ch->uuid, MEASUREMENT_INTERVAL_UUID) == 0)
gatt_read_char(ch->t->attrib, handle,
valid_range_desc_cb, ch->t);
return;
if (uuid != GATT_CLIENT_CHARAC_CFG_UUID)
return;
- if (g_strcmp0(ch->attr.uuid, TEMPERATURE_MEASUREMENT_UUID) == 0) {
+ if (g_strcmp0(ch->uuid, TEMPERATURE_MEASUREMENT_UUID) == 0) {
ch->t->measurement_ccc_handle = handle;
if (g_slist_length(ch->t->tadapter->fwatchers) == 0)
val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
msg = g_strdup("Enable Temperature Measurement indication");
- } else if (g_strcmp0(ch->attr.uuid,
- INTERMEDIATE_TEMPERATURE_UUID) == 0) {
+ } else if (g_strcmp0(ch->uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
ch->t->intermediate_ccc_handle = handle;
if (g_slist_length(ch->t->tadapter->iwatchers) == 0)
val = GATT_CLIENT_CHARAC_CFG_NOTIF_BIT;
msg = g_strdup("Enable Intermediate Temperature notification");
- } else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0) {
+ } else if (g_strcmp0(ch->uuid, MEASUREMENT_INTERVAL_UUID) == 0) {
val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
msg = g_strdup("Enable Measurement Interval indication");
} else {
gpointer user_data)
{
struct characteristic *ch = user_data;
- struct att_data_list *list;
+ struct att_data_list *list = NULL;
uint8_t format;
int i;
if (status != 0) {
error("Discover all characteristic descriptors failed [%s]: %s",
- ch->attr.uuid, att_ecode2str(status));
- return;
+ ch->uuid, att_ecode2str(status));
+ goto done;
}
list = dec_find_info_resp(pdu, len, &format);
if (list == NULL)
- return;
+ goto done;
if (format != ATT_FIND_INFO_RESP_FMT_16BIT)
goto done;
}
done:
- att_data_list_free(list);
+ if (list != NULL)
+ att_data_list_free(list);
+ g_free(ch);
+}
+
+static void discover_desc(struct thermometer *t, struct gatt_char *c,
+ struct gatt_char *c_next)
+{
+ struct characteristic *ch;
+ uint16_t start, end;
+
+ start = c->value_handle + 1;
+
+ if (c_next != NULL) {
+ if (start == c_next->handle)
+ return;
+ end = c_next->handle - 1;
+ } else if (c->value_handle != t->svc_range->end) {
+ end = t->svc_range->end;
+ } else {
+ return;
+ }
+
+ ch = g_new0(struct characteristic, 1);
+ ch->t = t;
+ memcpy(ch->uuid, c->uuid, sizeof(c->uuid));
+
+ gatt_find_info(t->attrib, start, end, discover_desc_cb, ch);
}
static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- struct characteristic *ch = user_data;
- struct thermometer *t = ch->t;
+ struct thermometer *t = user_data;
uint8_t value[TEMPERATURE_TYPE_SIZE];
ssize_t vlen;
static void read_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- struct characteristic *ch = user_data;
+ struct thermometer *t = user_data;
uint8_t value[MEASUREMENT_INTERVAL_SIZE];
uint16_t interval;
ssize_t vlen;
}
interval = att_get_u16(&value[0]);
- change_property(ch->t, "Interval", &interval);
+ change_property(t, "Interval", &interval);
}
-static void process_thermometer_char(struct characteristic *ch)
+static void process_thermometer_char(struct thermometer *t,
+ struct gatt_char *c, struct gatt_char *c_next)
{
- struct thermometer *t = ch->t;
-
- if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
+ if (g_strcmp0(c->uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
gboolean intermediate = TRUE;
- change_property(ch->t, "Intermediate", &intermediate);
+ change_property(t, "Intermediate", &intermediate);
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_MEASUREMENT_UUID) == 0) {
+ ATT_OP_HANDLE_NOTIFY, c->value_handle,
+ intermediate_notify_handler, t, NULL);
+
+ discover_desc(t, c, c_next);
+ } else if (g_strcmp0(c->uuid, TEMPERATURE_MEASUREMENT_UUID) == 0) {
t->attio_measurement_id = g_attrib_register(t->attrib,
- ATT_OP_HANDLE_IND, ch->attr.value_handle,
- measurement_ind_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);
- } else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0) {
- ch->t->interval_val_handle = ch->attr.value_handle;
+ ATT_OP_HANDLE_IND, c->value_handle,
+ measurement_ind_handler, t, NULL);
- gatt_read_char(ch->t->attrib, ch->attr.value_handle,
- read_interval_cb, ch);
+ discover_desc(t, c, c_next);
+ } else if (g_strcmp0(c->uuid, TEMPERATURE_TYPE_UUID) == 0) {
+ gatt_read_char(t->attrib, c->value_handle,
+ read_temp_type_cb, t);
+ } else if (g_strcmp0(c->uuid, MEASUREMENT_INTERVAL_UUID) == 0) {
+ gatt_read_char(t->attrib, c->value_handle, read_interval_cb, t);
+
+ t->interval_val_handle = c->value_handle;
t->attio_interval_id = g_attrib_register(t->attrib,
- ATT_OP_HANDLE_IND, ch->attr.value_handle,
- interval_ind_handler, t, NULL);
+ ATT_OP_HANDLE_IND, c->value_handle,
+ interval_ind_handler, t, NULL);
+
+ discover_desc(t, c, c_next);
}
}
for (l = characteristics; l; l = l->next) {
struct gatt_char *c = l->data;
- struct characteristic *ch;
- uint16_t start, end;
-
- ch = g_new0(struct characteristic, 1);
- ch->attr.handle = c->handle;
- ch->attr.properties = c->properties;
- ch->attr.value_handle = c->value_handle;
- memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
- ch->t = t;
-
- t->chars = g_slist_append(t->chars, ch);
-
- process_thermometer_char(ch);
-
- start = c->value_handle + 1;
-
- if (l->next != NULL) {
- struct gatt_char *c = l->next->data;
- if (start == c->handle)
- continue;
- end = c->handle - 1;
- } else if (c->value_handle != t->svc_range->end) {
- end = t->svc_range->end;
- } else {
- continue;
- }
+ struct gatt_char *c_next = (l->next ? l->next->data : NULL);
- gatt_find_info(t->attrib, start, end, discover_desc_cb, ch);
+ process_thermometer_char(t, c, c_next);
}
}