aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen Ganir <chen.ganir@ti.com>2012-03-20 13:29:16 +0200
committerJoão Paulo Rechi Vita <jprvita@openbossa.org>2012-06-21 18:00:19 -0300
commit04096d279ec8e6243b16ab48d47b6eeb7929c782 (patch)
treed0676e3851a1553306bc747c1b7bfd845be11942
parent726227d68fd8df4213646601edd6d808e1a1cff3 (diff)
downloadbluez-04096d279ec8e6243b16ab48d47b6eeb7929c782.tar.gz
bluez-04096d279ec8e6243b16ab48d47b6eeb7929c782.tar.xz
bluez-04096d279ec8e6243b16ab48d47b6eeb7929c782.zip
battery: Add support for notifications
Add support for emitting PropertyChanged when a battery level characteristic notification is sent from the peer device.
-rw-r--r--batterystate/batterystate.c107
-rw-r--r--doc/battery-api.txt8
2 files changed, 112 insertions, 3 deletions
diff --git a/batterystate/batterystate.c b/batterystate/batterystate.c
index d81d78a8..1ca11599 100644
--- a/batterystate/batterystate.c
+++ b/batterystate/batterystate.c
@@ -50,6 +50,7 @@ struct battery {
GAttrib *attrib; /* GATT connection */
guint attioid; /* Att watcher id */
struct att_range *svc_range; /* Battery range */
+ guint attnotid; /* Att notifications id */
GSList *chars; /* Characteristics */
};
@@ -102,6 +103,14 @@ static gint cmp_device(gconstpointer a, gconstpointer b)
return -1;
}
+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 void batterystate_free(gpointer user_data)
{
struct battery *batt = user_data;
@@ -117,6 +126,9 @@ static void batterystate_free(gpointer user_data)
dbus_connection_unref(batt->conn);
+ if (batt->attnotid > 0)
+ g_attrib_unregister(batt->attrib, batt->attnotid);
+
btd_device_unref(batt->dev);
g_free(batt->svc_range);
g_free(batt);
@@ -156,6 +168,17 @@ static void process_batteryservice_char(struct characteristic *ch)
}
}
+static void batterylevel_enable_notify_cb(guint8 status, const guint8 *pdu,
+ guint16 len, gpointer user_data)
+{
+ char *msg = user_data;
+
+ if (status != 0)
+ error("Could not enable battery level notification: %s", msg);
+
+ g_free(msg);
+}
+
static void batterylevel_presentation_format_desc_cb(guint8 status,
const guint8 *pdu, guint16 len,
gpointer user_data)
@@ -192,6 +215,23 @@ static void process_batterylevel_desc(struct descriptor *desc)
char uuidstr[MAX_LEN_UUID_STR];
bt_uuid_t btuuid;
+ bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+
+ if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0 && g_strcmp0(ch->attr.uuid,
+ BATTERY_LEVEL_UUID) == 0) {
+ uint8_t atval[2];
+ uint16_t val;
+ char *msg;
+
+ val = GATT_CLIENT_CHARAC_CFG_NOTIF_BIT;
+ msg = g_strdup("Enable BatteryLevel notification");
+
+ att_put_u16(val, atval);
+ gatt_write_char(ch->batt->attrib, desc->handle, atval, 2,
+ batterylevel_enable_notify_cb, msg);
+ return;
+ }
+
bt_uuid16_create(&btuuid, GATT_CHARAC_FMT_UUID);
if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0) {
@@ -275,6 +315,12 @@ static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
return reply;
}
+static void emit_battery_level_changed(struct characteristic *c)
+{
+ emit_property_changed(c->batt->conn, c->path, BATTERY_INTERFACE,
+ "Level", DBUS_TYPE_BYTE, &c->level);
+}
+
static const GDBusMethodTable battery_methods[] = {
{ GDBUS_METHOD("GetProperties",
NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
@@ -282,6 +328,13 @@ static const GDBusMethodTable battery_methods[] = {
{ }
};
+static const GDBusSignalTable battery_signals[] = {
+ { GDBUS_SIGNAL("PropertyChanged",
+ GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+
+ { }
+};
+
static void configure_batterystate_cb(GSList *characteristics, guint8 status,
gpointer user_data)
{
@@ -315,7 +368,7 @@ static void configure_batterystate_cb(GSList *characteristics, guint8 status,
if (!g_dbus_register_interface(batt->conn, ch->path,
BATTERY_INTERFACE,
- battery_methods, NULL, NULL,
+ battery_methods, battery_signals, NULL,
ch, char_free)) {
error("D-Bus register interface %s failed",
BATTERY_INTERFACE);
@@ -343,12 +396,64 @@ static void configure_batterystate_cb(GSList *characteristics, guint8 status,
}
}
+static void proc_batterylevel(struct characteristic *c, const uint8_t *pdu,
+ uint16_t len, gboolean final)
+{
+ uint8_t new_batt_level = 0;
+ gboolean changed = FALSE;
+
+ if (!pdu) {
+ error("Battery level notification: Invalid pdu length");
+ goto done;
+ }
+
+ new_batt_level = pdu[1];
+
+ if (new_batt_level != c->level)
+ changed = TRUE;
+
+ c->level = new_batt_level;
+
+done:
+ if (changed) {
+ emit_battery_level_changed(c);
+ }
+}
+
+static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+ struct battery *batt = user_data;
+ struct characteristic *ch;
+ uint16_t handle;
+ GSList *l;
+
+ if (len < 3) {
+ error("notif_handler: Bad pdu received");
+ return;
+ }
+
+ handle = att_get_u16(&pdu[1]);
+ l = g_slist_find_custom(batt->chars, &handle, cmp_char_val_handle);
+ if (l == NULL) {
+ error("notif_handler: Unexpected handle 0x%04x", handle);
+ return;
+ }
+
+ ch = l->data;
+ if (g_strcmp0(ch->attr.uuid, BATTERY_LEVEL_UUID) == 0) {
+ proc_batterylevel(ch, pdu, len, FALSE);
+ }
+}
+
static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
{
struct battery *batt = user_data;
batt->attrib = g_attrib_ref(attrib);
+ batt->attnotid = g_attrib_register(batt->attrib, ATT_OP_HANDLE_NOTIFY,
+ notif_handler, batt, NULL);
+
gatt_discover_char(batt->attrib, batt->svc_range->start,
batt->svc_range->end, NULL,
configure_batterystate_cb, batt);
diff --git a/doc/battery-api.txt b/doc/battery-api.txt
index df1fb040..f31e7e59 100644
--- a/doc/battery-api.txt
+++ b/doc/battery-api.txt
@@ -16,6 +16,11 @@ Methods dict GetProperties()
Returns all properties for the interface. See the
Properties section for the available properties.
+Signals PropertyChanged(string name, variant value)
+
+ This signal indicates a changed value of the given
+ property.
+
Properties byte Namespace [readonly]
Namespace value from the battery format characteristic
@@ -30,5 +35,4 @@ Properties byte Namespace [readonly]
byte Level [readonly]
- Battery level (0-100).
-
+ Battery level (0-100).