Next set of patches enhances support for health thermometer thermomter profile.
They include fixes suggested in early set.
[PATCH 01/19] Get thermometer service range to load the driver.
[PATCH 02/19] Register Health Thermometer Interface
[PATCH 03/19] Unregister Health Thermometer Interface
[PATCH 04/19] Add functions to manage attio callbacks
[PATCH 05/19] Add handler function to manage GATT indications
[PATCH 06/19] Get all characteristics in thermometer service
[PATCH 07/19] Read temperature type characteristic
[PATCH 08/19] Read measurement interval characteristic
[PATCH 09/19] Set Intermediate property if intermediate temp.
Hello Gustavo.
2011/9/20 Gustavo Padovan <[email protected]>:
> * Santiago Carot <[email protected]> [2011-09-20 22:40:56 +0200]:
>
>> Hello,
>>
>> 2011/9/20 Gustavo Padovan <[email protected]>:
>> > Hi Santiago,
>> >
>> > * Santiago Carot-Nemesio <[email protected]> [2011-09-20 19:47:19 +0200]:
>> >
>> >> ---
>> >> ?thermometer/thermometer.c | ? 54 ++++++++++++++++++++++++++++++++++++++++++++-
>> >> ?1 files changed, 53 insertions(+), 1 deletions(-)
>> >>
>> >> diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
>> >> index f0b977e..2dcc4ba 100644
>> >> --- a/thermometer/thermometer.c
>> >> +++ b/thermometer/thermometer.c
>> >> @@ -39,6 +39,14 @@
>> >> ?#define INTERMEDIATE_TEMPERATURE_UUID ? ? ? ?"00002a1e-0000-1000-8000-00805f9b34fb"
>> >> ?#define MEASUREMENT_INTERVAL_UUID ? ?"00002a21-0000-1000-8000-00805f9b34fb"
>> >>
>> >> +struct properties {
>> >> + ? ? gboolean ? ? ? ?intermediate;
>> >> + ? ? guint8 ? ? ? ? ?*type;
>> >> + ? ? guint16 ? ? ? ? *interval;
>> >> + ? ? guint16 ? ? ? ? *max;
>> >> + ? ? guint16 ? ? ? ? *min;
>> >> +};
>> >> +
>> >> ?struct thermometer {
>> >> ? ? ? DBusConnection ? ? ? ? ?*conn; ? ? ? ? ?/* The connection to the bus */
>> >> ? ? ? struct btd_device ? ? ? *dev; ? ? ? ? ? /* Device reference */
>> >> @@ -47,6 +55,7 @@ struct thermometer {
>> >> ? ? ? gint ? ? ? ? ? ? ? ? ? ?attioid; ? ? ? ?/* Att watcher id */
>> >> ? ? ? gint ? ? ? ? ? ? ? ? ? ?attindid; ? ? ? /* Att incications id */
>> >> ? ? ? GSList ? ? ? ? ? ? ? ? ?*chars; ? ? ? ? /* Characteristics */
>> >> + ? ? struct properties ? ? ? properties; ? ? /* Thermometer's properties */
>> >
>> > fold type, interval, max and min here seems a better idea.
>> >
>> >> ?};
>> >>
>> >> ?struct characteristic {
>> >> @@ -63,6 +72,24 @@ struct descriptor {
>> >>
>> >> ?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_char(gpointer user_data)
>> >> ?{
>> >> ? ? ? struct characteristic *c = user_data;
>> >> @@ -87,6 +114,11 @@ static void destroy_thermometer(gpointer user_data)
>> >> ? ? ? if (t->chars)
>> >> ? ? ? ? ? ? ? g_slist_free_full(t->chars, destroy_char);
>> >>
>> >> + ? ? g_free(t->properties.type);
>> >> + ? ? g_free(t->properties.interval);
>> >> + ? ? g_free(t->properties.max);
>> >> + ? ? g_free(t->properties.min);
>> >> +
>> >> ? ? ? dbus_connection_unref(t->conn);
>> >> ? ? ? btd_device_unref(t->dev);
>> >> ? ? ? g_free(t->svc_range);
>> >> @@ -113,7 +145,27 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
>> >> ?static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
>> >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? gpointer user_data)
>> >> ?{
>> >> - ? ? /* TODO */
>> >> + ? ? struct characteristic *ch = user_data;
>> >> + ? ? struct thermometer *t = ch->t;
>> >> + ? ? uint8_t value;
>> >> + ? ? int vlen;
>> >> +
>> >> + ? ? if (status != 0) {
>> >> + ? ? ? ? ? ? DBG("Temperature Type value read failed: %s",
>> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? att_ecode2str(status));
> ?>> + ? ? ? ? ? ? return;
>> >> + ? ? }
>> >> +
>> >> + ? ? if (!dec_read_resp(pdu, len, &value, &vlen)) {
>> >> + ? ? ? ? ? ? DBG("Protocol error");
>> >> + ? ? ? ? ? ? return;
>> >> + ? ? }
>> >> +
>> >> + ? ? DBG("TEMPERATURE TYPE: %s", temptype2str(value));
>> >> + ? ? if (!t->properties.type)
>> >> + ? ? ? ? ? ? t->properties.type = g_new0(guint8, 1);
>> >
>> > Is there a good reason why this is allocated memory? I'm no seeing the point.
>>
>> The reason for doing that is because "type" is an optional attribute
>> in HTP. Another sollution could be use a flag in addition to the type
>> field. I thought it's easier and simpler to use a pointer instead two
>> fields to manage this stuff.
>
> What if type = -1 as flag? You are wasting memory here and using dereferences
> where it is not needed.
>
I think I didn't undestand you. Do you mean to use an special value like flag?
On the other hand, type is an unsigned integer, it can't be <0,
besides, any value for type is valid and usabe and it has it's own
meaning so that you couldn't define an special value as flag here to
manage this stuff in this way.
waiting comments.
Regards.
* Santiago Carot <[email protected]> [2011-09-20 22:40:56 +0200]:
> Hello,
>
> 2011/9/20 Gustavo Padovan <[email protected]>:
> > Hi Santiago,
> >
> > * Santiago Carot-Nemesio <[email protected]> [2011-09-20 19:47:19 +0200]:
> >
> >> ---
> >> ?thermometer/thermometer.c | ? 54 ++++++++++++++++++++++++++++++++++++++++++++-
> >> ?1 files changed, 53 insertions(+), 1 deletions(-)
> >>
> >> diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
> >> index f0b977e..2dcc4ba 100644
> >> --- a/thermometer/thermometer.c
> >> +++ b/thermometer/thermometer.c
> >> @@ -39,6 +39,14 @@
> >> ?#define INTERMEDIATE_TEMPERATURE_UUID ? ? ? ?"00002a1e-0000-1000-8000-00805f9b34fb"
> >> ?#define MEASUREMENT_INTERVAL_UUID ? ?"00002a21-0000-1000-8000-00805f9b34fb"
> >>
> >> +struct properties {
> >> + ? ? gboolean ? ? ? ?intermediate;
> >> + ? ? guint8 ? ? ? ? ?*type;
> >> + ? ? guint16 ? ? ? ? *interval;
> >> + ? ? guint16 ? ? ? ? *max;
> >> + ? ? guint16 ? ? ? ? *min;
> >> +};
> >> +
> >> ?struct thermometer {
> >> ? ? ? DBusConnection ? ? ? ? ?*conn; ? ? ? ? ?/* The connection to the bus */
> >> ? ? ? struct btd_device ? ? ? *dev; ? ? ? ? ? /* Device reference */
> >> @@ -47,6 +55,7 @@ struct thermometer {
> >> ? ? ? gint ? ? ? ? ? ? ? ? ? ?attioid; ? ? ? ?/* Att watcher id */
> >> ? ? ? gint ? ? ? ? ? ? ? ? ? ?attindid; ? ? ? /* Att incications id */
> >> ? ? ? GSList ? ? ? ? ? ? ? ? ?*chars; ? ? ? ? /* Characteristics */
> >> + ? ? struct properties ? ? ? properties; ? ? /* Thermometer's properties */
> >
> > fold type, interval, max and min here seems a better idea.
> >
> >> ?};
> >>
> >> ?struct characteristic {
> >> @@ -63,6 +72,24 @@ struct descriptor {
> >>
> >> ?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_char(gpointer user_data)
> >> ?{
> >> ? ? ? struct characteristic *c = user_data;
> >> @@ -87,6 +114,11 @@ static void destroy_thermometer(gpointer user_data)
> >> ? ? ? if (t->chars)
> >> ? ? ? ? ? ? ? g_slist_free_full(t->chars, destroy_char);
> >>
> >> + ? ? g_free(t->properties.type);
> >> + ? ? g_free(t->properties.interval);
> >> + ? ? g_free(t->properties.max);
> >> + ? ? g_free(t->properties.min);
> >> +
> >> ? ? ? dbus_connection_unref(t->conn);
> >> ? ? ? btd_device_unref(t->dev);
> >> ? ? ? g_free(t->svc_range);
> >> @@ -113,7 +145,27 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
> >> ?static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
> >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? gpointer user_data)
> >> ?{
> >> - ? ? /* TODO */
> >> + ? ? struct characteristic *ch = user_data;
> >> + ? ? struct thermometer *t = ch->t;
> >> + ? ? uint8_t value;
> >> + ? ? int vlen;
> >> +
> >> + ? ? if (status != 0) {
> >> + ? ? ? ? ? ? DBG("Temperature Type value read failed: %s",
> >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? att_ecode2str(status));
>> + ? ? ? ? ? ? return;
> >> + ? ? }
> >> +
> >> + ? ? if (!dec_read_resp(pdu, len, &value, &vlen)) {
> >> + ? ? ? ? ? ? DBG("Protocol error");
> >> + ? ? ? ? ? ? return;
> >> + ? ? }
> >> +
> >> + ? ? DBG("TEMPERATURE TYPE: %s", temptype2str(value));
> >> + ? ? if (!t->properties.type)
> >> + ? ? ? ? ? ? t->properties.type = g_new0(guint8, 1);
> >
> > Is there a good reason why this is allocated memory? I'm no seeing the point.
>
> The reason for doing that is because "type" is an optional attribute
> in HTP. Another sollution could be use a flag in addition to the type
> field. I thought it's easier and simpler to use a pointer instead two
> fields to manage this stuff.
What if type = -1 as flag? You are wasting memory here and using dereferences
where it is not needed.
Gustavo
Hello,
2011/9/20 Gustavo Padovan <[email protected]>:
> Hi Santiago,
>
> * Santiago Carot-Nemesio <[email protected]> [2011-09-20 19:47:19 +0200]:
>
>> ---
>> ?thermometer/thermometer.c | ? 54 ++++++++++++++++++++++++++++++++++++++++++++-
>> ?1 files changed, 53 insertions(+), 1 deletions(-)
>>
>> diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
>> index f0b977e..2dcc4ba 100644
>> --- a/thermometer/thermometer.c
>> +++ b/thermometer/thermometer.c
>> @@ -39,6 +39,14 @@
>> ?#define INTERMEDIATE_TEMPERATURE_UUID ? ? ? ?"00002a1e-0000-1000-8000-00805f9b34fb"
>> ?#define MEASUREMENT_INTERVAL_UUID ? ?"00002a21-0000-1000-8000-00805f9b34fb"
>>
>> +struct properties {
>> + ? ? gboolean ? ? ? ?intermediate;
>> + ? ? guint8 ? ? ? ? ?*type;
>> + ? ? guint16 ? ? ? ? *interval;
>> + ? ? guint16 ? ? ? ? *max;
>> + ? ? guint16 ? ? ? ? *min;
>> +};
>> +
>> ?struct thermometer {
>> ? ? ? DBusConnection ? ? ? ? ?*conn; ? ? ? ? ?/* The connection to the bus */
>> ? ? ? struct btd_device ? ? ? *dev; ? ? ? ? ? /* Device reference */
>> @@ -47,6 +55,7 @@ struct thermometer {
>> ? ? ? gint ? ? ? ? ? ? ? ? ? ?attioid; ? ? ? ?/* Att watcher id */
>> ? ? ? gint ? ? ? ? ? ? ? ? ? ?attindid; ? ? ? /* Att incications id */
>> ? ? ? GSList ? ? ? ? ? ? ? ? ?*chars; ? ? ? ? /* Characteristics */
>> + ? ? struct properties ? ? ? properties; ? ? /* Thermometer's properties */
>
> fold type, interval, max and min here seems a better idea.
>
>> ?};
>>
>> ?struct characteristic {
>> @@ -63,6 +72,24 @@ struct descriptor {
>>
>> ?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_char(gpointer user_data)
>> ?{
>> ? ? ? struct characteristic *c = user_data;
>> @@ -87,6 +114,11 @@ static void destroy_thermometer(gpointer user_data)
>> ? ? ? if (t->chars)
>> ? ? ? ? ? ? ? g_slist_free_full(t->chars, destroy_char);
>>
>> + ? ? g_free(t->properties.type);
>> + ? ? g_free(t->properties.interval);
>> + ? ? g_free(t->properties.max);
>> + ? ? g_free(t->properties.min);
>> +
>> ? ? ? dbus_connection_unref(t->conn);
>> ? ? ? btd_device_unref(t->dev);
>> ? ? ? g_free(t->svc_range);
>> @@ -113,7 +145,27 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
>> ?static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? gpointer user_data)
>> ?{
>> - ? ? /* TODO */
>> + ? ? struct characteristic *ch = user_data;
>> + ? ? struct thermometer *t = ch->t;
>> + ? ? uint8_t value;
>> + ? ? int vlen;
>> +
>> + ? ? if (status != 0) {
>> + ? ? ? ? ? ? DBG("Temperature Type value read failed: %s",
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? att_ecode2str(status));
>> + ? ? ? ? ? ? return;
>> + ? ? }
>> +
>> + ? ? if (!dec_read_resp(pdu, len, &value, &vlen)) {
>> + ? ? ? ? ? ? DBG("Protocol error");
>> + ? ? ? ? ? ? return;
>> + ? ? }
>> +
>> + ? ? DBG("TEMPERATURE TYPE: %s", temptype2str(value));
>> + ? ? if (!t->properties.type)
>> + ? ? ? ? ? ? t->properties.type = g_new0(guint8, 1);
>
> Is there a good reason why this is allocated memory? I'm no seeing the point.
The reason for doing that is because "type" is an optional attribute
in HTP. Another sollution could be use a flag in addition to the type
field. I thought it's easier and simpler to use a pointer instead two
fields to manage this stuff.
Regards.
Hi Santiago,
* Santiago Carot-Nemesio <[email protected]> [2011-09-20 19:47:19 +0200]:
> ---
> thermometer/thermometer.c | 54 ++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 53 insertions(+), 1 deletions(-)
>
> diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
> index f0b977e..2dcc4ba 100644
> --- a/thermometer/thermometer.c
> +++ b/thermometer/thermometer.c
> @@ -39,6 +39,14 @@
> #define INTERMEDIATE_TEMPERATURE_UUID "00002a1e-0000-1000-8000-00805f9b34fb"
> #define MEASUREMENT_INTERVAL_UUID "00002a21-0000-1000-8000-00805f9b34fb"
>
> +struct properties {
> + gboolean intermediate;
> + guint8 *type;
> + guint16 *interval;
> + guint16 *max;
> + guint16 *min;
> +};
> +
> struct thermometer {
> DBusConnection *conn; /* The connection to the bus */
> struct btd_device *dev; /* Device reference */
> @@ -47,6 +55,7 @@ struct thermometer {
> gint attioid; /* Att watcher id */
> gint attindid; /* Att incications id */
> GSList *chars; /* Characteristics */
> + struct properties properties; /* Thermometer's properties */
fold type, interval, max and min here seems a better idea.
> };
>
> struct characteristic {
> @@ -63,6 +72,24 @@ struct descriptor {
>
> 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_char(gpointer user_data)
> {
> struct characteristic *c = user_data;
> @@ -87,6 +114,11 @@ static void destroy_thermometer(gpointer user_data)
> if (t->chars)
> g_slist_free_full(t->chars, destroy_char);
>
> + g_free(t->properties.type);
> + g_free(t->properties.interval);
> + g_free(t->properties.max);
> + g_free(t->properties.min);
> +
> dbus_connection_unref(t->conn);
> btd_device_unref(t->dev);
> g_free(t->svc_range);
> @@ -113,7 +145,27 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
> static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
> gpointer user_data)
> {
> - /* TODO */
> + struct characteristic *ch = user_data;
> + struct thermometer *t = ch->t;
> + uint8_t value;
> + int vlen;
> +
> + if (status != 0) {
> + DBG("Temperature Type value read failed: %s",
> + att_ecode2str(status));
> + return;
> + }
> +
> + if (!dec_read_resp(pdu, len, &value, &vlen)) {
> + DBG("Protocol error");
> + return;
> + }
> +
> + DBG("TEMPERATURE TYPE: %s", temptype2str(value));
> + if (!t->properties.type)
> + t->properties.type = g_new0(guint8, 1);
Is there a good reason why this is allocated memory? I'm no seeing the point.
Gustavo
Hi,
This is only a set of 9 patches. Subject should seem as [PATCH X/09].
In any case, patches are valid.
Sorry for the mess.
Regards
2011/9/20 Santiago Carot-Nemesio <[email protected]>:
> ---
> ?thermometer/thermometer.c | ? ?3 ++-
> ?1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
> index 0178e99..fdf459e 100644
> --- a/thermometer/thermometer.c
> +++ b/thermometer/thermometer.c
> @@ -258,7 +258,8 @@ static void process_thermometer_char(struct characteristic *ch)
> ? ? ? ?GAttribResultFunc func;
>
> ? ? ? ?if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
> - ? ? ? ? ? ? ? /* TODO: Change intermediate property and emit signal */
> + ? ? ? ? ? ? ? gboolean intermediate = TRUE;
> + ? ? ? ? ? ? ? change_property(ch->t, "Intermediate", &intermediate);
> ? ? ? ? ? ? ? ?return;
> ? ? ? ?} else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0)
> ? ? ? ? ? ? ? ?func = read_temp_type_cb;
> --
> 1.7.6.1
>
>
---
thermometer/thermometer.c | 110 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index f8c17c6..f0b977e 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -30,10 +30,15 @@
#include "gattrib.h"
#include "attio.h"
#include "att.h"
+#include "gatt.h"
#include "thermometer.h"
#define THERMOMETER_INTERFACE "org.bluez.Thermometer"
+#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"
+
struct thermometer {
DBusConnection *conn; /* The connection to the bus */
struct btd_device *dev; /* Device reference */
@@ -41,10 +46,31 @@ struct thermometer {
struct att_range *svc_range; /* Thermometer range */
gint attioid; /* Att watcher id */
gint attindid; /* Att incications id */
+ GSList *chars; /* Characteristics */
+};
+
+struct characteristic {
+ struct att_char attr; /* Characteristic */
+ GSList *desc; /* Descriptors */
+ struct thermometer *t; /* Thermometer where the char belongs */
+};
+
+struct descriptor {
+ struct characteristic *ch;
+ uint16_t handle;
+ bt_uuid_t uuid;
};
static GSList *thermometers = NULL;
+static void destroy_char(gpointer user_data)
+{
+ struct characteristic *c = user_data;
+
+ g_slist_free_full(c->desc, g_free);
+ g_free(c);
+}
+
static void destroy_thermometer(gpointer user_data)
{
struct thermometer *t = user_data;
@@ -58,6 +84,9 @@ static void destroy_thermometer(gpointer user_data)
if (t->attrib)
g_attrib_unref(t->attrib);
+ if (t->chars)
+ g_slist_free_full(t->chars, destroy_char);
+
dbus_connection_unref(t->conn);
btd_device_unref(t->dev);
g_free(t->svc_range);
@@ -75,6 +104,85 @@ static gint cmp_device(gconstpointer a, gconstpointer b)
return -1;
}
+static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ /* TODO */
+}
+
+static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ /* TODO */
+}
+
+static void read_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ /* TODO */
+}
+
+static void process_thermometer_char(struct characteristic *ch)
+{
+ GAttribResultFunc func;
+
+ if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
+ /* TODO: Change intermediate property and emit signal */
+ return;
+ } else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0)
+ func = read_temp_type_cb;
+ else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
+ func = read_interval_cb;
+ else
+ return;
+
+ gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0, func, ch);
+}
+
+static void configure_thermometer_cb(GSList *characteristics, guint8 status,
+ gpointer user_data)
+{
+ struct thermometer *t = user_data;
+ GSList *l;
+
+ if (status) {
+ error("Discover thermometer characteristics: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ for (l = characteristics; l; l = l->next) {
+ struct att_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) {
+ struct att_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;
+
+ gatt_find_info(t->attrib, start, end, discover_desc_cb, ch);
+ }
+}
+
static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -152,6 +260,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);
+ gatt_discover_char(t->attrib, t->svc_range->start, t->svc_range->end,
+ NULL, configure_thermometer_cb, t);
}
static void attio_disconnected_cb(gpointer user_data)
--
1.7.6.1
---
thermometer/thermometer.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 0178e99..fdf459e 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -258,7 +258,8 @@ static void process_thermometer_char(struct characteristic *ch)
GAttribResultFunc func;
if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
- /* TODO: Change intermediate property and emit signal */
+ gboolean intermediate = TRUE;
+ change_property(ch->t, "Intermediate", &intermediate);
return;
} else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0)
func = read_temp_type_cb;
--
1.7.6.1
---
thermometer/thermometer.c | 81 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 80 insertions(+), 1 deletions(-)
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 2dcc4ba..0178e99 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -23,6 +23,7 @@
#include <gdbus.h>
#include <bluetooth/uuid.h>
+#include "dbus-common.h"
#include "adapter.h"
#include "device.h"
#include "error.h"
@@ -136,6 +137,60 @@ static gint cmp_device(gconstpointer a, gconstpointer b)
return -1;
}
+static void change_property(struct thermometer *t, const gchar *name,
+ gpointer value) {
+ if (g_strcmp0(name, "Intermediate") == 0) {
+ gboolean *intermediate = value;
+ if (t->properties.intermediate == *intermediate)
+ return;
+
+ t->properties.intermediate = *intermediate;
+ emit_property_changed(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE, name,
+ DBUS_TYPE_BOOLEAN,
+ &t->properties.intermediate);
+ } else if (g_strcmp0(name, "Interval") == 0) {
+ uint16_t *interval = value;
+ if (t->properties.interval &&
+ *t->properties.interval == *interval)
+ return;
+
+ if (!t->properties.interval)
+ t->properties.interval = g_new0(guint16, 1);
+
+ *t->properties.interval = *interval;
+ emit_property_changed(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE, name,
+ DBUS_TYPE_UINT16,
+ t->properties.interval);
+ } else if (g_strcmp0(name, "Maximum") == 0) {
+ uint16_t *max = value;
+ if (t->properties.max && *t->properties.max == *max)
+ return;
+
+ if (!t->properties.max)
+ t->properties.max = g_new0(guint16, 1);
+
+ *t->properties.max = *max;
+ emit_property_changed(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE, name,
+ DBUS_TYPE_UINT16, t->properties.max);
+ } else if (g_strcmp0(name, "Minimum") == 0) {
+ uint16_t *min = value;
+ if (t->properties.min && *t->properties.min == *min)
+ return;
+
+ if (!t->properties.min)
+ t->properties.min = g_new0(guint16, 1);
+
+ *t->properties.min = *min;
+ emit_property_changed(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE, name,
+ DBUS_TYPE_UINT16, t->properties.min);
+ } else
+ DBG("%s is not a thermometer property", name);
+}
+
static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
@@ -171,7 +226,31 @@ static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
static void read_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- /* TODO */
+ struct characteristic *ch = user_data;
+ uint8_t value[ATT_MAX_MTU];
+ uint16_t *p, interval;
+ int vlen;
+
+ if (status != 0) {
+ DBG("Measurement Interval value read failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ if (!dec_read_resp(pdu, len, value, &vlen)) {
+ DBG("Protocol error\n");
+ return;
+ }
+
+ if (vlen < 2) {
+ DBG("Invalid Interval received");
+ return;
+ }
+
+ p = (uint16_t *) value;
+ interval = btohs(*p);
+
+ change_property(ch->t, "Interval", &interval);
}
static void process_thermometer_char(struct characteristic *ch)
--
1.7.6.1
---
thermometer/thermometer.c | 54 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 53 insertions(+), 1 deletions(-)
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index f0b977e..2dcc4ba 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -39,6 +39,14 @@
#define INTERMEDIATE_TEMPERATURE_UUID "00002a1e-0000-1000-8000-00805f9b34fb"
#define MEASUREMENT_INTERVAL_UUID "00002a21-0000-1000-8000-00805f9b34fb"
+struct properties {
+ gboolean intermediate;
+ guint8 *type;
+ guint16 *interval;
+ guint16 *max;
+ guint16 *min;
+};
+
struct thermometer {
DBusConnection *conn; /* The connection to the bus */
struct btd_device *dev; /* Device reference */
@@ -47,6 +55,7 @@ struct thermometer {
gint attioid; /* Att watcher id */
gint attindid; /* Att incications id */
GSList *chars; /* Characteristics */
+ struct properties properties; /* Thermometer's properties */
};
struct characteristic {
@@ -63,6 +72,24 @@ struct descriptor {
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_char(gpointer user_data)
{
struct characteristic *c = user_data;
@@ -87,6 +114,11 @@ static void destroy_thermometer(gpointer user_data)
if (t->chars)
g_slist_free_full(t->chars, destroy_char);
+ g_free(t->properties.type);
+ g_free(t->properties.interval);
+ g_free(t->properties.max);
+ g_free(t->properties.min);
+
dbus_connection_unref(t->conn);
btd_device_unref(t->dev);
g_free(t->svc_range);
@@ -113,7 +145,27 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- /* TODO */
+ struct characteristic *ch = user_data;
+ struct thermometer *t = ch->t;
+ uint8_t value;
+ int vlen;
+
+ if (status != 0) {
+ DBG("Temperature Type value read failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ if (!dec_read_resp(pdu, len, &value, &vlen)) {
+ DBG("Protocol error");
+ return;
+ }
+
+ DBG("TEMPERATURE TYPE: %s", temptype2str(value));
+ if (!t->properties.type)
+ t->properties.type = g_new0(guint8, 1);
+
+ *t->properties.type = value;
}
static void read_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
--
1.7.6.1
---
thermometer/thermometer.c | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index cdfe455..e06c6da 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -28,6 +28,7 @@
#include "error.h"
#include "log.h"
#include "gattrib.h"
+#include "attio.h"
#include "att.h"
#include "thermometer.h"
@@ -36,7 +37,9 @@
struct thermometer {
DBusConnection *conn; /* The connection to the bus */
struct btd_device *dev; /* Device reference */
+ GAttrib *attrib; /* GATT connection */
struct att_range *svc_range; /* Thermometer range */
+ gint attioid; /* Att watcher id */
};
static GSList *thermometers = NULL;
@@ -45,6 +48,12 @@ static void destroy_thermometer(gpointer user_data)
{
struct thermometer *t = user_data;
+ if (t->attioid)
+ btd_device_remove_attio_callback(t->dev, t->attioid);
+
+ if (t->attrib)
+ g_attrib_unref(t->attrib);
+
dbus_connection_unref(t->conn);
btd_device_unref(t->dev);
g_free(t->svc_range);
@@ -126,6 +135,23 @@ static GDBusSignalTable thermometer_signals[] = {
{ }
};
+static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+{
+ struct thermometer *t = user_data;
+
+ t->attrib = g_attrib_ref(attrib);
+}
+
+static void attio_disconnected_cb(gpointer user_data)
+{
+ struct thermometer *t = user_data;
+
+ DBG("GATT Disconnected");
+
+ g_attrib_unref(t->attrib);
+ t->attrib = NULL;
+}
+
int thermometer_register(DBusConnection *connection, struct btd_device *device,
struct att_primary *tattr)
{
@@ -149,6 +175,9 @@ int thermometer_register(DBusConnection *connection, struct btd_device *device,
}
thermometers = g_slist_prepend(thermometers, t);
+
+ t->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
+ attio_disconnected_cb, t);
return 0;
}
--
1.7.6.1
---
thermometer/thermometer.c | 23 ++++++++++++++++++++++-
1 files changed, 22 insertions(+), 1 deletions(-)
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index a89d8a9..cdfe455 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -51,6 +51,17 @@ static void destroy_thermometer(gpointer user_data)
g_free(t);
}
+static gint cmp_device(gconstpointer a, gconstpointer b)
+{
+ const struct thermometer *t = a;
+ const struct btd_device *dev = b;
+
+ if (dev == t->dev)
+ return 0;
+
+ return -1;
+}
+
static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -143,5 +154,15 @@ int thermometer_register(DBusConnection *connection, struct btd_device *device,
void thermometer_unregister(struct btd_device *device)
{
- /* TODO: Unregister Health Thermometer Interface */
+ struct thermometer *t;
+ GSList *l;
+
+ l = g_slist_find_custom(thermometers, device, cmp_device);
+ if (!l)
+ return;
+
+ t = l->data;
+ thermometers = g_slist_remove(thermometers, t);
+ g_dbus_unregister_interface(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE);
}
--
1.7.6.1
---
thermometer/thermometer.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index e06c6da..f8c17c6 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -40,6 +40,7 @@ struct thermometer {
GAttrib *attrib; /* GATT connection */
struct att_range *svc_range; /* Thermometer range */
gint attioid; /* Att watcher id */
+ gint attindid; /* Att incications id */
};
static GSList *thermometers = NULL;
@@ -51,6 +52,9 @@ static void destroy_thermometer(gpointer user_data)
if (t->attioid)
btd_device_remove_attio_callback(t->dev, t->attioid);
+ if (t->attindid)
+ g_attrib_unregister(t->attrib, t->attindid);
+
if (t->attrib)
g_attrib_unref(t->attrib);
@@ -135,11 +139,19 @@ static GDBusSignalTable thermometer_signals[] = {
{ }
};
+static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+ /* TODO: Process indication */
+}
+
static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
{
struct thermometer *t = user_data;
t->attrib = g_attrib_ref(attrib);
+
+ t->attindid = g_attrib_register(t->attrib, ATT_OP_HANDLE_IND,
+ ind_handler, t, NULL);
}
static void attio_disconnected_cb(gpointer user_data)
@@ -148,6 +160,11 @@ static void attio_disconnected_cb(gpointer user_data)
DBG("GATT Disconnected");
+ if (t->attindid) {
+ g_attrib_unregister(t->attrib, t->attindid);
+ t->attindid = 0;
+ }
+
g_attrib_unref(t->attrib);
t->attrib = NULL;
}
--
1.7.6.1
---
thermometer/thermometer.c | 108 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 107 insertions(+), 1 deletions(-)
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 027ae02..a89d8a9 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -25,13 +25,119 @@
#include "adapter.h"
#include "device.h"
+#include "error.h"
+#include "log.h"
+#include "gattrib.h"
#include "att.h"
#include "thermometer.h"
+#define THERMOMETER_INTERFACE "org.bluez.Thermometer"
+
+struct thermometer {
+ DBusConnection *conn; /* The connection to the bus */
+ struct btd_device *dev; /* Device reference */
+ struct att_range *svc_range; /* Thermometer range */
+};
+
+static GSList *thermometers = NULL;
+
+static void destroy_thermometer(gpointer user_data)
+{
+ struct thermometer *t = user_data;
+
+ dbus_connection_unref(t->conn);
+ btd_device_unref(t->dev);
+ g_free(t->svc_range);
+ g_free(t);
+}
+
+static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ /* TODO: */
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".ThermometerError",
+ "Function not implemented.");
+}
+
+static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ /* TODO: */
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".ThermometerError",
+ "Function not implemented.");
+}
+
+static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ /* TODO: */
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".ThermometerError",
+ "Function not implemented.");
+}
+
+static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ /* TODO: */
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".ThermometerError",
+ "Function not implemented.");
+}
+
+static DBusMessage *enable_intermediate(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ /* TODO: */
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".ThermometerError",
+ "Function not implemented.");
+}
+
+static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ /* TODO: */
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".ThermometerError",
+ "Function not implemented.");
+}
+
+static GDBusMethodTable thermometer_methods[] = {
+ { "GetProperties", "", "a{sv}", get_properties },
+ { "SetProperty", "sv", "", set_property,
+ G_DBUS_METHOD_FLAG_ASYNC },
+ { "RegisterWatcher", "o", "", register_watcher },
+ { "UnregisterWatcher", "o", "", unregister_watcher },
+ { "EnableIntermediateMeasurement", "o", "", enable_intermediate },
+ { "DisableIntermediateMeasurement","o", "", disable_intermediate },
+ { }
+};
+
+static GDBusSignalTable thermometer_signals[] = {
+ { "PropertyChanged", "sv" },
+ { }
+};
+
int thermometer_register(DBusConnection *connection, struct btd_device *device,
struct att_primary *tattr)
{
- /* TODO: Register Health Thermometer Interface */
+ const gchar *path = device_get_path(device);
+ struct thermometer *t;
+
+ t = g_new0(struct thermometer, 1);
+ t->conn = dbus_connection_ref(connection);
+ t->dev = btd_device_ref(device);
+ t->svc_range = g_new0(struct att_range, 1);
+ t->svc_range->start = tattr->start;
+ t->svc_range->end = tattr->end;
+
+ if (!g_dbus_register_interface(t->conn, path, THERMOMETER_INTERFACE,
+ thermometer_methods, thermometer_signals,
+ NULL, t, destroy_thermometer)) {
+ error("D-Bus failed to register %s interface",
+ THERMOMETER_INTERFACE);
+ destroy_thermometer(t);
+ return -1;
+ }
+
+ thermometers = g_slist_prepend(thermometers, t);
return 0;
}
--
1.7.6.1
---
thermometer/manager.c | 13 ++++++++++++-
thermometer/thermometer.c | 5 ++++-
thermometer/thermometer.h | 3 ++-
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/thermometer/manager.c b/thermometer/manager.c
index 08f0e0a..b39094f 100644
--- a/thermometer/manager.c
+++ b/thermometer/manager.c
@@ -21,9 +21,11 @@
*/
#include <gdbus.h>
+#include <bluetooth/uuid.h>
#include "adapter.h"
#include "device.h"
+#include "att.h"
#include "thermometer.h"
#include "manager.h"
@@ -33,7 +35,16 @@ static DBusConnection *connection = NULL;
static int thermometer_driver_probe(struct btd_device *device, GSList *uuids)
{
- return thermometer_register(connection, device);
+ struct att_primary *tattr;
+ GSList *list;
+
+ list = device_services_from_record(device, uuids);
+ if (!list)
+ return -1;
+
+ tattr = list->data;
+
+ return thermometer_register(connection, device, tattr);
}
static void thermometer_driver_remove(struct btd_device *device)
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
index 3cd821a..027ae02 100644
--- a/thermometer/thermometer.c
+++ b/thermometer/thermometer.c
@@ -21,12 +21,15 @@
*/
#include <gdbus.h>
+#include <bluetooth/uuid.h>
#include "adapter.h"
#include "device.h"
+#include "att.h"
#include "thermometer.h"
-int thermometer_register(DBusConnection *connection, struct btd_device *device)
+int thermometer_register(DBusConnection *connection, struct btd_device *device,
+ struct att_primary *tattr)
{
/* TODO: Register Health Thermometer Interface */
return 0;
diff --git a/thermometer/thermometer.h b/thermometer/thermometer.h
index 0937444..298c9ad 100644
--- a/thermometer/thermometer.h
+++ b/thermometer/thermometer.h
@@ -20,5 +20,6 @@
*
*/
-int thermometer_register(DBusConnection *connection, struct btd_device *device);
+int thermometer_register(DBusConnection *connection, struct btd_device *device,
+ struct att_primary *tattr);
void thermometer_unregister(struct btd_device *device);
--
1.7.6.1