summaryrefslogtreecommitdiff
path: root/proximity
diff options
context:
space:
mode:
authorAnderson Lizardo <anderson.lizardo@openbossa.org>2011-07-28 11:43:03 -0300
committerJohan Hedberg <johan.hedberg@intel.com>2011-08-03 12:28:49 +0300
commit46fd11cd900ebded12507798eb12ae492925171e (patch)
treea1ed438a97ca9633d1dc7bc2a44bb5ed96c2a077 /proximity
parent5f3ec93302bfe5cc8e233520353d3657a462709a (diff)
downloadbluez-46fd11cd900ebded12507798eb12ae492925171e.tar.gz
Proximity Monitor: Write Alert Level to Reporter
When the Proximity Monitor connects to the Reporter, it shall write its current Alert Level (usually defined by the user) into the Alert Level characteristic on the Monitor. So once the link is lost, the Monitor will alert with the appropriate level. Note: Register connection callback to write alert level to the Reporter.
Diffstat (limited to 'proximity')
-rw-r--r--proximity/monitor.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/proximity/monitor.c b/proximity/monitor.c
index 8465f92db..c16385a01 100644
--- a/proximity/monitor.c
+++ b/proximity/monitor.c
@@ -35,19 +35,28 @@
#include <sys/stat.h>
#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
#include "dbus-common.h"
#include "adapter.h"
#include "device.h"
#include "error.h"
#include "log.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "attio.h"
#include "monitor.h"
#include "textfile.h"
#define PROXIMITY_INTERFACE "org.bluez.Proximity"
+#define LINK_LOSS_UUID "00001803-0000-1000-8000-00805f9b34fb"
+#define ALERT_LEVEL_CHR_UUID 0x2A06
+
struct monitor {
struct btd_device *device;
+ GAttrib *attrib;
char *linklosslevel; /* Link Loss Alert Level */
};
@@ -90,6 +99,87 @@ static char *read_proximity_config(bdaddr_t *sba, bdaddr_t *dba,
return textfile_caseget(filename, key);
}
+static void char_discovered_cb(GSList *characteristics, guint8 status,
+ gpointer user_data)
+{
+ struct monitor *monitor = user_data;
+ struct att_char *chr;
+ uint8_t value;
+
+ if (status) {
+ error("Discover Link Loss handle: %s", att_ecode2str(status));
+ return;
+ }
+
+ if (strcmp(monitor->linklosslevel, "none") == 0)
+ value = 0x00;
+ else if (strcmp(monitor->linklosslevel, "mild") == 0)
+ value = 0x01;
+ else if (strcmp(monitor->linklosslevel, "high") == 0)
+ value = 0x02;
+
+ DBG("Setting alert level \"%s\" on Reporter", monitor->linklosslevel);
+
+ /* Assume there is a single Alert Level characteristic */
+ chr = characteristics->data;
+
+ gatt_write_cmd(monitor->attrib, chr->value_handle, &value, 1, NULL, NULL);
+}
+
+static int write_alert_level(struct monitor *monitor)
+{
+ GSList *l, *primaries;
+ uint16_t start = 0, end = 0;
+ bt_uuid_t uuid;
+
+ primaries = btd_device_get_primaries(monitor->device);
+ if (primaries == NULL) {
+ DBG("No primary services found");
+ return -1;
+ }
+
+ for (l = primaries; l; l = l->next) {
+ struct att_primary *primary = l->data;
+
+ if (strcmp(primary->uuid, LINK_LOSS_UUID) == 0) {
+ start = primary->start;
+ end = primary->end;
+ break;
+ }
+ }
+
+ if (!start) {
+ DBG("Link Loss service not found");
+ return -1;
+ }
+
+ DBG("Link Loss service found at range 0x%04x-0x%04x", start, end);
+
+ bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID);
+
+ /* FIXME: use cache (requires service changed support) ? */
+ gatt_discover_char(monitor->attrib, start, end, &uuid, char_discovered_cb,
+ monitor);
+
+ return 0;
+}
+
+static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+{
+ struct monitor *monitor = user_data;
+
+ monitor->attrib = g_attrib_ref(attrib);
+ write_alert_level(monitor);
+}
+
+static void attio_disconnected_cb(gpointer user_data)
+{
+ struct monitor *monitor = user_data;
+
+ g_attrib_unref(monitor->attrib);
+ monitor->attrib = NULL;
+}
+
static DBusMessage *set_link_loss_alert(DBusConnection *conn, DBusMessage *msg,
const char *level, void *data)
{
@@ -229,6 +319,9 @@ int monitor_register(DBusConnection *conn, struct btd_device *device)
DBG("Registered interface %s on path %s", PROXIMITY_INTERFACE, path);
+ btd_device_add_attio_callback(device, attio_connected_cb,
+ attio_disconnected_cb, monitor);
+
return 0;
}