linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 00/13] Heart Rate Profile plugin
@ 2012-09-25 14:27 Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 01/13] Heart Rate Profile (HRP) client API Andrzej Kaczmarek
                   ` (13 more replies)
  0 siblings, 14 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

Hi,

Changes since v7:
- rebased to latest upstream master (btd_profile changes)


Andrzej Kaczmarek (6):
  heartrate: Add attio callbacks
  heartrate: Discover HRS characteristics
  heartrate: Discover Heart Rate Measurement CCC
  heartrate: Add support to enable notifications
  heartrate: Process measurement notifications
  heartrate: Add support to reset Energy Expended

Rafal Garbat (6):
  heartrate: Add initial HRP client support
  heartrate: Read Body Sensor Location characteristics
  heartrate: Add HeartRateManager interface
  heartrate: Add GetProperties method
  heartrate: Add HeartRateWatcher interface to default policy
  heartrate: Add test script

Santiago Carot-Nemesio (1):
  Heart Rate Profile (HRP) client API

 Makefile.am                    |   9 +-
 Makefile.tools                 |   3 +-
 doc/heartrate-api.txt          |  84 +++++
 lib/uuid.h                     |   5 +
 profiles/heartrate/heartrate.c | 826 +++++++++++++++++++++++++++++++++++++++++
 profiles/heartrate/heartrate.h |  27 ++
 profiles/heartrate/main.c      |  52 +++
 profiles/heartrate/manager.c   |  97 +++++
 profiles/heartrate/manager.h   |  24 ++
 src/bluetooth.conf             |   1 +
 test/test-heartrate            | 103 +++++
 11 files changed, 1228 insertions(+), 3 deletions(-)
 create mode 100644 doc/heartrate-api.txt
 create mode 100644 profiles/heartrate/heartrate.c
 create mode 100644 profiles/heartrate/heartrate.h
 create mode 100644 profiles/heartrate/main.c
 create mode 100644 profiles/heartrate/manager.c
 create mode 100644 profiles/heartrate/manager.h
 create mode 100755 test/test-heartrate

-- 
1.7.11.3


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v8 01/13] Heart Rate Profile (HRP) client API
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 02/13] heartrate: Add initial HRP client support Andrzej Kaczmarek
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio

From: Santiago Carot-Nemesio <sancane@gmail.com>

---
 doc/heartrate-api.txt | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)
 create mode 100644 doc/heartrate-api.txt

diff --git a/doc/heartrate-api.txt b/doc/heartrate-api.txt
new file mode 100644
index 0000000..1fa9d0b
--- /dev/null
+++ b/doc/heartrate-api.txt
@@ -0,0 +1,84 @@
+Heart Rate API description
+****************************************
+
+Copyright (C) 2012	Santiago Carot-Nemesio <sancane@gmail.com>
+Copyright (C) 2012	Tieto Poland
+
+Heart Rate Manager hierarchy
+============================
+
+Service		org.bluez
+Interface	org.bluez.HeartRateManager
+Object path	[variable prefix]/{hci0,hci1,...}
+
+Methods		RegisterWatcher(object agent)
+
+			Registers a watcher to monitor heart rate measurements.
+
+			Possible Errors: org.bluez.Error.InvalidArguments
+
+		UnregisterWatcher(object agent)
+
+			Unregisters a watcher.
+
+Heart Rate Profile hierarchy
+============================
+
+Service		org.bluez
+Interface	org.bluez.HeartRate
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Methods		dict GetProperties()
+
+			Returns all properties for the interface. See the
+			Properties section for the available properties.
+
+		Reset()
+
+			Restart the accumulation of energy expended from zero.
+
+			Possible Errors: org.bluez.Error.NotSupported
+
+Properties	String Location (optional) [readonly]
+
+			Possible values: "Other", "Chest", "Wrist","Finger",
+					"Hand", "Earlobe", "Foot"
+
+		boolean ResetSupported [readonly]
+
+			True if energy expended is supported.
+
+Heart Rate Watcher hierarchy
+
+============================
+Service		unique name
+Interface	org.bluez.HeartRateWatcher
+Object path	freely definable
+
+Methods		void MeasurementReceived(object device, dict measurement)
+
+			This callback is called whenever a heart rate
+			measurement is received from the heart rate device.
+
+			Measurement:
+
+				uint16 Value:
+
+					Measurement value expressed in beats per
+					minute (bpm)
+
+				uint16 Energy (optional):
+
+					Accumulated energy expended in kilo Joules
+
+				boolean Contact (optional):
+
+					true if skin contact is detected by sensor,
+					false otherwise
+
+				array{uint16} Interval (optional):
+
+					RR-Interval values which represent the time
+					between two consecutive R waves in an ECG.
+					Values are ordered starting from oldest to
+					most recent.
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 02/13] heartrate: Add initial HRP client support
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 01/13] Heart Rate Profile (HRP) client API Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 03/13] heartrate: Add attio callbacks Andrzej Kaczmarek
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Rafal Garbat

From: Rafal Garbat <rafal.garbat@tieto.com>

This patch adds initial support for the Heart Rate Profile client.
Profile driver is registered to keep track of adapters and devices.
---
 Makefile.am                    |   9 ++-
 lib/uuid.h                     |   2 +
 profiles/heartrate/heartrate.c | 165 +++++++++++++++++++++++++++++++++++++++++
 profiles/heartrate/heartrate.h |  26 +++++++
 profiles/heartrate/main.c      |  52 +++++++++++++
 profiles/heartrate/manager.c   |  80 ++++++++++++++++++++
 profiles/heartrate/manager.h   |  24 ++++++
 7 files changed, 356 insertions(+), 2 deletions(-)
 create mode 100644 profiles/heartrate/heartrate.c
 create mode 100644 profiles/heartrate/heartrate.h
 create mode 100644 profiles/heartrate/main.c
 create mode 100644 profiles/heartrate/manager.c
 create mode 100644 profiles/heartrate/manager.h

diff --git a/Makefile.am b/Makefile.am
index 372111a..808a81f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -211,7 +211,7 @@ endif
 
 if GATTMODULES
 builtin_modules += thermometer alert time gatt_example proximity deviceinfo \
-			gatt
+			gatt heartrate
 builtin_sources += profiles/thermometer/main.c \
 			profiles/thermometer/manager.h \
 			profiles/thermometer/manager.c \
@@ -240,7 +240,12 @@ builtin_sources += profiles/thermometer/main.c \
 			profiles/deviceinfo/deviceinfo.c \
 			profiles/gatt/main.c profiles/gatt/manager.h \
 			profiles/gatt/manager.c profiles/gatt/gas.h \
-			profiles/gatt/gas.c
+			profiles/gatt/gas.c \
+			profiles/heartrate/main.c \
+			profiles/heartrate/manager.c \
+			profiles/heartrate/manager.h \
+			profiles/heartrate/heartrate.c \
+			profiles/heartrate/heartrate.h
 endif
 
 builtin_modules += formfactor
diff --git a/lib/uuid.h b/lib/uuid.h
index aa6efdf..3488e66 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -63,6 +63,8 @@ extern "C" {
 
 #define SAP_UUID		"0000112D-0000-1000-8000-00805f9b34fb"
 
+#define HEART_RATE_UUID			"0000180d-0000-1000-8000-00805f9b34fb"
+
 #define HEALTH_THERMOMETER_UUID		"00001809-0000-1000-8000-00805f9b34fb"
 #define TEMPERATURE_MEASUREMENT_UUID	"00002a1c-0000-1000-8000-00805f9b34fb"
 #define TEMPERATURE_TYPE_UUID		"00002a1d-0000-1000-8000-00805f9b34fb"
diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
new file mode 100644
index 0000000..87bc309
--- /dev/null
+++ b/profiles/heartrate/heartrate.c
@@ -0,0 +1,165 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Tieto Poland
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdbool.h>
+#include <glib.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "heartrate.h"
+
+struct heartrate_adapter {
+	struct btd_adapter	*adapter;
+	GSList			*devices;
+};
+
+struct heartrate {
+	struct btd_device		*dev;
+	struct heartrate_adapter	*hradapter;
+};
+
+static GSList *heartrate_adapters = NULL;
+
+static gint cmp_adapter(gconstpointer a, gconstpointer b)
+{
+	const struct heartrate_adapter *hradapter = a;
+	const struct btd_adapter *adapter = b;
+
+	if (adapter == hradapter->adapter)
+		return 0;
+
+	return -1;
+}
+
+static gint cmp_device(gconstpointer a, gconstpointer b)
+{
+	const struct heartrate *hr = a;
+	const struct btd_device *dev = b;
+
+	if (dev == hr->dev)
+		return 0;
+
+	return -1;
+}
+
+static struct heartrate_adapter *
+find_heartrate_adapter(struct btd_adapter *adapter)
+{
+	GSList *l = g_slist_find_custom(heartrate_adapters, adapter,
+								cmp_adapter);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
+
+static void destroy_heartrate(gpointer user_data)
+{
+	struct heartrate *hr = user_data;
+
+	btd_device_unref(hr->dev);
+	g_free(hr);
+}
+
+static void destroy_heartrate_adapter(gpointer user_data)
+{
+	struct heartrate_adapter *hradapter = user_data;
+
+	g_free(hradapter);
+}
+
+int heartrate_adapter_register(struct btd_adapter *adapter)
+{
+	struct heartrate_adapter *hradapter;
+
+	hradapter = g_new0(struct heartrate_adapter, 1);
+	hradapter->adapter = adapter;
+
+	heartrate_adapters = g_slist_prepend(heartrate_adapters, hradapter);
+
+	return 0;
+}
+
+void heartrate_adapter_unregister(struct btd_adapter *adapter)
+{
+	struct heartrate_adapter *hradapter;
+
+	hradapter = find_heartrate_adapter(adapter);
+	if (hradapter == NULL)
+		return;
+
+	heartrate_adapters = g_slist_remove(heartrate_adapters, hradapter);
+
+	destroy_heartrate_adapter(hradapter);
+}
+
+int heartrate_device_register(struct btd_device *device)
+{
+	struct btd_adapter *adapter;
+	struct heartrate_adapter *hradapter;
+	struct heartrate *hr;
+
+	adapter = device_get_adapter(device);
+
+	hradapter = find_heartrate_adapter(adapter);
+
+	if (hradapter == NULL)
+		return -1;
+
+	hr = g_new0(struct heartrate, 1);
+	hr->dev = btd_device_ref(device);
+	hr->hradapter = hradapter;
+
+	hradapter->devices = g_slist_prepend(hradapter->devices, hr);
+
+	return 0;
+}
+
+void heartrate_device_unregister(struct btd_device *device)
+{
+	struct btd_adapter *adapter;
+	struct heartrate_adapter *hradapter;
+	struct heartrate *hr;
+	GSList *l;
+
+	adapter = device_get_adapter(device);
+
+	hradapter = find_heartrate_adapter(adapter);
+	if (hradapter == NULL)
+		return;
+
+	l = g_slist_find_custom(hradapter->devices, device, cmp_device);
+	if (l == NULL)
+		return;
+
+	hr = l->data;
+
+	hradapter->devices = g_slist_remove(hradapter->devices, hr);
+
+	destroy_heartrate(hr);
+}
diff --git a/profiles/heartrate/heartrate.h b/profiles/heartrate/heartrate.h
new file mode 100644
index 0000000..486f5b3
--- /dev/null
+++ b/profiles/heartrate/heartrate.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Tieto Poland
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+int heartrate_adapter_register(struct btd_adapter *adapter);
+void heartrate_adapter_unregister(struct btd_adapter *adapter);
+int heartrate_device_register(struct btd_device *device);
+void heartrate_device_unregister(struct btd_device *device);
diff --git a/profiles/heartrate/main.c b/profiles/heartrate/main.c
new file mode 100644
index 0000000..40f34bc
--- /dev/null
+++ b/profiles/heartrate/main.c
@@ -0,0 +1,52 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Tieto Poland
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <glib.h>
+#include <errno.h>
+
+#include "plugin.h"
+#include "manager.h"
+#include "hcid.h"
+#include "log.h"
+
+static int heartrate_init(void)
+{
+	if (!main_opts.gatt_enabled) {
+		DBG("GATT is disabled");
+		return -ENOTSUP;
+	}
+
+	return heartrate_manager_init();
+}
+
+static void heartrate_exit(void)
+{
+	heartrate_manager_exit();
+}
+
+BLUETOOTH_PLUGIN_DEFINE(heartrate, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+					heartrate_init, heartrate_exit)
diff --git a/profiles/heartrate/manager.c b/profiles/heartrate/manager.c
new file mode 100644
index 0000000..3e668f3
--- /dev/null
+++ b/profiles/heartrate/manager.c
@@ -0,0 +1,80 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Tieto Poland
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <gdbus.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "profile.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "heartrate.h"
+#include "manager.h"
+
+static int heartrate_adapter_probe(struct btd_profile *p,
+						struct btd_adapter *adapter)
+{
+	return heartrate_adapter_register(adapter);
+}
+
+static void heartrate_adapter_remove(struct btd_profile *p,
+						struct btd_adapter *adapter)
+{
+	heartrate_adapter_unregister(adapter);
+}
+
+static int heartrate_device_probe(struct btd_profile *p,
+				struct btd_device *device, GSList *uuids)
+{
+	return heartrate_device_register(device);
+}
+
+static void heartrate_device_remove(struct btd_profile *p,
+						struct btd_device *device)
+{
+	heartrate_device_unregister(device);
+}
+
+static struct btd_profile hrp_profile = {
+	.name		= "Heart Rate GATT Driver",
+	.remote_uuids	= BTD_UUIDS(HEART_RATE_UUID),
+
+	.device_probe	= heartrate_device_probe,
+	.device_remove	= heartrate_device_remove,
+
+	.adapter_probe	= heartrate_adapter_probe,
+	.adapter_remove	= heartrate_adapter_remove,
+};
+
+int heartrate_manager_init(void)
+{
+	return btd_profile_register(&hrp_profile);
+}
+
+void heartrate_manager_exit(void)
+{
+	btd_profile_unregister(&hrp_profile);
+}
diff --git a/profiles/heartrate/manager.h b/profiles/heartrate/manager.h
new file mode 100644
index 0000000..de799f6
--- /dev/null
+++ b/profiles/heartrate/manager.h
@@ -0,0 +1,24 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Tieto Poland
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+int heartrate_manager_init(void);
+void heartrate_manager_exit(void);
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 03/13] heartrate: Add attio callbacks
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 01/13] Heart Rate Profile (HRP) client API Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 02/13] heartrate: Add initial HRP client support Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 04/13] heartrate: Discover HRS characteristics Andrzej Kaczmarek
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

---
 profiles/heartrate/heartrate.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index 87bc309..e057180 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -31,6 +31,11 @@
 
 #include "adapter.h"
 #include "device.h"
+#include "gattrib.h"
+#include "att.h"
+#include "gatt.h"
+#include "attio.h"
+#include "log.h"
 #include "heartrate.h"
 
 struct heartrate_adapter {
@@ -41,6 +46,8 @@ struct heartrate_adapter {
 struct heartrate {
 	struct btd_device		*dev;
 	struct heartrate_adapter	*hradapter;
+	GAttrib				*attrib;
+	guint				attioid;
 };
 
 static GSList *heartrate_adapters = NULL;
@@ -82,6 +89,12 @@ static void destroy_heartrate(gpointer user_data)
 {
 	struct heartrate *hr = user_data;
 
+	if (hr->attioid > 0)
+		btd_device_remove_attio_callback(hr->dev, hr->attioid);
+
+	if (hr->attrib != NULL)
+		g_attrib_unref(hr->attrib);
+
 	btd_device_unref(hr->dev);
 	g_free(hr);
 }
@@ -93,6 +106,25 @@ static void destroy_heartrate_adapter(gpointer user_data)
 	g_free(hradapter);
 }
 
+static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+{
+	struct heartrate *hr = user_data;
+
+	DBG("");
+
+	hr->attrib = g_attrib_ref(attrib);
+}
+
+static void attio_disconnected_cb(gpointer user_data)
+{
+	struct heartrate *hr = user_data;
+
+	DBG("");
+
+	g_attrib_unref(hr->attrib);
+	hr->attrib = NULL;
+}
+
 int heartrate_adapter_register(struct btd_adapter *adapter)
 {
 	struct heartrate_adapter *hradapter;
@@ -137,6 +169,9 @@ int heartrate_device_register(struct btd_device *device)
 
 	hradapter->devices = g_slist_prepend(hradapter->devices, hr);
 
+	hr->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
+						attio_disconnected_cb, hr);
+
 	return 0;
 }
 
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 04/13] heartrate: Discover HRS characteristics
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (2 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 03/13] heartrate: Add attio callbacks Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 05/13] heartrate: Discover Heart Rate Measurement CCC Andrzej Kaczmarek
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

This patch adds support to discover known Heart Rate Service
characteristics.
---
 lib/uuid.h                     |  3 +++
 profiles/heartrate/heartrate.c | 43 +++++++++++++++++++++++++++++++++++++++++-
 profiles/heartrate/heartrate.h |  3 ++-
 profiles/heartrate/manager.c   | 19 ++++++++++++++++++-
 4 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/lib/uuid.h b/lib/uuid.h
index 3488e66..9da1b54 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -64,6 +64,9 @@ extern "C" {
 #define SAP_UUID		"0000112D-0000-1000-8000-00805f9b34fb"
 
 #define HEART_RATE_UUID			"0000180d-0000-1000-8000-00805f9b34fb"
+#define HEART_RATE_MEASUREMENT_UUID	"00002a37-0000-1000-8000-00805f9b34fb"
+#define BODY_SENSOR_LOCATION_UUID	"00002a38-0000-1000-8000-00805f9b34fb"
+#define HEART_RATE_CONTROL_POINT_UUID	"00002a39-0000-1000-8000-00805f9b34fb"
 
 #define HEALTH_THERMOMETER_UUID		"00001809-0000-1000-8000-00805f9b34fb"
 #define TEMPERATURE_MEASUREMENT_UUID	"00002a1c-0000-1000-8000-00805f9b34fb"
diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index e057180..a6733d3 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -48,6 +48,11 @@ struct heartrate {
 	struct heartrate_adapter	*hradapter;
 	GAttrib				*attrib;
 	guint				attioid;
+
+	struct att_range		*svc_range;	/* primary svc range */
+
+	uint16_t			measurement_val_handle;
+	uint16_t			hrcp_val_handle;
 };
 
 static GSList *heartrate_adapters = NULL;
@@ -96,6 +101,7 @@ static void destroy_heartrate(gpointer user_data)
 		g_attrib_unref(hr->attrib);
 
 	btd_device_unref(hr->dev);
+	g_free(hr->svc_range);
 	g_free(hr);
 }
 
@@ -106,6 +112,33 @@ static void destroy_heartrate_adapter(gpointer user_data)
 	g_free(hradapter);
 }
 
+static void discover_char_cb(GSList *chars, guint8 status, gpointer user_data)
+{
+	struct heartrate *hr = user_data;
+
+	if (status) {
+		error("Discover HRS characteristics failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	for (; chars; chars = chars->next) {
+		struct gatt_char *c = chars->data;
+
+		if (g_strcmp0(c->uuid, HEART_RATE_MEASUREMENT_UUID) == 0) {
+			hr->measurement_val_handle = c->value_handle;
+			/* TODO: discover CCC handle */
+		} else if (g_strcmp0(c->uuid, BODY_SENSOR_LOCATION_UUID) == 0) {
+			DBG("Body Sensor Location supported");
+			/* TODO: read characterictic value */
+		} else if (g_strcmp0(c->uuid,
+					HEART_RATE_CONTROL_POINT_UUID) == 0) {
+			DBG("Heart Rate Control Point supported");
+			hr->hrcp_val_handle = c->value_handle;
+		}
+	}
+}
+
 static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 {
 	struct heartrate *hr = user_data;
@@ -113,6 +146,9 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 	DBG("");
 
 	hr->attrib = g_attrib_ref(attrib);
+
+	gatt_discover_char(hr->attrib, hr->svc_range->start, hr->svc_range->end,
+						NULL, discover_char_cb, hr);
 }
 
 static void attio_disconnected_cb(gpointer user_data)
@@ -150,7 +186,8 @@ void heartrate_adapter_unregister(struct btd_adapter *adapter)
 	destroy_heartrate_adapter(hradapter);
 }
 
-int heartrate_device_register(struct btd_device *device)
+int heartrate_device_register(struct btd_device *device,
+						struct gatt_primary *prim)
 {
 	struct btd_adapter *adapter;
 	struct heartrate_adapter *hradapter;
@@ -167,6 +204,10 @@ int heartrate_device_register(struct btd_device *device)
 	hr->dev = btd_device_ref(device);
 	hr->hradapter = hradapter;
 
+	hr->svc_range = g_new0(struct att_range, 1);
+	hr->svc_range->start = prim->range.start;
+	hr->svc_range->end = prim->range.end;
+
 	hradapter->devices = g_slist_prepend(hradapter->devices, hr);
 
 	hr->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
diff --git a/profiles/heartrate/heartrate.h b/profiles/heartrate/heartrate.h
index 486f5b3..064939d 100644
--- a/profiles/heartrate/heartrate.h
+++ b/profiles/heartrate/heartrate.h
@@ -22,5 +22,6 @@
 
 int heartrate_adapter_register(struct btd_adapter *adapter);
 void heartrate_adapter_unregister(struct btd_adapter *adapter);
-int heartrate_device_register(struct btd_device *device);
+int heartrate_device_register(struct btd_device *device,
+						struct gatt_primary *prim);
 void heartrate_device_unregister(struct btd_device *device);
diff --git a/profiles/heartrate/manager.c b/profiles/heartrate/manager.c
index 3e668f3..19b18a8 100644
--- a/profiles/heartrate/manager.c
+++ b/profiles/heartrate/manager.c
@@ -34,6 +34,14 @@
 #include "heartrate.h"
 #include "manager.h"
 
+static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct gatt_primary *prim = a;
+	const char *uuid = b;
+
+	return g_strcmp0(prim->uuid, uuid);
+}
+
 static int heartrate_adapter_probe(struct btd_profile *p,
 						struct btd_adapter *adapter)
 {
@@ -49,7 +57,16 @@ static void heartrate_adapter_remove(struct btd_profile *p,
 static int heartrate_device_probe(struct btd_profile *p,
 				struct btd_device *device, GSList *uuids)
 {
-	return heartrate_device_register(device);
+	GSList *primaries;
+	GSList *l;
+
+	primaries = btd_device_get_primaries(device);
+
+	l = g_slist_find_custom(primaries, HEART_RATE_UUID, primary_uuid_cmp);
+	if (l == NULL)
+		return -EINVAL;
+
+	return heartrate_device_register(device, l->data);
 }
 
 static void heartrate_device_remove(struct btd_profile *p,
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 05/13] heartrate: Discover Heart Rate Measurement CCC
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (3 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 04/13] heartrate: Discover HRS characteristics Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 06/13] heartrate: Read Body Sensor Location characteristics Andrzej Kaczmarek
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

This patch adds support to discover CCC descriptor for Heart Rate
Measurement characteristic.
---
 profiles/heartrate/heartrate.c | 66 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index a6733d3..d3d6d43 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -52,6 +52,7 @@ struct heartrate {
 	struct att_range		*svc_range;	/* primary svc range */
 
 	uint16_t			measurement_val_handle;
+	uint16_t			measurement_ccc_handle;
 	uint16_t			hrcp_val_handle;
 };
 
@@ -112,6 +113,65 @@ static void destroy_heartrate_adapter(gpointer user_data)
 	g_free(hradapter);
 }
 
+static void discover_ccc_cb(guint8 status, const guint8 *pdu,
+						guint16 len, gpointer user_data)
+{
+	struct heartrate *hr = user_data;
+	struct att_data_list *list;
+	uint8_t format;
+	int i;
+
+	if (status != 0) {
+		error("Discover Heart Rate Measurement descriptors failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	list = dec_find_info_resp(pdu, len, &format);
+	if (list == NULL)
+		return;
+
+	if (format != ATT_FIND_INFO_RESP_FMT_16BIT)
+		goto done;
+
+	for (i = 0; i < list->num; i++) {
+		uint8_t *value;
+		uint16_t handle, uuid;
+
+		value = list->data[i];
+		handle = att_get_u16(value);
+		uuid = att_get_u16(value + 2);
+
+		if (uuid == GATT_CLIENT_CHARAC_CFG_UUID) {
+			hr->measurement_ccc_handle = handle;
+			break;
+		}
+	}
+
+done:
+	att_data_list_free(list);
+}
+
+static void discover_measurement_ccc(struct heartrate *hr,
+				struct gatt_char *c, struct gatt_char *c_next)
+{
+	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 != hr->svc_range->end) {
+		end = hr->svc_range->end;
+	} else {
+		return;
+	}
+
+	gatt_find_info(hr->attrib, start, end, discover_ccc_cb, hr);
+}
+
 static void discover_char_cb(GSList *chars, guint8 status, gpointer user_data)
 {
 	struct heartrate *hr = user_data;
@@ -126,8 +186,12 @@ static void discover_char_cb(GSList *chars, guint8 status, gpointer user_data)
 		struct gatt_char *c = chars->data;
 
 		if (g_strcmp0(c->uuid, HEART_RATE_MEASUREMENT_UUID) == 0) {
+			struct gatt_char *c_next =
+				(chars->next ? chars->next->data : NULL);
+
 			hr->measurement_val_handle = c->value_handle;
-			/* TODO: discover CCC handle */
+
+			discover_measurement_ccc(hr, c, c_next);
 		} else if (g_strcmp0(c->uuid, BODY_SENSOR_LOCATION_UUID) == 0) {
 			DBG("Body Sensor Location supported");
 			/* TODO: read characterictic value */
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 06/13] heartrate: Read Body Sensor Location characteristics
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (4 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 05/13] heartrate: Discover Heart Rate Measurement CCC Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 07/13] heartrate: Add HeartRateManager interface Andrzej Kaczmarek
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Rafal Garbat

From: Rafal Garbat <rafal.garbat@tieto.com>

This patch adds support to read and store Body Sensor Location
characteristic value.
---
 profiles/heartrate/heartrate.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index d3d6d43..2547f9b 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -54,6 +54,9 @@ struct heartrate {
 	uint16_t			measurement_val_handle;
 	uint16_t			measurement_ccc_handle;
 	uint16_t			hrcp_val_handle;
+
+	gboolean			has_location;
+	uint8_t				location;
 };
 
 static GSList *heartrate_adapters = NULL;
@@ -113,6 +116,34 @@ static void destroy_heartrate_adapter(gpointer user_data)
 	g_free(hradapter);
 }
 
+static void read_sensor_location_cb(guint8 status, const guint8 *pdu,
+						guint16 len, gpointer user_data)
+{
+	struct heartrate *hr = user_data;
+	uint8_t value;
+	ssize_t vlen;
+
+	if (status != 0) {
+		error("Body Sensor Location read failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	vlen = dec_read_resp(pdu, len, &value, sizeof(value));
+	if (vlen < 0) {
+		error("Protocol error");
+		return;
+	}
+
+	if (vlen != sizeof(value)) {
+		error("Invalid length for Body Sensor Location");
+		return;
+	}
+
+	hr->has_location = TRUE;
+	hr->location = value;
+}
+
 static void discover_ccc_cb(guint8 status, const guint8 *pdu,
 						guint16 len, gpointer user_data)
 {
@@ -194,7 +225,9 @@ static void discover_char_cb(GSList *chars, guint8 status, gpointer user_data)
 			discover_measurement_ccc(hr, c, c_next);
 		} else if (g_strcmp0(c->uuid, BODY_SENSOR_LOCATION_UUID) == 0) {
 			DBG("Body Sensor Location supported");
-			/* TODO: read characterictic value */
+
+			gatt_read_char(hr->attrib, c->value_handle, 0,
+						read_sensor_location_cb, hr);
 		} else if (g_strcmp0(c->uuid,
 					HEART_RATE_CONTROL_POINT_UUID) == 0) {
 			DBG("Heart Rate Control Point supported");
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 07/13] heartrate: Add HeartRateManager interface
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (5 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 06/13] heartrate: Read Body Sensor Location characteristics Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 08/13] heartrate: Add support to enable notifications Andrzej Kaczmarek
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Rafal Garbat

From: Rafal Garbat <rafal.garbat@tieto.com>

This patch adds support for org.bluez.HeartRateManager interface on
adapters which allows to register and unregister per-adapter watcher.
---
 profiles/heartrate/heartrate.c | 154 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 153 insertions(+), 1 deletion(-)

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index 2547f9b..b07a343 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -24,13 +24,16 @@
 #include <config.h>
 #endif
 
+#include <gdbus.h>
 #include <errno.h>
 #include <stdbool.h>
 #include <glib.h>
 #include <bluetooth/uuid.h>
 
 #include "adapter.h"
+#include "dbus-common.h"
 #include "device.h"
+#include "error.h"
 #include "gattrib.h"
 #include "att.h"
 #include "gatt.h"
@@ -38,9 +41,12 @@
 #include "log.h"
 #include "heartrate.h"
 
+#define HEART_RATE_MANAGER_INTERFACE	"org.bluez.HeartRateManager"
+
 struct heartrate_adapter {
 	struct btd_adapter	*adapter;
 	GSList			*devices;
+	GSList			*watchers;
 };
 
 struct heartrate {
@@ -59,6 +65,13 @@ struct heartrate {
 	uint8_t				location;
 };
 
+struct watcher {
+	struct heartrate_adapter	*hradapter;
+	guint				id;
+	char				*srv;
+	char				*path;
+};
+
 static GSList *heartrate_adapters = NULL;
 
 static gint cmp_adapter(gconstpointer a, gconstpointer b)
@@ -83,6 +96,19 @@ static gint cmp_device(gconstpointer a, gconstpointer b)
 	return -1;
 }
 
+static gint cmp_watcher(gconstpointer a, gconstpointer b)
+{
+	const struct watcher *watcher = a;
+	const struct watcher *match = b;
+	int ret;
+
+	ret = g_strcmp0(watcher->srv, match->srv);
+	if (ret != 0)
+		return ret;
+
+	return g_strcmp0(watcher->path, match->path);
+}
+
 static struct heartrate_adapter *
 find_heartrate_adapter(struct btd_adapter *adapter)
 {
@@ -94,6 +120,34 @@ find_heartrate_adapter(struct btd_adapter *adapter)
 	return l->data;
 }
 
+static void destroy_watcher(gpointer user_data)
+{
+	struct watcher *watcher = user_data;
+
+	g_free(watcher->path);
+	g_free(watcher->srv);
+	g_free(watcher);
+}
+
+static struct watcher *find_watcher(GSList *list, const char *sender,
+							const char *path)
+{
+	struct watcher *match;
+	GSList *l;
+
+	match = g_new0(struct watcher, 1);
+	match->srv = g_strdup(sender);
+	match->path = g_strdup(path);
+
+	l = g_slist_find_custom(list, match, cmp_watcher);
+	destroy_watcher(match);
+
+	if (l != NULL)
+		return l->data;
+
+	return NULL;
+}
+
 static void destroy_heartrate(gpointer user_data)
 {
 	struct heartrate *hr = user_data;
@@ -109,10 +163,19 @@ static void destroy_heartrate(gpointer user_data)
 	g_free(hr);
 }
 
+static void remove_watcher(gpointer user_data)
+{
+	struct watcher *watcher = user_data;
+
+	g_dbus_remove_watch(btd_get_dbus_connection(), watcher->id);
+}
+
 static void destroy_heartrate_adapter(gpointer user_data)
 {
 	struct heartrate_adapter *hradapter = user_data;
 
+	g_slist_free_full(hradapter->watchers, remove_watcher);
+
 	g_free(hradapter);
 }
 
@@ -258,6 +321,81 @@ static void attio_disconnected_cb(gpointer user_data)
 	hr->attrib = NULL;
 }
 
+static void watcher_exit_cb(DBusConnection *conn, void *user_data)
+{
+	struct watcher *watcher = user_data;
+	struct heartrate_adapter *hradapter = watcher->hradapter;
+
+	DBG("heartrate watcher [%s] disconnected", watcher->path);
+
+	hradapter->watchers = g_slist_remove(hradapter->watchers, watcher);
+	g_dbus_remove_watch(conn, watcher->id);
+}
+
+static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct heartrate_adapter *hradapter = data;
+	struct watcher *watcher;
+	const char *sender = dbus_message_get_sender(msg);
+	char *path;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	watcher = find_watcher(hradapter->watchers, sender, path);
+	if (watcher != NULL)
+		return btd_error_already_exists(msg);
+
+	watcher = g_new0(struct watcher, 1);
+	watcher->hradapter = hradapter;
+	watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit_cb,
+						watcher, destroy_watcher);
+	watcher->srv = g_strdup(sender);
+	watcher->path = g_strdup(path);
+
+	hradapter->watchers = g_slist_prepend(hradapter->watchers, watcher);
+
+	DBG("heartrate watcher [%s] registered", path);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct heartrate_adapter *hradapter = data;
+	struct watcher *watcher;
+	const char *sender = dbus_message_get_sender(msg);
+	char *path;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return btd_error_invalid_args(msg);
+
+	watcher = find_watcher(hradapter->watchers, sender, path);
+	if (watcher == NULL)
+		return btd_error_does_not_exist(msg);
+
+	hradapter->watchers = g_slist_remove(hradapter->watchers, watcher);
+	g_dbus_remove_watch(conn, watcher->id);
+
+	DBG("heartrate watcher [%s] unregistered", path);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable heartrate_manager_methods[] = {
+	{ GDBUS_METHOD("RegisterWatcher",
+			GDBUS_ARGS({ "agent", "o" }), NULL,
+			register_watcher) },
+	{ GDBUS_METHOD("UnregisterWatcher",
+			GDBUS_ARGS({ "agent", "o" }), NULL,
+			unregister_watcher) },
+	{ }
+};
+
 int heartrate_adapter_register(struct btd_adapter *adapter)
 {
 	struct heartrate_adapter *hradapter;
@@ -267,6 +405,18 @@ int heartrate_adapter_register(struct btd_adapter *adapter)
 
 	heartrate_adapters = g_slist_prepend(heartrate_adapters, hradapter);
 
+	if (!g_dbus_register_interface(btd_get_dbus_connection(),
+						adapter_get_path(adapter),
+						HEART_RATE_MANAGER_INTERFACE,
+						heartrate_manager_methods,
+						NULL, NULL, hradapter,
+						destroy_heartrate_adapter)) {
+		error("D-Bus failed to register %s interface",
+						HEART_RATE_MANAGER_INTERFACE);
+		destroy_heartrate_adapter(hradapter);
+		return -EIO;
+	}
+
 	return 0;
 }
 
@@ -280,7 +430,9 @@ void heartrate_adapter_unregister(struct btd_adapter *adapter)
 
 	heartrate_adapters = g_slist_remove(heartrate_adapters, hradapter);
 
-	destroy_heartrate_adapter(hradapter);
+	g_dbus_unregister_interface(btd_get_dbus_connection(),
+					adapter_get_path(hradapter->adapter),
+					HEART_RATE_MANAGER_INTERFACE);
 }
 
 int heartrate_device_register(struct btd_device *device,
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 08/13] heartrate: Add support to enable notifications
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (6 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 07/13] heartrate: Add HeartRateManager interface Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 09/13] heartrate: Process measurement notifications Andrzej Kaczmarek
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

This patch adds support to enable notifications for Heart Rate Measurement
characteristic value. Notifications are enabled automatically when at
least one watcher is registered and disabled otherwise.
---
 profiles/heartrate/heartrate.c | 67 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index b07a343..dda030b 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -207,6 +207,17 @@ static void read_sensor_location_cb(guint8 status, const guint8 *pdu,
 	hr->location = value;
 }
 
+static void char_write_cb(guint8 status, const guint8 *pdu, guint16 len,
+							gpointer user_data)
+{
+	char *msg = user_data;
+
+	if (status != 0)
+		error("%s failed", msg);
+
+	g_free(msg);
+}
+
 static void discover_ccc_cb(guint8 status, const guint8 *pdu,
 						guint16 len, gpointer user_data)
 {
@@ -237,7 +248,20 @@ static void discover_ccc_cb(guint8 status, const guint8 *pdu,
 		uuid = att_get_u16(value + 2);
 
 		if (uuid == GATT_CLIENT_CHARAC_CFG_UUID) {
+			uint8_t value[2];
+			char *msg;
+
 			hr->measurement_ccc_handle = handle;
+
+			if (g_slist_length(hr->hradapter->watchers) == 0)
+				break;
+
+			att_put_u16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
+			msg = g_strdup("Enable measurement");
+
+			gatt_write_char(hr->attrib, handle, value,
+					sizeof(value), char_write_cb, msg);
+
 			break;
 		}
 	}
@@ -299,6 +323,40 @@ static void discover_char_cb(GSList *chars, guint8 status, gpointer user_data)
 	}
 }
 
+static void enable_measurement(gpointer data, gpointer user_data)
+{
+	struct heartrate *hr = data;
+	uint16_t handle = hr->measurement_ccc_handle;
+	uint8_t value[2];
+	char *msg;
+
+	if (hr->attrib == NULL || !handle)
+		return;
+
+	att_put_u16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
+	msg = g_strdup("Enable measurement");
+
+	gatt_write_char(hr->attrib, handle, value, sizeof(value),
+							char_write_cb, msg);
+}
+
+static void disable_measurement(gpointer data, gpointer user_data)
+{
+	struct heartrate *hr = data;
+	uint16_t handle = hr->measurement_ccc_handle;
+	uint8_t value[2];
+	char *msg;
+
+	if (hr->attrib == NULL || !handle)
+		return;
+
+	att_put_u16(0x0000, value);
+	msg = g_strdup("Disable measurement");
+
+	gatt_write_char(hr->attrib, handle, value, sizeof(value),
+							char_write_cb, msg);
+}
+
 static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 {
 	struct heartrate *hr = user_data;
@@ -330,6 +388,9 @@ static void watcher_exit_cb(DBusConnection *conn, void *user_data)
 
 	hradapter->watchers = g_slist_remove(hradapter->watchers, watcher);
 	g_dbus_remove_watch(conn, watcher->id);
+
+	if (g_slist_length(hradapter->watchers) == 0)
+		g_slist_foreach(hradapter->devices, disable_measurement, 0);
 }
 
 static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
@@ -355,6 +416,9 @@ static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
 	watcher->srv = g_strdup(sender);
 	watcher->path = g_strdup(path);
 
+	if (g_slist_length(hradapter->watchers) == 0)
+		g_slist_foreach(hradapter->devices, enable_measurement, 0);
+
 	hradapter->watchers = g_slist_prepend(hradapter->watchers, watcher);
 
 	DBG("heartrate watcher [%s] registered", path);
@@ -381,6 +445,9 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
 	hradapter->watchers = g_slist_remove(hradapter->watchers, watcher);
 	g_dbus_remove_watch(conn, watcher->id);
 
+	if (g_slist_length(hradapter->watchers) == 0)
+		g_slist_foreach(hradapter->devices, disable_measurement, 0);
+
 	DBG("heartrate watcher [%s] unregistered", path);
 
 	return dbus_message_new_method_return(msg);
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 09/13] heartrate: Process measurement notifications
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (7 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 08/13] heartrate: Add support to enable notifications Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 10/13] heartrate: Add support to reset Energy Expended Andrzej Kaczmarek
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

This patch adds processing of received Heart Rate Measurement
characteristic notifications and sends processed data to registered
watchers.
---
 profiles/heartrate/heartrate.c | 167 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 166 insertions(+), 1 deletion(-)

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index dda030b..ba1c1fa 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -42,6 +42,13 @@
 #include "heartrate.h"
 
 #define HEART_RATE_MANAGER_INTERFACE	"org.bluez.HeartRateManager"
+#define HEART_RATE_WATCHER_INTERFACE	"org.bluez.HeartRateWatcher"
+
+#define HR_VALUE_FORMAT		0x01
+#define SENSOR_CONTACT_DETECTED	0x02
+#define SENSOR_CONTACT_SUPPORT	0x04
+#define ENERGY_EXP_STATUS	0x08
+#define RR_INTERVAL		0x10
 
 struct heartrate_adapter {
 	struct btd_adapter	*adapter;
@@ -54,6 +61,7 @@ struct heartrate {
 	struct heartrate_adapter	*hradapter;
 	GAttrib				*attrib;
 	guint				attioid;
+	guint				attionotid;
 
 	struct att_range		*svc_range;	/* primary svc range */
 
@@ -72,6 +80,17 @@ struct watcher {
 	char				*path;
 };
 
+struct measurement {
+	struct heartrate	*hr;
+	uint16_t		value;
+	gboolean		has_energy;
+	uint16_t		energy;
+	gboolean		has_contact;
+	gboolean		contact;
+	uint16_t		num_interval;
+	uint16_t		*interval;
+};
+
 static GSList *heartrate_adapters = NULL;
 
 static gint cmp_adapter(gconstpointer a, gconstpointer b)
@@ -155,8 +174,10 @@ static void destroy_heartrate(gpointer user_data)
 	if (hr->attioid > 0)
 		btd_device_remove_attio_callback(hr->dev, hr->attioid);
 
-	if (hr->attrib != NULL)
+	if (hr->attrib != NULL) {
+		g_attrib_unregister(hr->attrib, hr->attionotid);
 		g_attrib_unref(hr->attrib);
+	}
 
 	btd_device_unref(hr->dev);
 	g_free(hr->svc_range);
@@ -357,6 +378,142 @@ static void disable_measurement(gpointer data, gpointer user_data)
 							char_write_cb, msg);
 }
 
+static void update_watcher(gpointer data, gpointer user_data)
+{
+	struct watcher *w = data;
+	struct measurement *m = user_data;
+	struct heartrate *hr = m->hr;
+	const gchar *path = device_get_path(hr->dev);
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call(w->srv, w->path,
+			HEART_RATE_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, "Value", DBUS_TYPE_UINT16, &m->value);
+
+	if (m->has_energy)
+		dict_append_entry(&dict, "Energy", DBUS_TYPE_UINT16,
+								&m->energy);
+
+	if (m->has_contact)
+		dict_append_entry(&dict, "Contact", DBUS_TYPE_BOOLEAN,
+								&m->contact);
+
+	if (m->num_interval > 0)
+		dict_append_array(&dict, "Interval", DBUS_TYPE_UINT16,
+						&m->interval, m->num_interval);
+
+	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 process_measurement(struct heartrate *hr, const uint8_t *pdu,
+								uint16_t len)
+{
+	struct measurement m;
+	uint8_t flags;
+
+	flags = *pdu;
+
+	pdu++;
+	len--;
+
+	memset(&m, 0, sizeof(m));
+
+	if (flags & HR_VALUE_FORMAT) {
+		if (len < 2) {
+			error("Heart Rate Measurement field missing");
+			return;
+		}
+
+		m.value = att_get_u16(pdu);
+		pdu += 2;
+		len -= 2;
+	} else {
+		if (len < 1) {
+			error("Heart Rate Measurement field missing");
+			return;
+		}
+
+		m.value = *pdu;
+		pdu++;
+		len--;
+	}
+
+	if (flags & ENERGY_EXP_STATUS) {
+		if (len < 2) {
+			error("Energy Expended field missing");
+			return;
+		}
+
+		m.has_energy = TRUE;
+		m.energy = att_get_u16(pdu);
+		pdu += 2;
+		len -= 2;
+	}
+
+	if (flags & RR_INTERVAL) {
+		int i;
+
+		if (len == 0 || (len % 2 != 0)) {
+			error("RR-Interval field malformed");
+			return;
+		}
+
+		m.num_interval = len / 2;
+		m.interval = g_new(uint16_t, m.num_interval);
+
+		for (i = 0; i < m.num_interval; pdu += 2, i++)
+			m.interval[i] = att_get_u16(pdu);
+	}
+
+	if (flags & SENSOR_CONTACT_SUPPORT) {
+		m.has_contact = TRUE;
+		m.contact = !!(flags & SENSOR_CONTACT_DETECTED);
+	}
+
+	/* Notify all registered watchers */
+	m.hr = hr;
+	g_slist_foreach(hr->hradapter->watchers, update_watcher, &m);
+
+	g_free(m.interval);
+}
+
+static void notify_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+	struct heartrate *hr = user_data;
+	uint16_t handle;
+
+	/* should be at least opcode (1b) + handle (2b) */
+	if (len < 3) {
+		error("Invalid PDU received");
+		return;
+	}
+
+	handle = att_get_u16(pdu + 1);
+	if (handle != hr->measurement_val_handle) {
+		error("Unexpected handle: 0x%04x", handle);
+		return;
+	}
+
+	process_measurement(hr, pdu + 3, len - 3);
+}
+
 static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 {
 	struct heartrate *hr = user_data;
@@ -365,6 +522,9 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 
 	hr->attrib = g_attrib_ref(attrib);
 
+	hr->attionotid = g_attrib_register(hr->attrib, ATT_OP_HANDLE_NOTIFY,
+						notify_handler, hr, NULL);
+
 	gatt_discover_char(hr->attrib, hr->svc_range->start, hr->svc_range->end,
 						NULL, discover_char_cb, hr);
 }
@@ -375,6 +535,11 @@ static void attio_disconnected_cb(gpointer user_data)
 
 	DBG("");
 
+	if (hr->attionotid > 0) {
+		g_attrib_unregister(hr->attrib, hr->attionotid);
+		hr->attionotid = 0;
+	}
+
 	g_attrib_unref(hr->attrib);
 	hr->attrib = NULL;
 }
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 10/13] heartrate: Add support to reset Energy Expended
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (8 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 09/13] heartrate: Process measurement notifications Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 11/13] heartrate: Add GetProperties method Andrzej Kaczmarek
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

This patch adds Reset method on HeartRate interface to reset Energy
Expended.
---
 profiles/heartrate/heartrate.c | 45 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index ba1c1fa..add34b8 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -41,6 +41,7 @@
 #include "log.h"
 #include "heartrate.h"
 
+#define HEART_RATE_INTERFACE		"org.bluez.HeartRate"
 #define HEART_RATE_MANAGER_INTERFACE	"org.bluez.HeartRateManager"
 #define HEART_RATE_WATCHER_INTERFACE	"org.bluez.HeartRateWatcher"
 
@@ -628,6 +629,35 @@ static const GDBusMethodTable heartrate_manager_methods[] = {
 	{ }
 };
 
+static DBusMessage *hrcp_reset(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct heartrate *hr = data;
+	uint8_t value;
+	char *vmsg;
+
+	if (!hr->hrcp_val_handle)
+		return btd_error_not_supported(msg);
+
+	if (!hr->attrib)
+		return btd_error_not_available(msg);
+
+	value = 0x01;
+	vmsg = g_strdup("Reset Control Point");
+	gatt_write_char(hr->attrib, hr->hrcp_val_handle, &value,
+					sizeof(value), char_write_cb, vmsg);
+
+	DBG("Energy Expended Value has been reset");
+
+	return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable heartrate_device_methods[] = {
+	{ GDBUS_METHOD("Reset", NULL, NULL,
+			hrcp_reset) },
+	{ }
+};
+
 int heartrate_adapter_register(struct btd_adapter *adapter)
 {
 	struct heartrate_adapter *hradapter;
@@ -685,6 +715,18 @@ int heartrate_device_register(struct btd_device *device,
 	hr->dev = btd_device_ref(device);
 	hr->hradapter = hradapter;
 
+	if (!g_dbus_register_interface(btd_get_dbus_connection(),
+						device_get_path(device),
+						HEART_RATE_INTERFACE,
+						heartrate_device_methods,
+						NULL, NULL, hr,
+						destroy_heartrate)) {
+		error("D-Bus failed to register %s interface",
+						HEART_RATE_INTERFACE);
+		destroy_heartrate(hr);
+		return -EIO;
+	}
+
 	hr->svc_range = g_new0(struct att_range, 1);
 	hr->svc_range->start = prim->range.start;
 	hr->svc_range->end = prim->range.end;
@@ -718,5 +760,6 @@ void heartrate_device_unregister(struct btd_device *device)
 
 	hradapter->devices = g_slist_remove(hradapter->devices, hr);
 
-	destroy_heartrate(hr);
+	g_dbus_unregister_interface(btd_get_dbus_connection(),
+				device_get_path(device), HEART_RATE_INTERFACE);
 }
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 11/13] heartrate: Add GetProperties method
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (9 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 10/13] heartrate: Add support to reset Energy Expended Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 12/13] heartrate: Add HeartRateWatcher interface to default policy Andrzej Kaczmarek
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Rafal Garbat

From: Rafal Garbat <rafal.garbat@tieto.com>

---
 profiles/heartrate/heartrate.c | 61 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index add34b8..81dd5cc 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -94,6 +94,25 @@ struct measurement {
 
 static GSList *heartrate_adapters = NULL;
 
+static const char * const location_enum[] = {
+	"Other",
+	"Chest",
+	"Wrist",
+	"Finger",
+	"Hand",
+	"Earlobe",
+	"Foot",
+};
+
+static const gchar *location2str(uint8_t value)
+{
+	 if (value < G_N_ELEMENTS(location_enum))
+		return location_enum[value];
+
+	error("Body Sensor Location [%d] is RFU", value);
+	return NULL;
+}
+
 static gint cmp_adapter(gconstpointer a, gconstpointer b)
 {
 	const struct heartrate_adapter *hradapter = a;
@@ -629,6 +648,45 @@ static const GDBusMethodTable heartrate_manager_methods[] = {
 	{ }
 };
 
+static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct heartrate *hr = data;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	DBusMessage *reply;
+	gboolean has_reset;
+
+	reply = dbus_message_new_method_return(msg);
+	if (reply == NULL)
+		return NULL;
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	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);
+
+	if (hr->has_location) {
+		char *loc = g_strdup(location2str(hr->location));
+
+		if (loc) {
+			dict_append_entry(&dict, "Location",
+						DBUS_TYPE_STRING, &loc);
+			g_free(loc);
+		}
+	}
+
+	has_reset = !!hr->hrcp_val_handle;
+	dict_append_entry(&dict, "ResetSupported", DBUS_TYPE_BOOLEAN,
+								&has_reset);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	return reply;
+}
+
 static DBusMessage *hrcp_reset(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
@@ -653,6 +711,9 @@ static DBusMessage *hrcp_reset(DBusConnection *conn, DBusMessage *msg,
 }
 
 static const GDBusMethodTable heartrate_device_methods[] = {
+	{ GDBUS_METHOD("GetProperties",
+			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+			get_properties) },
 	{ GDBUS_METHOD("Reset", NULL, NULL,
 			hrcp_reset) },
 	{ }
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 12/13] heartrate: Add HeartRateWatcher interface to default policy
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (10 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 11/13] heartrate: Add GetProperties method Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-25 14:27 ` [PATCH v8 13/13] heartrate: Add test script Andrzej Kaczmarek
  2012-09-28 10:25 ` [PATCH v8 00/13] Heart Rate Profile plugin Johan Hedberg
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Rafal Garbat

From: Rafal Garbat <rafal.garbat@tieto.com>

---
 src/bluetooth.conf | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 664dbd9..77a9371 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -16,6 +16,7 @@
     <allow send_interface="org.bluez.MediaPlayer"/>
     <allow send_interface="org.bluez.Watcher"/>
     <allow send_interface="org.bluez.ThermometerWatcher"/>
+    <allow send_interface="org.bluez.HeartRateWatcher"/>
   </policy>
 
   <policy at_console="true">
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v8 13/13] heartrate: Add test script
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (11 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 12/13] heartrate: Add HeartRateWatcher interface to default policy Andrzej Kaczmarek
@ 2012-09-25 14:27 ` Andrzej Kaczmarek
  2012-09-28 10:25 ` [PATCH v8 00/13] Heart Rate Profile plugin Johan Hedberg
  13 siblings, 0 replies; 19+ messages in thread
From: Andrzej Kaczmarek @ 2012-09-25 14:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Rafal Garbat

From: Rafal Garbat <rafal.garbat@tieto.com>

---
 Makefile.tools      |   3 +-
 test/test-heartrate | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100755 test/test-heartrate

diff --git a/Makefile.tools b/Makefile.tools
index 15fe4e2..81feb75 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -212,4 +212,5 @@ EXTRA_DIST += test/sap_client.py test/hsplay test/hsmicro \
 		test/test-proximity test/test-thermometer test/test-profile \
 		test/test-health test/test-health-sink test/service-record.dtd \
 		test/service-did.xml test/service-spp.xml test/service-opp.xml \
-		test/service-ftp.xml test/simple-player test/test-nap
+		test/service-ftp.xml test/simple-player test/test-nap \
+		test/test-heartrate
diff --git a/test/test-heartrate b/test/test-heartrate
new file mode 100755
index 0000000..316375d
--- /dev/null
+++ b/test/test-heartrate
@@ -0,0 +1,103 @@
+#!/usr/bin/python
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+'''
+Heart Rate Monitor test script
+'''
+
+import gobject
+
+import sys
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+from optparse import OptionParser, make_option
+
+class Watcher(dbus.service.Object):
+	@dbus.service.method("org.bluez.HeartRateWatcher",
+					in_signature="oa{sv}", out_signature="")
+	def MeasurementReceived(self, device, measure):
+		print("Measurement received from %s" % device)
+		print("Value: ", measure["Value"])
+
+		if "Energy" in measure:
+			print("Energy: ", measure["Energy"])
+
+		if "Contact" in measure:
+			print("Contact: ", measure["Contact"])
+
+		if "Interval" in measure:
+			for i in measure["Interval"]:
+				print("Interval: ", i)
+
+if __name__ == "__main__":
+	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+	bus = dbus.SystemBus()
+
+	manager = dbus.Interface(bus.get_object("org.bluez", "/"),
+					"org.bluez.Manager")
+
+	option_list = [
+		make_option("-i", "--adapter", action="store",
+			type="string", dest="adapter"),
+		make_option("-b", "--device", action="store",
+			type="string", dest="address"),
+		]
+
+	parser = OptionParser(option_list=option_list)
+
+	(options, args) = parser.parse_args()
+
+	if not options.address:
+		print("Usage: %s [-i <adapter>] -b <bdaddr> [cmd]" % (sys.argv[0]))
+		print("Possible commands:")
+		print("\tReset")
+		sys.exit(1)
+
+	if options.adapter:
+		adapter_path = manager.FindAdapter(options.adapter)
+	else:
+		adapter_path = manager.DefaultAdapter()
+
+	adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
+							"org.bluez.Adapter")
+
+	heartrateManager = dbus.Interface(bus.get_object("org.bluez",
+				adapter_path), "org.bluez.HeartRateManager")
+
+	path = "/test/watcher"
+	heartrateManager.RegisterWatcher(path)
+
+	device_path = adapter.FindDevice(options.address)
+
+	device = dbus.Interface(bus.get_object("org.bluez", device_path),
+							"org.bluez.Device")
+
+	heartrate = dbus.Interface(bus.get_object("org.bluez",
+					device_path), "org.bluez.HeartRate")
+
+	watcher = Watcher(bus, path)
+
+	properties = heartrate.GetProperties()
+
+	if "Location" in properties:
+		print("Sensor location: %s" % properties["Location"])
+	else:
+		print("Sensor location is not supported")
+
+	if len(args) > 0:
+		if args[0] == "Reset":
+			reset_sup = properties["ResetSupported"]
+			if reset_sup:
+				heartrate.Reset()
+			else:
+				print("Reset not supported")
+				sys.exit(1)
+		else:
+			print("unknown command")
+			sys.exit(1)
+
+	mainloop = gobject.MainLoop()
+	mainloop.run()
-- 
1.7.11.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v8 00/13] Heart Rate Profile plugin
  2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
                   ` (12 preceding siblings ...)
  2012-09-25 14:27 ` [PATCH v8 13/13] heartrate: Add test script Andrzej Kaczmarek
@ 2012-09-28 10:25 ` Johan Hedberg
  2012-09-28 12:55   ` Christian Cier-Zniewski
  13 siblings, 1 reply; 19+ messages in thread
From: Johan Hedberg @ 2012-09-28 10:25 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth

Hi Andrzej,

On Tue, Sep 25, 2012, Andrzej Kaczmarek wrote:
> Changes since v7:
> - rebased to latest upstream master (btd_profile changes)
> 
> 
> Andrzej Kaczmarek (6):
>   heartrate: Add attio callbacks
>   heartrate: Discover HRS characteristics
>   heartrate: Discover Heart Rate Measurement CCC
>   heartrate: Add support to enable notifications
>   heartrate: Process measurement notifications
>   heartrate: Add support to reset Energy Expended
> 
> Rafal Garbat (6):
>   heartrate: Add initial HRP client support
>   heartrate: Read Body Sensor Location characteristics
>   heartrate: Add HeartRateManager interface
>   heartrate: Add GetProperties method
>   heartrate: Add HeartRateWatcher interface to default policy
>   heartrate: Add test script
> 
> Santiago Carot-Nemesio (1):
>   Heart Rate Profile (HRP) client API
> 
>  Makefile.am                    |   9 +-
>  Makefile.tools                 |   3 +-
>  doc/heartrate-api.txt          |  84 +++++
>  lib/uuid.h                     |   5 +
>  profiles/heartrate/heartrate.c | 826 +++++++++++++++++++++++++++++++++++++++++
>  profiles/heartrate/heartrate.h |  27 ++
>  profiles/heartrate/main.c      |  52 +++
>  profiles/heartrate/manager.c   |  97 +++++
>  profiles/heartrate/manager.h   |  24 ++
>  src/bluetooth.conf             |   1 +
>  test/test-heartrate            | 103 +++++
>  11 files changed, 1228 insertions(+), 3 deletions(-)
>  create mode 100644 doc/heartrate-api.txt
>  create mode 100644 profiles/heartrate/heartrate.c
>  create mode 100644 profiles/heartrate/heartrate.h
>  create mode 100644 profiles/heartrate/main.c
>  create mode 100644 profiles/heartrate/manager.c
>  create mode 100644 profiles/heartrate/manager.h
>  create mode 100755 test/test-heartrate

All patches in this set have been applied. Thanks.

One notable change I did when applying was to the sensor location API.
The convention is to use lower case for string property values so I
change the API and code to follow this.

Johan

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v8 00/13] Heart Rate Profile plugin
  2012-09-28 10:25 ` [PATCH v8 00/13] Heart Rate Profile plugin Johan Hedberg
@ 2012-09-28 12:55   ` Christian Cier-Zniewski
  2012-09-28 13:16     ` Johan Hedberg
  0 siblings, 1 reply; 19+ messages in thread
From: Christian Cier-Zniewski @ 2012-09-28 12:55 UTC (permalink / raw)
  To: johan.hedberg, linux-bluetooth

Hello Johan,

On 28.09.2012 12:25, Johan Hedberg wrote:
>    Heart Rate Profile (HRP) client API
>
>   Makefile.am                    |   9 +-
>
> All patches in this set have been applied. Thanks.
>
>


I had to apply the following patch to get the heart rate profile working.
It is currently missing in HEAD although it was present in the patchset 
provided by Andrzej.

Christian

---

diff --git a/Makefile.am b/Makefile.am
index 3b37198..c27eb01 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -212,7 +212,7 @@ endif

  if GATTMODULES
  builtin_modules += thermometer alert time gatt_example proximity 
deviceinfo \
-                       gatt scanparam
+                       gatt scanparam heartrate
  builtin_sources += profiles/thermometer/main.c \
                         profiles/thermometer/manager.h \
                         profiles/thermometer/manager.c \




^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v8 00/13] Heart Rate Profile plugin
  2012-09-28 12:55   ` Christian Cier-Zniewski
@ 2012-09-28 13:16     ` Johan Hedberg
  2012-09-28 13:59       ` Johan Hedberg
  2012-09-28 14:07       ` Christian Cier-Zniewski
  0 siblings, 2 replies; 19+ messages in thread
From: Johan Hedberg @ 2012-09-28 13:16 UTC (permalink / raw)
  To: Christian Cier-Zniewski; +Cc: linux-bluetooth

Hi,

On Fri, Sep 28, 2012, Christian Cier-Zniewski wrote:
> Hello Johan,
> 
> On 28.09.2012 12:25, Johan Hedberg wrote:
> >   Heart Rate Profile (HRP) client API
> >
> >  Makefile.am                    |   9 +-
> >
> >All patches in this set have been applied. Thanks.
> >
> >
> 
> 
> I had to apply the following patch to get the heart rate profile working.
> It is currently missing in HEAD although it was present in the
> patchset provided by Andrzej.
> 
> Christian
> 
> ---
> 
> diff --git a/Makefile.am b/Makefile.am
> index 3b37198..c27eb01 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -212,7 +212,7 @@ endif
> 
>  if GATTMODULES
>  builtin_modules += thermometer alert time gatt_example proximity
> deviceinfo \
> -                       gatt scanparam
> +                       gatt scanparam heartrate
>  builtin_sources += profiles/thermometer/main.c \
>                         profiles/thermometer/manager.h \
>                         profiles/thermometer/manager.c \
> 

The Makefile.am changes had conflicts because of other GATT profiles I
applied earlier, so I had to completely manually fix this and probably
made some mistake. Could you please send a proper git patch for this and
I'll apply it?

Johan

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v8 00/13] Heart Rate Profile plugin
  2012-09-28 13:16     ` Johan Hedberg
@ 2012-09-28 13:59       ` Johan Hedberg
  2012-09-28 14:07       ` Christian Cier-Zniewski
  1 sibling, 0 replies; 19+ messages in thread
From: Johan Hedberg @ 2012-09-28 13:59 UTC (permalink / raw)
  To: Christian Cier-Zniewski, linux-bluetooth

Hi,

On Fri, Sep 28, 2012, Johan Hedberg wrote:
> On Fri, Sep 28, 2012, Christian Cier-Zniewski wrote:
> > Hello Johan,
> > 
> > On 28.09.2012 12:25, Johan Hedberg wrote:
> > >   Heart Rate Profile (HRP) client API
> > >
> > >  Makefile.am                    |   9 +-
> > >
> > >All patches in this set have been applied. Thanks.
> > >
> > >
> > 
> > 
> > I had to apply the following patch to get the heart rate profile working.
> > It is currently missing in HEAD although it was present in the
> > patchset provided by Andrzej.
> > 
> > Christian
> > 
> > ---
> > 
> > diff --git a/Makefile.am b/Makefile.am
> > index 3b37198..c27eb01 100644
> > --- a/Makefile.am
> > +++ b/Makefile.am
> > @@ -212,7 +212,7 @@ endif
> > 
> >  if GATTMODULES
> >  builtin_modules += thermometer alert time gatt_example proximity
> > deviceinfo \
> > -                       gatt scanparam
> > +                       gatt scanparam heartrate
> >  builtin_sources += profiles/thermometer/main.c \
> >                         profiles/thermometer/manager.h \
> >                         profiles/thermometer/manager.c \
> > 
> 
> The Makefile.am changes had conflicts because of other GATT profiles I
> applied earlier, so I had to completely manually fix this and probably
> made some mistake. Could you please send a proper git patch for this and
> I'll apply it?

Nevermind, I went ahead and fixed it myself.

Johan

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v8 00/13] Heart Rate Profile plugin
  2012-09-28 13:16     ` Johan Hedberg
  2012-09-28 13:59       ` Johan Hedberg
@ 2012-09-28 14:07       ` Christian Cier-Zniewski
  1 sibling, 0 replies; 19+ messages in thread
From: Christian Cier-Zniewski @ 2012-09-28 14:07 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth

Hi,

Am 28.09.2012 15:16, schrieb Johan Hedberg:
> The Makefile.am changes had conflicts because of other GATT profiles I 
> applied earlier, so I had to completely manually fix this and probably 
> made some mistake. Could you please send a proper git patch for this 
> and I'll apply it? Johan 

Enable heart rate profile in Makefile.am.

---
  Makefile.am |    2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index 3b37198..c27eb01 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -212,7 +212,7 @@ endif

  if GATTMODULES
  builtin_modules += thermometer alert time gatt_example proximity 
deviceinfo \
-                       gatt scanparam
+                       gatt scanparam heartrate
  builtin_sources += profiles/thermometer/main.c \
                         profiles/thermometer/manager.h \
                         profiles/thermometer/manager.c \
--
1.7.10.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-09-28 14:07 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-25 14:27 [PATCH v8 00/13] Heart Rate Profile plugin Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 01/13] Heart Rate Profile (HRP) client API Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 02/13] heartrate: Add initial HRP client support Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 03/13] heartrate: Add attio callbacks Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 04/13] heartrate: Discover HRS characteristics Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 05/13] heartrate: Discover Heart Rate Measurement CCC Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 06/13] heartrate: Read Body Sensor Location characteristics Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 07/13] heartrate: Add HeartRateManager interface Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 08/13] heartrate: Add support to enable notifications Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 09/13] heartrate: Process measurement notifications Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 10/13] heartrate: Add support to reset Energy Expended Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 11/13] heartrate: Add GetProperties method Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 12/13] heartrate: Add HeartRateWatcher interface to default policy Andrzej Kaczmarek
2012-09-25 14:27 ` [PATCH v8 13/13] heartrate: Add test script Andrzej Kaczmarek
2012-09-28 10:25 ` [PATCH v8 00/13] Heart Rate Profile plugin Johan Hedberg
2012-09-28 12:55   ` Christian Cier-Zniewski
2012-09-28 13:16     ` Johan Hedberg
2012-09-28 13:59       ` Johan Hedberg
2012-09-28 14:07       ` Christian Cier-Zniewski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).