* Re: [PATCHv6 00/17] Bluetooth: Create AMP physical link
From: Andrei Emeltchenko @ 2012-09-20 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: mathewm, gustavo, marcel
In-Reply-To: <1347978509-12133-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
ping
On Tue, Sep 18, 2012 at 05:28:12PM +0300, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> This set of patches enhances A2MP protocol and creates physical
> link between AMP controllers. This is further iteration towards
> Bluetooth High Speed.
>
> Changes:
> * p6: Refactoring: moving code from pal.[ch] to amp.[ch]
> * p5: Fix issues reported by Mat in mailing list review
> * p4: Rebased against recent bluetooth-next, minor fixes
> * p3: Use hci_conn for representing physical link(type AMP_LINK) instead of
> struct phy_link, refactoring.
> * p2: Remove HCI callbacks and use amp_mgr global list, refactor code.
> * p1: Fixed locking issues, added basic logical link preparation.
> * v3: Remove workqueue from callback processing; change callback functions
> names according to reviewers recommendations; create global amp_mgr_list to
> have lookup to amp manager, physical and logical links so for those HCI events
> which might be identified by __handler__ we have lookup; remove extensive
> hexdump from gen_amp_key.
> * v2: Fix typos and bugs, add functionality: now physical connection
> might be established.
> * v1: Fix typos, change debug prints, refactor code for better
> splitting functionality.
>
> Andrei Emeltchenko (16):
> Bluetooth: Add HCI logical link cmds definitions
> Bluetooth: A2MP: Create amp_mgr global list
> Bluetooth: AMP: Use HCI cmd to Read AMP Info
> Bluetooth: AMP: Use HCI cmd to Read Loc AMP Assoc
> Bluetooth: A2MP: Process Discover Response
> Bluetooth: AMP: Physical link struct and heplers
> Bluetooth: AMP: Remote AMP ctrl definitions
> Bluetooth: AMP: Handle create / disc phylink req
> Bluetooth: A2MP: Process A2MP Getinfo Rsp
> Bluetooth: A2MP: Process A2MP Get AMP Assoc Rsp
> Bluetooth: Choose connection based on capabilities
> Bluetooth: AMP: Add AMP key calculation
> Bluetooth: AMP: Create Physical Link
> Bluetooth: AMP: Write remote AMP Assoc
> Bluetooth: A2MP: Add fallback to normal l2cap init sequence
> Bluetooth: AMP: Process Chan Selected event
>
> Dmitry Kasatkin (1):
> Bluetooth: Add function to derive AMP key using hmac
>
> include/net/bluetooth/a2mp.h | 22 ++
> include/net/bluetooth/amp.h | 47 +++++
> include/net/bluetooth/hci.h | 39 +++-
> include/net/bluetooth/hci_core.h | 11 +
> include/net/bluetooth/l2cap.h | 4 +
> net/bluetooth/Kconfig | 1 +
> net/bluetooth/Makefile | 2 +-
> net/bluetooth/a2mp.c | 423 +++++++++++++++++++++++++++++++++++---
> net/bluetooth/amp.c | 348 +++++++++++++++++++++++++++++++
> net/bluetooth/hci_event.c | 106 +++++++++-
> net/bluetooth/l2cap_core.c | 35 +++-
> 11 files changed, 1000 insertions(+), 38 deletions(-)
> create mode 100644 include/net/bluetooth/amp.h
> create mode 100644 net/bluetooth/amp.c
>
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 06/10] battery: Get Battery ID
From: Chen Ganir @ 2012-09-20 11:03 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <CAJdJm_MyO5Fq-rDWMnSm3pkR_Qj8ghCri8We0fXtaYVXtpzB6A@mail.gmail.com>
Anderson,
On 09/20/2012 01:46 PM, Anderson Lizardo wrote:
> Hi Chen,
>
> On Thu, Sep 20, 2012 at 4:27 AM, <chen.ganir@ti.com> wrote:
>> @@ -150,31 +200,35 @@ static void configure_battery_cb(GSList *characteristics, guint8 status,
>>
>> for (l = characteristics; l; l = l->next) {
>> struct gatt_char *c = l->data;
>> - struct characteristic *ch;
>> - uint16_t start, end;
>> -
>> - ch = g_new0(struct characteristic, 1);
>> - ch->attr.handle = c->handle;
>> - ch->attr.properties = c->properties;
>> - ch->attr.value_handle = c->value_handle;
>> - memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
>> - ch->batt = batt;
>>
>> - batt->chars = g_slist_append(batt->chars, ch);
>> -
>> - start = c->value_handle + 1;
>> -
>> - if (l->next != NULL) {
>> - struct gatt_char *c = l->next->data;
>> - if (start == c->handle)
>> + if (g_strcmp0(c->uuid, BATTERY_LEVEL_UUID) == 0) {
>
> Minor comment, but looks like it would be cleaner if you used:
>
> if (g_strcmp0(c->uuid, BATTERY_LEVEL_UUID) != 0)
> continue;
>
> and avoided all this shifting and one more level of indentation.
>
I'll change that. It does make more sense.
>> + 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->batt = batt;
>> +
>> + batt->chars = g_slist_append(batt->chars, ch);
>> +
>> + start = c->value_handle + 1;
>> +
>> + if (l->next != NULL) {
>> + struct gatt_char *c = l->next->data;
>> + if (start == c->handle)
>> + continue;
>> + end = c->handle - 1;
>> + } else if (c->value_handle != batt->svc_range->end)
>> + end = batt->svc_range->end;
>> + else
>> continue;
>> - end = c->handle - 1;
>> - } else if (c->value_handle != batt->svc_range->end)
>> - end = batt->svc_range->end;
>> - else
>> - continue;
>>
>> - gatt_find_info(batt->attrib, start, end, discover_desc_cb, ch);
>> + gatt_find_info(batt->attrib, start, end,
>> + discover_desc_cb, ch);
>> + }
>> }
>> }
>
> Regards,
>
Thanks,
--
BR,
Chen Ganir
^ permalink raw reply
* Re: [PATCH v3 00/10] Implement Generic battery and LE Battery client
From: Chen Ganir @ 2012-09-20 11:04 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <CAJdJm_MhZwRyD8JVsmm6QTWqhWh1x2FXkopTQqdmNy=td0aj8Q@mail.gmail.com>
Anderson,
On 09/20/2012 01:56 PM, Anderson Lizardo wrote:
> Hi Chen,
>
> On Thu, Sep 20, 2012 at 4:27 AM, <chen.ganir@ti.com> wrote:
>> From: Chen Ganir <chen.ganir@ti.com>
>>
>> This patch set replaces previous patch sets which implemented the LE battery
>> GATT Client. This patch set implements a generic device battery D-Bus interface
>> that can be used to get remote device battery status using D-Bus. In addition,
>> This patch set also implements the GATT Battery client, which uses the generic
>> device battery to expose LE device battery status.
>>
>> see doc/battery-api.txt and doc/device-api.txt for more information.
>>
>> This is version 2 of the patch set, including multiple style and other comments
>> reported on the ML. This version is rebased on the latest code.
>
> Besides some minor style comments (found on this last round of
> review), patch set looks good to me.
>
> Regards,
>
Thanks for the review !
I'll wait and see if there are any more comments before i send the next
patch set with fixes.
--
BR,
Chen Ganir
^ permalink raw reply
* Rebase against recent wireless-next
From: Andrei Emeltchenko @ 2012-09-20 11:05 UTC (permalink / raw)
To: linux-bluetooth, Gustavo Padovan
Hi Gustavo,
When we get rebased against wireless-next?
Best regards
Andrei Emeltchenko
^ permalink raw reply
* Re: [PATCH BlueZ v1] gatttool: Fix Characteristic descriptor discovery
From: Johan Hedberg @ 2012-09-20 11:11 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1348083476-21435-1-git-send-email-claudio.takahasi@openbossa.org>
Hi Claudio,
On Wed, Sep 19, 2012, Claudio Takahasi wrote:
> This patch fixes end condition for Characteristic Descriptor Discovery.
> This sub-procedure is complete when the Error Response is received and
> the Error Code is set to Attribute Not Found or the Find Information
> Response has an Attribute Handle that is equal to the Ending Handle of
> the request.
> ---
> attrib/interactive.c | 22 +++++++++++++---------
> 1 file changed, 13 insertions(+), 9 deletions(-)
Applied. Thanks.
Johan
^ permalink raw reply
* [PATCH v6 00/13] Heart Rate Profile plugin
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
Hi,
Here's v6 of heartrate plugin patches. After some thinking I decided to
refactor code a bit to keep it more compact and (hopefully) easier to
follow. Most important change here is that instead of nested structures
to hold all characteristics and descriptors I only store handles to few
attributes which are used later. This allows to remove some code lines,
mostly helper functions to traverse lists of structures in order to get
some attribute handle which is now accessible immediately.
So to sum up v5 vs. v6: less code, less patches, still works.
Comments are welcome.
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 | 4 +-
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 | 93 +++++
profiles/heartrate/manager.h | 24 ++
src/bluetooth.conf | 1 +
test/test-heartrate | 103 +++++
11 files changed, 1224 insertions(+), 4 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
* [PATCH v6 01/13] Heart Rate Profile (HRP) client API
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Santiago Carot-Nemesio
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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
* [PATCH v6 02/13] heartrate: Add initial HRP client support
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Rafal Garbat
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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 | 76 +++++++++++++++++++
profiles/heartrate/manager.h | 24 ++++++
7 files changed, 352 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..2a9326d
--- /dev/null
+++ b/profiles/heartrate/manager.c
@@ -0,0 +1,76 @@
+/*
+ *
+ * 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_adapter *adapter)
+{
+ return heartrate_adapter_register(adapter);
+}
+
+static void heartrate_adapter_remove(struct btd_adapter *adapter)
+{
+ heartrate_adapter_unregister(adapter);
+}
+
+static int heartrate_device_probe(struct btd_device *device, GSList *uuids)
+{
+ return heartrate_device_register(device);
+}
+
+static void heartrate_device_remove(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
* [PATCH v6 03/13] heartrate: Add attio callbacks
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
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
* [PATCH v6 04/13] heartrate: Discover HRS characteristics
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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 2a9326d..a0997bd 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_adapter *adapter)
{
return heartrate_adapter_register(adapter);
@@ -46,7 +54,16 @@ static void heartrate_adapter_remove(struct btd_adapter *adapter)
static int heartrate_device_probe(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_device *device)
--
1.7.11.3
^ permalink raw reply related
* [PATCH v6 05/13] heartrate: Discover Heart Rate Measurement CCC
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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
* [PATCH v6 06/13] heartrate: Read Body Sensor Location characteristics
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Rafal Garbat
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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..8c12101 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 != 1) {
+ 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
* [PATCH v6 07/13] heartrate: Add HeartRateManager interface
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Rafal Garbat
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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 8c12101..760b294 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(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(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(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
* [PATCH v6 08/13] heartrate: Add support to enable notifications
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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 760b294..60ab2df 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)
{
@@ -238,6 +249,18 @@ static void discover_ccc_cb(guint8 status, const guint8 *pdu,
if (uuid == GATT_CLIENT_CHARAC_CFG_UUID) {
hr->measurement_ccc_handle = handle;
+
+ if (g_slist_length(hr->hradapter->watchers) > 0) {
+ uint8_t value[2];
+ char *msg;
+
+ 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 +322,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 +387,10 @@ 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
* [PATCH v6 09/13] heartrate: Process measurement notifications
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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 60ab2df..2e8e896 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);
@@ -356,6 +377,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(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;
@@ -364,6 +521,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);
}
@@ -374,6 +534,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
* [PATCH v6 10/13] heartrate: Add support to reset Energy Expended
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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 2e8e896..21ec1f7 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(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(get_dbus_connection(),
+ device_get_path(device), HEART_RATE_INTERFACE);
}
--
1.7.11.3
^ permalink raw reply related
* [PATCH v6 11/13] heartrate: Add GetProperties method
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Rafal Garbat
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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 21ec1f7..e00789f 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
* [PATCH v6 12/13] heartrate: Add HeartRateWatcher interface to default policy
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Rafal Garbat
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
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
* [PATCH v6 13/13] heartrate: Add test script
From: Andrzej Kaczmarek @ 2012-09-20 11:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Rafal Garbat
In-Reply-To: <1348139690-26985-1-git-send-email-andrzej.kaczmarek@tieto.com>
From: Rafal Garbat <rafal.garbat@tieto.com>
---
Makefile.tools | 4 +-
test/test-heartrate | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+), 2 deletions(-)
create mode 100755 test/test-heartrate
diff --git a/Makefile.tools b/Makefile.tools
index d3b6f57..f59a7c4 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -209,7 +209,7 @@ EXTRA_DIST += test/sap_client.py test/hsplay test/hsmicro \
test/test-network test/simple-agent test/simple-service \
test/simple-endpoint test/test-audio test/test-input \
test/test-sap-server test/test-oob test/test-attrib \
- test/test-proximity test/test-thermometer test/test-health \
- test/test-health-sink test/service-record.dtd \
+ test/test-proximity test/test-thermometer test/test-heartrate \
+ 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
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
* Re: [PATCH BlueZ] hog: Fix segfault when discovering descriptors
From: Johan Hedberg @ 2012-09-20 11:14 UTC (permalink / raw)
To: João Paulo Rechi Vita; +Cc: linux-bluetooth
In-Reply-To: <1347631010-3055-1-git-send-email-jprvita@openbossa.org>
Hi João Paulo,
On Fri, Sep 14, 2012, João Paulo Rechi Vita wrote:
> Invalid memory was being accessed when discovering the External Report
> Reference descriptor.
> ---
> profiles/input/hog_device.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH] Bluetooth: Force the process of unpair command if disconnect failed
From: Johan Hedberg @ 2012-09-20 11:16 UTC (permalink / raw)
To: Jefferson Delfes; +Cc: linux-bluetooth
In-Reply-To: <1347989814-4958-1-git-send-email-jefferson.delfes@openbossa.org>
Hi Jefferson,
On Tue, Sep 18, 2012, Jefferson Delfes wrote:
> The unpair process tries to disconnect any connection pending with
> remote. If there are some connection in connecting state, disconnect
> command will fail and unpair mgmt command will stay pending.
>
> That pending mgmt command can cause strange behavior like automatic
> unpair after a lost connection.
> ---
> net/bluetooth/mgmt.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
Acked-by: Johan Hedberg <johan.hedberg@intel.com>
Johan
^ permalink raw reply
* Re: [PATCH BlueZ v6 03/11] core: Mutually exclude concurrent connections
From: Johan Hedberg @ 2012-09-20 11:43 UTC (permalink / raw)
To: João Paulo Rechi Vita; +Cc: linux-bluetooth
In-Reply-To: <1347370387-17670-3-git-send-email-jprvita@openbossa.org>
Hi,
On Tue, Sep 11, 2012, João Paulo Rechi Vita wrote:
> Since controllers don't support more than one ongoing connection
> procedure at the same time, new connection attempts needs to yield if
> there is an ongoing connection procedure already.
> ---
> src/adapter.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
> src/device.c | 6 +++---
> src/device.h | 2 +-
> 3 files changed, 57 insertions(+), 12 deletions(-)
Couple of coding style things I'd like to get fixed in this one. Patches
1/11 and 2/11 have been already applied though so no need to resend
them.
> + if (g_slist_length(adapter->connect_list))
> + mgmt_start_discovery(adapter->dev_id);
Since you're not testing for a boolean I'd rather have a clear > 0 here.
> const char *path = adapter->path;
> + guint connect_list_size;
Call this conn_list_len (to make it shorter and to match what the
function you get this value from is called)
> + if (!adapter_has_discov_sessions(adapter) && !connect_list_size)
> return;
Again since conn_list_len is not a boolean I'd rather have a clear == 0.
> - DBG("hci%u restarting discovery, disc_sessions %u", adapter->dev_id,
> - g_slist_length(adapter->disc_sessions));
> + DBG("hci%u restarting discovery: disc_sessions %u, connect_list size "
> + "%u", adapter->dev_id, g_slist_length(adapter->disc_sessions),
Splitting strings like this is something that we really should try to
avoid. If you do the variable rename as I suggested you can get this on
the same line.
> +static gboolean clean_connecting_state(GIOChannel *io, GIOCondition cond, gpointer user_data)
Looks like a too long line to me.
> + if (adapter->waiting_to_connect == 0 &&
> + g_slist_length(adapter->connect_list))
> + mgmt_start_discovery(adapter->dev_id);
Again > 0 here (which is especially strange that you didn't do it from
the start as in the first test you do use == 0).
> + btd_device_unref(device);
> + return FALSE;
> +}
Empty line before the return statement please.
> + btd_device_unref(device);
> return FALSE;
> }
Same here.
As a general note (not relating specifically to this patch) I'd like to
see a clearer split and naming of LE/GATT-specific functionality and
variables (function names, struct btd_adapter/device member naming &
grouping, etc.). Right now these seem to be sprinkled all over the place
which can be confusing for someone looking at the code from a
BR/EDR-only or LE-only perspective.
Johan
^ permalink raw reply
* [PATCH obexd 1/2 v2] client: Use larger timeout first packet in transfers
From: Luiz Augusto von Dentz @ 2012-09-20 12:07 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This align the client timeout for GET operations with g_obex_get_req_pkt
which does use 60 seconds to cover for extra interaction during the first
packet.
---
v2: Change clients to use 60 seconds timeout.
client/transfer.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/client/transfer.c b/client/transfer.c
index 76f6681..e9fabfb 100644
--- a/client/transfer.c
+++ b/client/transfer.c
@@ -48,6 +48,8 @@
#define OBC_TRANSFER_ERROR obc_transfer_error_quark()
+#define FIRST_PACKET_TIMEOUT 60
+
static guint64 counter = 0;
struct transfer_callback {
@@ -662,7 +664,8 @@ static gboolean transfer_start_get(struct obc_transfer *transfer, GError **err)
transfer->params->data,
transfer->params->size);
- transfer->xfer = g_obex_send_req(transfer->obex, req, -1,
+ transfer->xfer = g_obex_send_req(transfer->obex, req,
+ FIRST_PACKET_TIMEOUT,
get_xfer_progress_first,
transfer, err);
if (transfer->xfer == 0)
--
1.7.11.4
^ permalink raw reply related
* [PATCH obexd 2/2 v2] test: Use longer D-Bus timeout in test scripts
From: Luiz Augusto von Dentz @ 2012-09-20 12:07 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1348142835-13146-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
As the daemon already waits for 60 seconds for the first response this
just use the same timeout for calls that don't use transfer but return the
response as reply.
---
test/map-client | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/map-client b/test/map-client
index ac1a8ca..7741c7f 100755
--- a/test/map-client
+++ b/test/map-client
@@ -109,11 +109,11 @@ class MapClient:
print "%s/" % (i["Name"])
def list_messages(self, folder):
- ret = self.map.GetMessageListing(folder, dict())
+ ret = self.map.GetMessageListing(folder, dict(), timeout=60)
print pformat(unwrap(ret))
def get_message(self, handle):
- self.map.GetMessageListing("", dict())
+ self.map.GetMessageListing("", dict(), timeout=60)
path = self.path + "/message" + handle
obj = bus.get_object("org.bluez.obex.client", path)
msg = dbus.Interface(obj, "org.bluez.obex.Message")
--
1.7.11.4
^ permalink raw reply related
* Re: [PATCH v0 1/4] adapter: Replace device authorizing flag
From: Luiz Augusto von Dentz @ 2012-09-20 12:20 UTC (permalink / raw)
To: Mikel Astiz; +Cc: linux-bluetooth, Mikel Astiz
In-Reply-To: <1347371730-14933-2-git-send-email-mikel.astiz.oss@gmail.com>
Hi Mikel,
On Tue, Sep 11, 2012 at 4:55 PM, Mikel Astiz <mikel.astiz.oss@gmail.com> wrote:
> From: Mikel Astiz <mikel.astiz@bmw-carit.de>
>
> Refactor code to drop the device authorizing flag by replacing it with a
> private authorization pointer in btd_adapter. After all, no more than
> one authorization can be ongoing, so the code is easier to follow if
> this is made explicit.
> ---
> src/adapter.c | 48 ++++++++++++++++++++++++++++++++----------------
> src/device.c | 11 -----------
> src/device.h | 2 --
> 3 files changed, 32 insertions(+), 29 deletions(-)
>
> diff --git a/src/adapter.c b/src/adapter.c
> index 4b675e8..14c5322 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -128,7 +128,8 @@ struct btd_adapter {
> GSList *found_devices;
> GSList *oor_devices; /* out of range device list */
> struct agent *agent; /* For the new API */
> - guint auth_idle_id; /* Ongoing authorization */
> + guint auth_idle_id; /* Ongoing authorization (trusted) */
> + struct service_auth *auth; /* Ongoing authorization */
You should probably store the id directly inside struct service_auth
as they depend on each other then when you free auth you also remove
the id if not set to 0.
--
Luiz Augusto von Dentz
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox