* Re: [PATCH 00/14] Thermometer watchers API change + fixes
From: Anderson Lizardo @ 2012-09-25 15:21 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
Hi Andrzej,
On Tue, Sep 25, 2012 at 10:52 AM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> Hi,
>
> Here's series of patches to move watchers from per-device to per-adapter
> interface (basically the same as done for HRP, see other series of patches).
> This applies to both final and intermediate temperature watchers - once
> watcher is registered, all connected devices are setup to send measurement
> notifications and the opposite when last watcher is unregistered.
>
> This major change is done in patches 1-6.
>
> Patches 7-11 contain some code and documentation refactoring, i.e. to
> remove duplicated code.
>
> Patches 12-14 are trival coding style fixes.
>
> Unfortunately, I wasn't able to fully test this code due to lack of proper
> thermometer device and sample device from CC2540 devkit does not quite
> work as expected (e.g. I can see CCC is written properly when watcher is
> registered but remote does not send any indications for unknown reason).
Unfortunately, the thermometer demo app (at least on TI's BLE stack
v1.1 installation) has several bugs. I haven't tested yet the latest
release (1.2.1), which version are you using?
Do you have access to PTS? You could test with it as well.
Maybe we should consider implementing a simple Thermometer role in
BlueZ for testing purposes. It is a relatively simple profile.
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* [PATCH v2] Cycling Speed and Cadence profile (CSCP) API
From: Andrzej Kaczmarek @ 2012-09-25 15:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348585647-25458-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
doc/cycling-api.txt | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+)
create mode 100644 doc/cycling-api.txt
diff --git a/doc/cycling-api.txt b/doc/cycling-api.txt
new file mode 100644
index 0000000..6186fe1
--- /dev/null
+++ b/doc/cycling-api.txt
@@ -0,0 +1,117 @@
+Cycling Speed and Cadence API description
+****************************************
+
+Copyright (C) 2012 Tieto Poland
+
+Cycling Speed and Cadence Manager hierarchy
+============================
+
+Service org.bluez
+Interface org.bluez.CyclingSpeedManager
+Object path [variable prefix]/{hci0,hci1,...}
+
+Methods RegisterWatcher(object agent)
+
+ Registers a watcher to monitor cycling speed and cadence
+ measurements.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ UnregisterWatcher(object agent)
+
+ Unregisters a watcher.
+
+Cycling Speed and Cadence Profile hierarchy
+============================
+
+Service org.bluez
+Interface org.bluez.CyclingSpeed
+Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Methods void SetProperty(string name, variant value)
+
+ Changes the value of the specified property. Only
+ read-write properties can be changed. On success
+ this will emit a PropertyChanged signal.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ dict GetProperties()
+
+ Returns all properties for the interface. See the
+ Properties section for the available properties.
+
+ SetCumulativeWheelRevolutions(uint32 value)
+
+ Sets cumulative wheel revolutions value if
+ Cumulative Wheel Revolutions feature is supported.
+
+ Possible Errors: org.bluez.Error.NotSupported
+
+Signals PropertyChanged(string name, variant value)
+
+ This signal indicates a changed value of the given
+ property.
+
+Properties string Location (optional) [readwrite]
+
+ Current sensor location, if supported.
+ If Multiple Sensor Locations feature is supported,
+ this property can be set to one of values read from
+ SupportedLocations property.
+
+ Possible values: "Other", "Top of shoe", "In shoe",
+ "Hip", "Front Wheel", "Left Crank",
+ "Right Crank", "Left Pedal",
+ "Right Pedal", "Front Hub",
+ "Rear Dropout", "Chainstay",
+ "Rear Wheel", "Rear Hub"
+
+ array{string} SupportedLocations (optional) [readonly]
+
+ List of locations supported by sensor, only present
+ if Multiple Sensor Locations feature is supported.
+
+ boolean WheelRevolutionDataSupported [readonly]
+
+ true if sensor can read and set Cumulative Wheel
+ Revolutions value, false otherwise.
+
+ boolean MultipleSensorLocationsSupported [readonly]
+
+ true if sensor supports Multiple Sensor Locations
+ feature and can set Location, false otherwise.
+
+Cycling Speed and Cadence Watcher hierarchy
+============================
+Service unique name
+Interface org.bluez.CyclingSpeedWatcher
+Object path freely definable
+
+Methods void MeasurementReceived(object device, dict measurement)
+
+ This callback is called whenever wheel and/or crank
+ revolutions measurement is received from sensor.
+
+ Measurement:
+
+ uint32 WheelRevolutions (optional):
+
+ Cumulative number of wheel revolutions.
+
+ uint16 LastWheelEventTime (optional):
+
+ Time of last event from wheel sensor.
+ Value is expressed in 1/1024 second
+ units and can roll over during a ride.
+
+ uint16 CrankRevolutions (optional):
+
+ Cumulative number of crank revolutions.
+ This value can occasionally roll over.
+
+ uint16 LastCrankEventTime (optional):
+
+ Time of last event from crank sensor.
+ Value is expressed in 1/1024 second
+ units and can roll over during a ride.
--
1.7.11.3
^ permalink raw reply related
* [RFC v2] Cycling Speed and Cadence profile (CSCP) API
From: Andrzej Kaczmarek @ 2012-09-25 15:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
Hi,
Changes since v1:
- minor fixes in descriptions (some pointed out by Anderson Lizardo)
- changed base name for interfaces to org.bluez.CyclingSpeed
previous name was org.bluez.Cycling
other option is e.g. org.bluez.CyclingSc
still need to figure out which is the best
Comments are welcome.
Andrzej Kaczmarek (1):
Cycling Speed and Cadence profile (CSCP) API
doc/cycling-api.txt | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+)
create mode 100644 doc/cycling-api.txt
--
1.7.11.3
^ permalink raw reply
* [PATCH v2 6/6] audio: Drop audio-specific authorization mechanism
From: Mikel Astiz @ 2012-09-25 14:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348584946-13895-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Remove the audio-specific service authorization mechanism in favor of
using the conventional one.
The main difference is that audio profiles will be authorized
independently. Therefore a single connection might result in several
profile authorization requests to the agent (i.e. HFP, A2DP and AVRCP).
This removes any internal policy that would skip the authorization
procedure, making it simpler and more convenient for IVI use-cases.
Agents interested in simulating the old behavior are encouraged to
either set the device as trusted or just reply to the additional
authorization requests automatically without user intervention.
---
audio/avctp.c | 29 +++++------
audio/avdtp.c | 25 +++++++---
audio/device.c | 150 --------------------------------------------------------
audio/device.h | 12 +----
audio/manager.c | 18 ++++---
5 files changed, 40 insertions(+), 194 deletions(-)
diff --git a/audio/avctp.c b/audio/avctp.c
index 4e0e8dc..40e85ed 100644
--- a/audio/avctp.c
+++ b/audio/avctp.c
@@ -139,6 +139,7 @@ struct avctp {
GIOChannel *io;
guint io_id;
+ int service_auth_id;
uint16_t mtu;
@@ -337,13 +338,9 @@ static void avctp_disconnected(struct avctp *session)
g_source_remove(session->io_id);
session->io_id = 0;
- if (session->state == AVCTP_STATE_CONNECTING) {
- struct audio_device *dev;
-
- dev = manager_get_device(&session->server->src,
- &session->dst, FALSE);
- audio_device_cancel_authorization(dev, auth_cb,
- session);
+ if (session->service_auth_id > 0) {
+ btd_cancel_authorization(session->service_auth_id);
+ session->service_auth_id = 0;
}
}
@@ -386,15 +383,7 @@ static void avctp_set_state(struct avctp *session, avctp_state_t new_state)
switch (new_state) {
case AVCTP_STATE_DISCONNECTED:
DBG("AVCTP Disconnected");
-
avctp_disconnected(session);
-
- if (old_state != AVCTP_STATE_CONNECTED)
- break;
-
- if (!audio_device_is_active(dev, NULL))
- audio_device_set_authorized(dev, FALSE);
-
break;
case AVCTP_STATE_CONNECTING:
DBG("AVCTP Connecting");
@@ -657,6 +646,8 @@ static void auth_cb(DBusError *derr, void *user_data)
struct avctp *session = user_data;
GError *err = NULL;
+ session->service_auth_id = 0;
+
if (session->io_id) {
g_source_remove(session->io_id);
session->io_id = 0;
@@ -736,6 +727,7 @@ static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
struct audio_device *dev;
char address[18];
bdaddr_t src, dst;
+ int auth_id;
GError *err = NULL;
bt_io_get(chan, &err,
@@ -780,12 +772,15 @@ static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
avctp_set_state(session, AVCTP_STATE_CONNECTING);
session->io = g_io_channel_ref(chan);
- if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID,
- auth_cb, session) < 0)
+ auth_id = btd_request_authorization(&dev->src, &dev->dst,
+ AVRCP_TARGET_UUID,
+ auth_cb, session);
+ if (auth_id < 0)
goto drop;
session->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
session_cb, session);
+ session->service_auth_id = auth_id;
return;
drop:
diff --git a/audio/avdtp.c b/audio/avdtp.c
index d44c504..3137094 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -400,6 +400,8 @@ struct avdtp {
/* True if the entire device is being disconnected */
gboolean device_disconnect;
+ int service_auth_id;
+
GIOChannel *io;
guint io_id;
@@ -1129,16 +1131,21 @@ static void release_stream(struct avdtp_stream *stream, struct avdtp *session)
static int avdtp_cancel_authorization(struct avdtp *session)
{
- struct audio_device *dev;
+ int err;
if (session->state != AVDTP_SESSION_STATE_CONNECTING)
return 0;
- dev = manager_get_device(&session->server->src, &session->dst, FALSE);
- if (dev == NULL)
- return -ENODEV;
+ if (!session->service_auth_id)
+ return 0;
- return audio_device_cancel_authorization(dev, auth_cb, session);
+ err = btd_cancel_authorization(session->service_auth_id);
+ if (err < 0)
+ return err;
+
+ session->service_auth_id = 0;
+
+ return 0;
}
static void connection_lost(struct avdtp *session, int err)
@@ -2507,7 +2514,7 @@ static void avdtp_confirm_cb(GIOChannel *chan, gpointer data)
struct audio_device *dev;
char address[18];
bdaddr_t src, dst;
- int perr;
+ int auth_id;
GError *err = NULL;
bt_io_get(chan, &err,
@@ -2566,15 +2573,17 @@ static void avdtp_confirm_cb(GIOChannel *chan, gpointer data)
session->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
(GIOFunc) session_cb, session);
- perr = audio_device_request_authorization(dev, ADVANCED_AUDIO_UUID,
+ auth_id = btd_request_authorization(&dev->src, &dev->dst,
+ ADVANCED_AUDIO_UUID,
auth_cb, session);
- if (perr < 0) {
+ if (auth_id < 0) {
avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
avdtp_unref(session);
goto drop;
}
dev->auto_connect = auto_connect;
+ session->service_auth_id = auth_id;
return;
diff --git a/audio/device.c b/audio/device.c
index 454bbb9..175e3c0 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -71,19 +71,12 @@ typedef enum {
AUDIO_STATE_CONNECTED,
} audio_state_t;
-struct service_auth {
- service_auth_cb cb;
- void *user_data;
-};
-
struct dev_priv {
audio_state_t state;
headset_state_t hs_state;
sink_state_t sink_state;
avctp_state_t avctp_state;
- GSList *auths;
- int auth_id;
DBusMessage *conn_req;
DBusMessage *dc_req;
@@ -94,8 +87,6 @@ struct dev_priv {
guint dc_id;
gboolean disconnecting;
- gboolean authorized;
- guint auth_idle_id;
};
static unsigned int sink_callback_id = 0;
@@ -110,8 +101,6 @@ static void device_free(struct audio_device *dev)
btd_device_unref(dev->btd_dev);
if (priv) {
- if (priv->auths)
- audio_device_cancel_authorization(dev, NULL, NULL);
if (priv->control_timer)
g_source_remove(priv->control_timer);
if (priv->avdtp_timer)
@@ -238,8 +227,6 @@ static void device_set_state(struct audio_device *dev, audio_state_t new_state)
return;
if (new_state == AUDIO_STATE_DISCONNECTED) {
- priv->authorized = FALSE;
-
if (priv->dc_id) {
device_remove_disconnect_watch(dev->btd_dev,
priv->dc_id);
@@ -732,140 +719,3 @@ void audio_device_unregister(struct audio_device *device)
device_free(device);
}
-
-static void auth_cb(DBusError *derr, void *user_data)
-{
- struct audio_device *dev = user_data;
- struct dev_priv *priv = dev->priv;
-
- priv->auth_id = 0;
-
- if (derr == NULL)
- priv->authorized = TRUE;
-
- while (priv->auths) {
- struct service_auth *auth = priv->auths->data;
-
- auth->cb(derr, auth->user_data);
- priv->auths = g_slist_remove(priv->auths, auth);
- g_free(auth);
- }
-}
-
-static gboolean auth_idle_cb(gpointer user_data)
-{
- struct audio_device *dev = user_data;
- struct dev_priv *priv = dev->priv;
-
- priv->auth_idle_id = 0;
-
- auth_cb(NULL, dev);
-
- return FALSE;
-}
-
-static gboolean audio_device_is_connected(struct audio_device *dev)
-{
- if (dev->headset) {
- headset_state_t state = headset_get_state(dev);
-
- if (state == HEADSET_STATE_CONNECTED ||
- state == HEADSET_STATE_PLAY_IN_PROGRESS ||
- state == HEADSET_STATE_PLAYING)
- return TRUE;
- }
-
- if (dev->sink) {
- sink_state_t state = sink_get_state(dev);
-
- if (state == SINK_STATE_CONNECTED ||
- state == SINK_STATE_PLAYING)
- return TRUE;
- }
-
- if (dev->source) {
- source_state_t state = source_get_state(dev);
-
- if (state == SOURCE_STATE_CONNECTED ||
- state == SOURCE_STATE_PLAYING)
- return TRUE;
- }
-
- return FALSE;
-}
-
-int audio_device_request_authorization(struct audio_device *dev,
- const char *uuid, service_auth_cb cb,
- void *user_data)
-{
- struct dev_priv *priv = dev->priv;
- struct service_auth *auth;
- int err;
-
- auth = g_try_new0(struct service_auth, 1);
- if (!auth)
- return -ENOMEM;
-
- auth->cb = cb;
- auth->user_data = user_data;
-
- priv->auths = g_slist_append(priv->auths, auth);
- if (g_slist_length(priv->auths) > 1)
- return 0;
-
- if (priv->authorized || audio_device_is_connected(dev)) {
- priv->auth_idle_id = g_idle_add(auth_idle_cb, dev);
- return 0;
- }
-
- err = btd_request_authorization(&dev->src, &dev->dst, uuid, auth_cb,
- dev);
- if (err < 0) {
- priv->auths = g_slist_remove(priv->auths, auth);
- g_free(auth);
- } else
- priv->auth_id = err;
-
- return err;
-}
-
-int audio_device_cancel_authorization(struct audio_device *dev,
- authorization_cb cb, void *user_data)
-{
- struct dev_priv *priv = dev->priv;
- GSList *l, *next;
-
- for (l = priv->auths; l != NULL; l = next) {
- struct service_auth *auth = l->data;
-
- next = g_slist_next(l);
-
- if (cb && auth->cb != cb)
- continue;
-
- if (user_data && auth->user_data != user_data)
- continue;
-
- priv->auths = g_slist_remove(priv->auths, auth);
- g_free(auth);
- }
-
- if (g_slist_length(priv->auths) == 0) {
- if (priv->auth_idle_id > 0) {
- g_source_remove(priv->auth_idle_id);
- priv->auth_idle_id = 0;
- } else {
- btd_cancel_authorization(priv->auth_id);
- priv->auth_id = 0;
- }
- }
-
- return 0;
-}
-
-void audio_device_set_authorized(struct audio_device *dev, gboolean auth)
-{
- struct dev_priv *priv = dev->priv;
-
- priv->authorized = auth;
-}
diff --git a/audio/device.h b/audio/device.h
index f9b868f..548462b 100644
--- a/audio/device.h
+++ b/audio/device.h
@@ -47,6 +47,7 @@ struct audio_device {
struct target *target;
guint hs_preauth_id;
+ int hs_service_auth_id;
struct dev_priv *priv;
};
@@ -59,14 +60,3 @@ void audio_device_unregister(struct audio_device *device);
gboolean audio_device_is_active(struct audio_device *dev,
const char *interface);
-
-typedef void (*authorization_cb) (DBusError *derr, void *user_data);
-
-int audio_device_cancel_authorization(struct audio_device *dev,
- authorization_cb cb, void *user_data);
-
-int audio_device_request_authorization(struct audio_device *dev,
- const char *uuid, authorization_cb cb,
- void *user_data);
-
-void audio_device_set_authorized(struct audio_device *dev, gboolean auth);
diff --git a/audio/manager.c b/audio/manager.c
index fbfe00f..06a71e3 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -328,7 +328,7 @@ static gboolean hs_preauth_cb(GIOChannel *chan, GIOCondition cond,
DBG("Headset disconnected during authorization");
- audio_device_cancel_authorization(device, headset_auth_cb, device);
+ btd_cancel_authorization(device->hs_service_auth_id);
headset_set_state(device, HEADSET_STATE_DISCONNECTED);
@@ -343,7 +343,7 @@ static void ag_confirm(GIOChannel *chan, gpointer data)
struct audio_device *device;
gboolean hfp_active;
bdaddr_t src, dst;
- int perr;
+ int auth_id;
GError *err = NULL;
uint8_t ch;
@@ -398,10 +398,11 @@ static void ag_confirm(GIOChannel *chan, gpointer data)
headset_set_state(device, HEADSET_STATE_CONNECTING);
- perr = audio_device_request_authorization(device, server_uuid,
- headset_auth_cb, device);
- if (perr < 0) {
- DBG("Authorization denied: %s", strerror(-perr));
+ auth_id = btd_request_authorization(&device->src, &device->dst,
+ server_uuid, headset_auth_cb,
+ device);
+ if (auth_id < 0) {
+ DBG("Authorization denied: %s", strerror(-auth_id));
headset_set_state(device, HEADSET_STATE_DISCONNECTED);
return;
}
@@ -480,8 +481,9 @@ static void hf_io_cb(GIOChannel *chan, gpointer data)
goto drop;
}
- perr = audio_device_request_authorization(device, server_uuid,
- gateway_auth_cb, device);
+ perr = btd_request_authorization(&device->src, &device->dst,
+ server_uuid, gateway_auth_cb,
+ device);
if (perr < 0) {
DBG("Authorization denied: %s", strerror(-perr));
gateway_set_state(device, GATEWAY_STATE_DISCONNECTED);
--
1.7.11.4
^ permalink raw reply related
* [PATCH v2 5/6] adapter: Queue parallel authorization requests
From: Mikel Astiz @ 2012-09-25 14:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348584946-13895-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Remote device could try to connect several profiles in parallel, or
several devices could be trying to connect services. Instead of
returning EBUSY, this patch adds a queue to each adapter such that the
authorization requests will be queued and processed sequentially.
---
src/adapter.c | 181 +++++++++++++++++++++++++++++++++-------------------------
1 file changed, 103 insertions(+), 78 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 5f1a722..83746c7 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -101,8 +101,10 @@ struct service_auth {
int id;
service_auth_cb cb;
void *user_data;
+ const char *uuid;
struct btd_device *device;
struct btd_adapter *adapter;
+ struct agent *agent; /* NULL for queued auths */
};
struct btd_adapter {
@@ -129,8 +131,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 (trusted) */
- struct service_auth *auth; /* Ongoing authorization */
+ guint auth_idle_id; /* Pending authorization dequeue */
+ GQueue *auths; /* Ongoing and pending auths */
GSList *connections; /* Connected devices */
GSList *devices; /* Devices structure pointers */
GSList *mode_sessions; /* Request Mode sessions */
@@ -158,6 +160,8 @@ struct btd_adapter {
GSList *profiles;
};
+static gboolean process_auth_queue(gpointer user_data);
+
static void dev_info_free(void *data)
{
struct remote_dev_info *dev = data;
@@ -951,16 +955,49 @@ static struct btd_device *adapter_create_device(struct btd_adapter *adapter,
return device;
}
+static void service_auth_cancel(struct service_auth *auth)
+{
+ DBusError derr;
+
+ dbus_error_init(&derr);
+ dbus_set_error_const(&derr, "org.bluez.Error.Canceled", NULL);
+
+ auth->cb(&derr, auth->user_data);
+
+ dbus_error_free(&derr);
+
+ if (auth->agent != NULL)
+ agent_cancel(auth->agent);
+
+ g_free(auth);
+}
+
void adapter_remove_device(struct btd_adapter *adapter,
struct btd_device *device,
gboolean remove_storage)
{
const gchar *dev_path = device_get_path(device);
- struct agent *agent;
+ GList *l;
adapter->devices = g_slist_remove(adapter->devices, device);
adapter->connections = g_slist_remove(adapter->connections, device);
+ l = adapter->auths->head;
+ while (l != NULL) {
+ struct service_auth *auth = l->data;
+ GList *next = g_list_next(l);
+
+ if (auth->device != device) {
+ l = next;
+ continue;
+ }
+
+ g_queue_delete_link(adapter->auths, l);
+ l = next;
+
+ service_auth_cancel(auth);
+ }
+
adapter_update_devices(adapter);
g_dbus_emit_signal(btd_get_dbus_connection(), adapter->path,
@@ -968,14 +1005,6 @@ void adapter_remove_device(struct btd_adapter *adapter,
DBUS_TYPE_OBJECT_PATH, &dev_path,
DBUS_TYPE_INVALID);
- agent = device_get_agent(device);
-
- if (agent && adapter->auth && adapter->auth->device == device) {
- g_free(adapter->auth);
- adapter->auth = NULL;
- agent_cancel(agent);
- }
-
device_remove(device, remove_storage);
}
@@ -2414,8 +2443,7 @@ static void adapter_free(gpointer user_data)
if (adapter->auth_idle_id)
g_source_remove(adapter->auth_idle_id);
- if (adapter->auth)
- g_free(adapter->auth);
+ g_queue_free_full(adapter->auths, g_free);
if (adapter->off_timer)
off_timer_remove(adapter);
@@ -2509,6 +2537,7 @@ struct btd_adapter *adapter_create(int id)
}
adapter->dev_id = id;
+ adapter->auths = g_queue_new();
snprintf(path, sizeof(path), "%s/hci%d", base_path, id);
adapter->path = g_strdup(path);
@@ -3152,26 +3181,60 @@ static void agent_auth_cb(struct agent *agent, DBusError *derr,
void *user_data)
{
struct btd_adapter *adapter = user_data;
- struct service_auth *auth = adapter->auth;
+ struct service_auth *auth = adapter->auths->head->data;
- adapter->auth = NULL;
+ g_queue_pop_head(adapter->auths);
auth->cb(derr, auth->user_data);
g_free(auth);
+
+ adapter->auth_idle_id = g_idle_add(process_auth_queue, adapter);
}
-static gboolean auth_idle_cb(gpointer user_data)
+static gboolean process_auth_queue(gpointer user_data)
{
struct btd_adapter *adapter = user_data;
- struct service_auth *auth = adapter->auth;
+ DBusError err;
- adapter->auth = NULL;
adapter->auth_idle_id = 0;
- auth->cb(NULL, auth->user_data);
+ dbus_error_init(&err);
+ dbus_set_error_const(&err, "org.bluez.Error.Rejected", NULL);
- g_free(auth);
+ while (!g_queue_is_empty(adapter->auths)) {
+ struct service_auth *auth = adapter->auths->head->data;
+ struct btd_device *device = auth->device;
+ const gchar *dev_path;
+
+ if (device_is_trusted(device) == TRUE) {
+ auth->cb(NULL, auth->user_data);
+ goto next;
+ }
+
+ auth->agent = device_get_agent(device);
+ if (auth->agent == NULL) {
+ warn("Can't find device agent");
+ auth->cb(&err, auth->user_data);
+ goto next;
+ }
+
+ dev_path = device_get_path(device);
+
+ if (agent_authorize(auth->agent, dev_path, auth->uuid,
+ agent_auth_cb, adapter, NULL) < 0) {
+ auth->cb(&err, auth->user_data);
+ goto next;
+ }
+
+ break;
+
+next:
+ g_free(auth);
+ g_queue_pop_head(adapter->auths);
+ }
+
+ dbus_error_free(&err);
return FALSE;
}
@@ -3182,10 +3245,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
{
struct service_auth *auth;
struct btd_device *device;
- struct agent *agent;
char address[18];
- const gchar *dev_path;
- int err;
ba2str(dst, address);
device = adapter_find_device(adapter, address);
@@ -3196,42 +3256,27 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
if (!g_slist_find(adapter->connections, device))
error("Authorization request for non-connected device!?");
- if (adapter->auth != NULL)
- return -EBUSY;
-
auth = g_try_new0(struct service_auth, 1);
if (!auth)
return -ENOMEM;
auth->cb = cb;
auth->user_data = user_data;
+ auth->uuid = uuid;
auth->device = device;
auth->adapter = adapter;
auth->id = service_auth_id++;
- if (device_is_trusted(device) == TRUE) {
- adapter->auth_idle_id = g_idle_add(auth_idle_cb, adapter);
- goto done;
- }
+ g_queue_push_tail(adapter->auths, auth);
- agent = device_get_agent(device);
- if (!agent) {
- warn("Can't find device agent");
- g_free(auth);
- return -EPERM;
- }
+ if (adapter->auths->length != 1)
+ return auth->id;
- dev_path = device_get_path(device);
+ if (adapter->auth_idle_id != 0)
+ return auth->id;
- err = agent_authorize(agent, dev_path, uuid, agent_auth_cb, adapter,
- NULL);
- if (err < 0) {
- g_free(auth);
- return err;
- }
+ adapter->auth_idle_id = g_idle_add(process_auth_queue, adapter);
-done:
- adapter->auth = auth;
return auth->id;
}
@@ -3263,18 +3308,20 @@ int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
return -EPERM;
}
-static struct btd_adapter *find_authorization(int id)
+static struct service_auth *find_authorization(int id)
{
GSList *l;
+ GList *l2;
for (l = manager_get_adapters(); l != NULL; l = g_slist_next(l)) {
struct btd_adapter *adapter = l->data;
- if (adapter->auth == NULL)
- continue;
+ for (l2 = adapter->auths->head; l2 != NULL; l2 = l2->next) {
+ struct service_auth *auth = l2->data;
- if (adapter->auth->id == id)
- return adapter;
+ if (auth->id == id)
+ return auth;
+ }
}
return NULL;
@@ -3282,39 +3329,17 @@ static struct btd_adapter *find_authorization(int id)
int btd_cancel_authorization(int id)
{
- struct btd_adapter *adapter;
- struct agent *agent;
- int err;
-
- adapter = find_authorization(id);
- if (adapter == NULL)
- return -EPERM;
-
- if (adapter->auth_idle_id) {
- g_source_remove(adapter->auth_idle_id);
- adapter->auth_idle_id = 0;
- g_free(adapter->auth);
- adapter->auth = NULL;
- return 0;
- }
-
- /*
- * FIXME: Cancel fails if authorization is requested to adapter's
- * agent and in the meanwhile CreatePairedDevice is called.
- */
+ struct service_auth *auth;
- agent = device_get_agent(adapter->auth->device);
- if (!agent)
+ auth = find_authorization(id);
+ if (auth == NULL)
return -EPERM;
- err = agent_cancel(agent);
+ g_queue_remove(auth->adapter->auths, auth);
- if (err == 0) {
- g_free(adapter->auth);
- adapter->auth = NULL;
- }
+ service_auth_cancel(auth);
- return err;
+ return 0;
}
static gchar *adapter_any_path = NULL;
--
1.7.11.4
^ permalink raw reply related
* [PATCH v2 4/6] adapter: Use authorization id for cancelling
From: Mikel Astiz @ 2012-09-25 14:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348584946-13895-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Return a request id in btd_request_authorization() in order to be used
when the request needs to be cancelled. This id alone will be enough to
use btd_cancel_authorization().
---
audio/device.c | 12 +++++++++---
plugins/service.c | 18 ++++++++++-------
profiles/input/server.c | 2 +-
src/adapter.c | 51 +++++++++++++++++++++++++++++++------------------
src/adapter.h | 2 +-
5 files changed, 54 insertions(+), 31 deletions(-)
diff --git a/audio/device.c b/audio/device.c
index 99d6512..454bbb9 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -83,6 +83,7 @@ struct dev_priv {
sink_state_t sink_state;
avctp_state_t avctp_state;
GSList *auths;
+ int auth_id;
DBusMessage *conn_req;
DBusMessage *dc_req;
@@ -737,6 +738,8 @@ static void auth_cb(DBusError *derr, void *user_data)
struct audio_device *dev = user_data;
struct dev_priv *priv = dev->priv;
+ priv->auth_id = 0;
+
if (derr == NULL)
priv->authorized = TRUE;
@@ -820,7 +823,8 @@ int audio_device_request_authorization(struct audio_device *dev,
if (err < 0) {
priv->auths = g_slist_remove(priv->auths, auth);
g_free(auth);
- }
+ } else
+ priv->auth_id = err;
return err;
}
@@ -850,8 +854,10 @@ int audio_device_cancel_authorization(struct audio_device *dev,
if (priv->auth_idle_id > 0) {
g_source_remove(priv->auth_idle_id);
priv->auth_idle_id = 0;
- } else
- btd_cancel_authorization(&dev->src, &dev->dst);
+ } else {
+ btd_cancel_authorization(priv->auth_id);
+ priv->auth_id = 0;
+ }
}
return 0;
diff --git a/plugins/service.c b/plugins/service.c
index e02a673..fca559d 100644
--- a/plugins/service.c
+++ b/plugins/service.c
@@ -65,6 +65,7 @@ struct pending_auth {
char *sender;
bdaddr_t dst;
char uuid[MAX_LEN_UUID_STR];
+ int id;
};
struct service_adapter {
@@ -557,8 +558,9 @@ done:
else
bacpy(&src, BDADDR_ANY);
- btd_request_authorization(&src, &auth->dst,
- auth->uuid, auth_cb, serv_adapter);
+ auth->id = btd_request_authorization(&src, &auth->dst,
+ auth->uuid, auth_cb,
+ serv_adapter);
}
static DBusMessage *request_authorization(DBusConnection *conn,
@@ -633,8 +635,9 @@ static DBusMessage *request_authorization(DBusConnection *conn,
else
bacpy(&src, BDADDR_ANY);
- if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb,
- serv_adapter) < 0) {
+ auth->id = btd_request_authorization(&src, &auth->dst, auth->uuid,
+ auth_cb, serv_adapter);
+ if (auth->id < 0) {
serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
auth);
g_free(auth);
@@ -664,7 +667,7 @@ static DBusMessage *cancel_authorization(DBusConnection *conn,
else
bacpy(&src, BDADDR_ANY);
- btd_cancel_authorization(&src, &auth->dst);
+ btd_cancel_authorization(auth->id);
reply = btd_error_not_authorized(auth->msg);
dbus_message_unref(auth->msg);
@@ -683,8 +686,9 @@ static DBusMessage *cancel_authorization(DBusConnection *conn,
else
bacpy(&src, BDADDR_ANY);
- btd_request_authorization(&src, &auth->dst,
- auth->uuid, auth_cb, serv_adapter);
+ auth->id = btd_request_authorization(&src, &auth->dst,
+ auth->uuid, auth_cb,
+ serv_adapter);
done:
return dbus_message_new_method_return(msg);
diff --git a/profiles/input/server.c b/profiles/input/server.c
index 0464c4a..0385012 100644
--- a/profiles/input/server.c
+++ b/profiles/input/server.c
@@ -175,7 +175,7 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
ret = btd_request_authorization(&src, &dst, HID_UUID,
auth_callback, server);
- if (ret == 0)
+ if (ret >= 0)
return;
ba2str(&src, addr);
diff --git a/src/adapter.c b/src/adapter.c
index 366a99f..5f1a722 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -85,6 +85,7 @@
#define OFF_TIMER 3
static GSList *adapter_drivers = NULL;
+static int service_auth_id = 0;
struct session_req {
struct btd_adapter *adapter;
@@ -97,6 +98,7 @@ struct session_req {
};
struct service_auth {
+ int id;
service_auth_cb cb;
void *user_data;
struct btd_device *device;
@@ -3205,6 +3207,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
auth->user_data = user_data;
auth->device = device;
auth->adapter = adapter;
+ auth->id = service_auth_id++;
if (device_is_trusted(device) == TRUE) {
adapter->auth_idle_id = g_idle_add(auth_idle_cb, adapter);
@@ -3229,7 +3232,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
done:
adapter->auth = auth;
- return 0;
+ return auth->id;
}
int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
@@ -3248,49 +3251,59 @@ int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
}
for (l = manager_get_adapters(); l != NULL; l = g_slist_next(l)) {
- int err;
+ int id;
adapter = l->data;
- err = adapter_authorize(adapter, dst, uuid, cb, user_data);
- if (err == 0)
- return 0;
+ id = adapter_authorize(adapter, dst, uuid, cb, user_data);
+ if (id >= 0)
+ return id;
}
return -EPERM;
}
-int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
+static struct btd_adapter *find_authorization(int id)
{
- struct btd_adapter *adapter = manager_find_adapter(src);
- struct btd_device *device;
+ GSList *l;
+
+ for (l = manager_get_adapters(); l != NULL; l = g_slist_next(l)) {
+ struct btd_adapter *adapter = l->data;
+
+ if (adapter->auth == NULL)
+ continue;
+
+ if (adapter->auth->id == id)
+ return adapter;
+ }
+
+ return NULL;
+}
+
+int btd_cancel_authorization(int id)
+{
+ struct btd_adapter *adapter;
struct agent *agent;
- char address[18];
int err;
- if (!adapter)
- return -EPERM;
-
- ba2str(dst, address);
- device = adapter_find_device(adapter, address);
- if (!device)
+ adapter = find_authorization(id);
+ if (adapter == NULL)
return -EPERM;
if (adapter->auth_idle_id) {
g_source_remove(adapter->auth_idle_id);
adapter->auth_idle_id = 0;
+ g_free(adapter->auth);
+ adapter->auth = NULL;
return 0;
}
- if (!adapter->auth || adapter->auth->device != device)
- return -EPERM;
-
/*
* FIXME: Cancel fails if authorization is requested to adapter's
* agent and in the meanwhile CreatePairedDevice is called.
*/
- agent = device_get_agent(device);
+ agent = device_get_agent(adapter->auth->device);
if (!agent)
return -EPERM;
diff --git a/src/adapter.h b/src/adapter.h
index eece6f5..df61a5a 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -149,7 +149,7 @@ int btd_register_adapter_driver(struct btd_adapter_driver *driver);
void btd_unregister_adapter_driver(struct btd_adapter_driver *driver);
int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
const char *uuid, service_auth_cb cb, void *user_data);
-int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst);
+int btd_cancel_authorization(int id);
const char *adapter_any_get_path(void);
--
1.7.11.4
^ permalink raw reply related
* [PATCH v2 3/6] adapter: Replace device authorizing flag
From: Mikel Astiz @ 2012-09-25 14:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348584946-13895-1-git-send-email-mikel.astiz.oss@gmail.com>
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 | 55 +++++++++++++++++++++++++++++++++++++------------------
src/device.c | 11 -----------
src/device.h | 2 --
3 files changed, 37 insertions(+), 31 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index f9acbd5..366a99f 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -127,7 +127,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 */
GSList *connections; /* Connected devices */
GSList *devices; /* Devices structure pointers */
GSList *mode_sessions; /* Request Mode sessions */
@@ -967,8 +968,11 @@ void adapter_remove_device(struct btd_adapter *adapter,
agent = device_get_agent(device);
- if (agent && device_is_authorizing(device))
+ if (agent && adapter->auth && adapter->auth->device == device) {
+ g_free(adapter->auth);
+ adapter->auth = NULL;
agent_cancel(agent);
+ }
device_remove(device, remove_storage);
}
@@ -2408,6 +2412,9 @@ static void adapter_free(gpointer user_data)
if (adapter->auth_idle_id)
g_source_remove(adapter->auth_idle_id);
+ if (adapter->auth)
+ g_free(adapter->auth);
+
if (adapter->off_timer)
off_timer_remove(adapter);
@@ -3142,22 +3149,28 @@ void btd_unregister_adapter_driver(struct btd_adapter_driver *driver)
static void agent_auth_cb(struct agent *agent, DBusError *derr,
void *user_data)
{
- struct service_auth *auth = user_data;
+ struct btd_adapter *adapter = user_data;
+ struct service_auth *auth = adapter->auth;
- device_set_authorizing(auth->device, FALSE);
+ adapter->auth = NULL;
auth->cb(derr, auth->user_data);
+
+ g_free(auth);
}
static gboolean auth_idle_cb(gpointer user_data)
{
- struct service_auth *auth = user_data;
- struct btd_adapter *adapter = auth->adapter;
+ struct btd_adapter *adapter = user_data;
+ struct service_auth *auth = adapter->auth;
+ adapter->auth = NULL;
adapter->auth_idle_id = 0;
auth->cb(NULL, auth->user_data);
+ g_free(auth);
+
return FALSE;
}
@@ -3181,7 +3194,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
if (!g_slist_find(adapter->connections, device))
error("Authorization request for non-connected device!?");
- if (adapter->auth_idle_id)
+ if (adapter->auth != NULL)
return -EBUSY;
auth = g_try_new0(struct service_auth, 1);
@@ -3194,10 +3207,8 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
auth->adapter = adapter;
if (device_is_trusted(device) == TRUE) {
- adapter->auth_idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
- auth_idle_cb, auth,
- g_free);
- return 0;
+ adapter->auth_idle_id = g_idle_add(auth_idle_cb, adapter);
+ goto done;
}
agent = device_get_agent(device);
@@ -3209,13 +3220,16 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
dev_path = device_get_path(device);
- err = agent_authorize(agent, dev_path, uuid, agent_auth_cb, auth, g_free);
- if (err < 0)
+ err = agent_authorize(agent, dev_path, uuid, agent_auth_cb, adapter,
+ NULL);
+ if (err < 0) {
g_free(auth);
- else
- device_set_authorizing(device, TRUE);
+ return err;
+ }
- return err;
+done:
+ adapter->auth = auth;
+ return 0;
}
int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
@@ -3268,6 +3282,9 @@ int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
return 0;
}
+ if (!adapter->auth || adapter->auth->device != device)
+ return -EPERM;
+
/*
* FIXME: Cancel fails if authorization is requested to adapter's
* agent and in the meanwhile CreatePairedDevice is called.
@@ -3279,8 +3296,10 @@ int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
err = agent_cancel(agent);
- if (err == 0)
- device_set_authorizing(device, FALSE);
+ if (err == 0) {
+ g_free(adapter->auth);
+ adapter->auth = NULL;
+ }
return err;
}
diff --git a/src/device.c b/src/device.c
index aa3a607..a19e98d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -161,7 +161,6 @@ struct btd_device {
gboolean bonded;
gboolean auto_connect;
- gboolean authorizing;
gint ref;
GIOChannel *att_io;
@@ -2916,16 +2915,6 @@ gboolean device_is_authenticating(struct btd_device *device)
return (device->authr != NULL);
}
-gboolean device_is_authorizing(struct btd_device *device)
-{
- return device->authorizing;
-}
-
-void device_set_authorizing(struct btd_device *device, gboolean auth)
-{
- device->authorizing = auth;
-}
-
void device_register_services(struct btd_device *device,
GSList *prim_list, int psm)
{
diff --git a/src/device.h b/src/device.h
index aee6d13..b704a4c 100644
--- a/src/device.h
+++ b/src/device.h
@@ -98,8 +98,6 @@ int device_notify_pincode(struct btd_device *device, gboolean secure,
const char *pincode, void *cb);
void device_cancel_authentication(struct btd_device *device, gboolean aborted);
gboolean device_is_authenticating(struct btd_device *device);
-gboolean device_is_authorizing(struct btd_device *device);
-void device_set_authorizing(struct btd_device *device, gboolean auth);
void device_add_connection(struct btd_device *device);
void device_remove_connection(struct btd_device *device);
void device_request_disconnect(struct btd_device *device, DBusMessage *msg);
--
1.7.11.4
^ permalink raw reply related
* [PATCH v2 2/6] audio: Fix crash on gateway close
From: Mikel Astiz @ 2012-09-25 14:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348584946-13895-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
gateway_close() can be called multiple times and thus the code must
handle the case where device->gateway is already NULL.
This issue can be easily reproduced if a device is removed (unpaired)
while HFP gateway is connected.
---
audio/gateway.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/audio/gateway.c b/audio/gateway.c
index 45b25a1..93a70ba 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -566,6 +566,9 @@ int gateway_close(struct audio_device *device)
struct gateway *gw = device->gateway;
int sock;
+ if (gw == NULL)
+ return 0;
+
if (gw->rfcomm) {
sock = g_io_channel_unix_get_fd(gw->rfcomm);
shutdown(sock, SHUT_RDWR);
--
1.7.11.4
^ permalink raw reply related
* [PATCH v2 1/6] build: Update glib dependency to 2.32
From: Mikel Astiz @ 2012-09-25 14:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348584946-13895-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
This version of the library adds several convenient features such as
g_queue_free_full.
---
acinclude.m4 | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/acinclude.m4 b/acinclude.m4
index 39b0a18..02e28bc 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -99,8 +99,8 @@ AC_DEFUN([AC_PATH_DBUS], [
])
AC_DEFUN([AC_PATH_GLIB], [
- PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes,
- AC_MSG_ERROR(GLib >= 2.28 is required))
+ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.32 is required))
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
])
--
1.7.11.4
^ permalink raw reply related
* [PATCH v2 0/6] Audio profile authorization
From: Mikel Astiz @ 2012-09-25 14:55 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
v2 includes the modification suggested by Luiz:
- Variable renaming from auth_id to id
- Use of g_queue_free_full, requiring a dependency update to glib 2.32
>From original cover-letter:
The agent-based profile authorization makes a special consideration for audio profiles: they are processed as if they all belonged to one single profile. This includes several internal policies that are inconvenient for IVI use-cases.
This patchset removes this exception by making use of the conventional authorization mechanism also for audio profiles.
The new approach is not straightforward since devices might send several connection requets in parallel (i.e. HFP, A2DP, AVRCP). This cannot be neither automatically rejected (EBUSY) nor forwarded in parallel to the agent, so a queue was added to store the pending authorization requests. These will be sent to the agent sequentially.
Mikel Astiz (6):
build: Update glib dependency to 2.32
audio: Fix crash on gateway close
adapter: Replace device authorizing flag
adapter: Use authorization id for cancelling
adapter: Queue parallel authorization requests
audio: Drop audio-specific authorization mechanism
acinclude.m4 | 4 +-
audio/avctp.c | 29 +++-----
audio/avdtp.c | 25 +++++--
audio/device.c | 144 ------------------------------------
audio/device.h | 12 +--
audio/gateway.c | 3 +
audio/manager.c | 18 +++--
plugins/service.c | 18 +++--
profiles/input/server.c | 2 +-
src/adapter.c | 193 +++++++++++++++++++++++++++++++-----------------
src/adapter.h | 2 +-
src/device.c | 11 ---
src/device.h | 2 -
13 files changed, 183 insertions(+), 280 deletions(-)
--
1.7.11.4
^ permalink raw reply
* [PATCH 14/14] thermometer: Fix missing braces
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
profiles/thermometer/thermometer.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 8733843..0e2bf0a 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -335,8 +335,9 @@ static void change_property(struct thermometer *t, const char *name,
emit_property_changed(device_get_path(t->dev),
THERMOMETER_INTERFACE, name,
DBUS_TYPE_UINT16, &t->min);
- } else
+ } else {
DBG("%s is not a thermometer property", name);
+ }
}
static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
@@ -421,8 +422,9 @@ static void process_thermometer_desc(struct descriptor *desc)
val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
msg = g_strdup("Enable Measurement Interval "
"indication");
- } else
+ } else {
goto done;
+ }
att_put_u16(val, atval);
gatt_write_char(ch->t->attrib, desc->handle, atval, 2,
@@ -548,12 +550,13 @@ static void process_thermometer_char(struct characteristic *ch)
gboolean intermediate = TRUE;
change_property(ch->t, "Intermediate", &intermediate);
return;
- } else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0)
+ } else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0) {
gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
read_temp_type_cb, ch);
- else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
+ } else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0) {
gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
read_interval_cb, ch);
+ }
}
static void configure_thermometer_cb(GSList *characteristics, guint8 status,
@@ -591,10 +594,11 @@ static void configure_thermometer_cb(GSList *characteristics, guint8 status,
if (start == c->handle)
continue;
end = c->handle - 1;
- } else if (c->value_handle != t->svc_range->end)
+ } else if (c->value_handle != t->svc_range->end) {
end = t->svc_range->end;
- else
+ } else {
continue;
+ }
gatt_find_info(t->attrib, start, end, discover_desc_cb, ch);
}
--
1.7.11.3
^ permalink raw reply related
* [PATCH 13/14] thermometer: Fix indentation
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
profiles/thermometer/thermometer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 7c9cd0e..8733843 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -83,7 +83,7 @@ struct thermometer {
};
struct characteristic {
- struct gatt_char attr; /* Characteristic */
+ struct gatt_char attr; /* Characteristic */
GSList *desc; /* Descriptors */
struct thermometer *t; /* Thermometer where the char belongs */
};
--
1.7.11.3
^ permalink raw reply related
* [PATCH 12/14] thermometer: Fix whitespace
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
profiles/thermometer/thermometer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index f42ab7d..7c9cd0e 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -634,7 +634,7 @@ static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
return reply;
}
-static void write_interval_cb (guint8 status, const guint8 *pdu, guint16 len,
+static void write_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
struct tmp_interval_data *data = user_data;
--
1.7.11.3
^ permalink raw reply related
* [PATCH 11/14] thermometer: Refactor processing of measurement characteristic value
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
Data buffer is read by simply moving buffer pointer instead of calculating
indexes of consecutive fields. This makes function flow easier to follow
as there's no need to care about presence of fields prior to current when
reading data.
---
profiles/thermometer/thermometer.c | 66 +++++++++++++++++++++-----------------
1 file changed, 37 insertions(+), 29 deletions(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 29d5e02..f42ab7d 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -1021,27 +1021,37 @@ static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
uint16_t len, gboolean final)
{
struct measurement m;
- const char *type;
+ const char *type = NULL;
uint8_t flags;
uint32_t raw;
- if (len < 4) {
+ /* skip opcode and handle */
+ pdu += 3;
+ len -= 3;
+
+ if (len < 1) {
DBG("Mandatory flags are not provided");
return;
}
- flags = pdu[3];
+ flags = *pdu;
+
if (flags & TEMP_UNITS)
m.unit = "Fahrenheit";
else
m.unit = "Celsius";
- if (len < 8) {
- DBG("Temperature measurement value is not provided");
+ pdu++;
+ len--;
+
+ if (len < 4) {
+ DBG("Mandatory temperature measurement value is not provided");
return;
}
- raw = att_get_u32(&pdu[4]);
+ memset(&m, 0, sizeof(m));
+
+ raw = att_get_u32(pdu);
m.mant = raw & 0x00FFFFFF;
m.exp = ((int32_t) raw) >> 24;
@@ -1050,48 +1060,46 @@ static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
m.mant = m.mant - FLOAT_MAX_MANTISSA;
}
+ pdu += 4;
+ len -= 4;
+
if (flags & TEMP_TIME_STAMP) {
struct tm ts;
time_t time;
- if (len < 15) {
- DBG("Can't get time stamp value");
+ if (len < 7) {
+ DBG("Time stamp is not provided");
return;
}
- ts.tm_year = att_get_u16(&pdu[8]) - 1900;
- ts.tm_mon = pdu[10] - 1;
- ts.tm_mday = pdu[11];
- ts.tm_hour = pdu[12];
- ts.tm_min = pdu[13];
- ts.tm_sec = pdu[14];
+ ts.tm_year = att_get_u16(pdu) - 1900;
+ ts.tm_mon = *(pdu + 2) - 1;
+ ts.tm_mday = *(pdu + 3);
+ ts.tm_hour = *(pdu + 4);
+ ts.tm_min = *(pdu + 5);
+ ts.tm_sec = *(pdu + 6);
ts.tm_isdst = -1;
time = mktime(&ts);
m.time = (uint64_t) time;
m.suptime = TRUE;
- } else
- m.suptime = FALSE;
+
+ pdu += 7;
+ len -= 7;
+ }
if (flags & TEMP_TYPE) {
- uint8_t index;
-
- if (m.suptime && len >= 16)
- index = 15;
- else if (!m.suptime && len >= 9)
- index = 9;
- else {
- DBG("Can't get temperature type");
+ if (len < 1) {
+ DBG("Temperature type is not provided");
return;
}
- type = temptype2str(pdu[index]);
- } else if (t->has_type)
+ type = temptype2str(*pdu);
+ } else if (t->has_type) {
type = temptype2str(t->type);
- else
- type = NULL;
+ }
- m.type = type ? g_strdup(type) : NULL;
+ m.type = g_strdup(type);
m.value = final ? "Final" : "Intermediate";
recv_measurement(t, &m);
--
1.7.11.3
^ permalink raw reply related
* [PATCH 10/14] thermometer: Add common function to write characteristics CCC
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
There are now few separate functions to write CCC for measurement
characteristics which looks similar. This patch adds common function
to write given value into CCC for given characteristics and leaves
dedicated functions to act only as simple wrappers.
---
profiles/thermometer/thermometer.c | 108 ++++++++-----------------------------
1 file changed, 23 insertions(+), 85 deletions(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 6f3314a..29d5e02 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -376,7 +376,7 @@ static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
change_property(desc->ch->t, "Minimum", &min);
}
-static void measurement_cb(guint8 status, const guint8 *pdu,
+static void write_ccc_cb(guint8 status, const guint8 *pdu,
guint16 len, gpointer user_data)
{
char *msg = user_data;
@@ -426,7 +426,7 @@ static void process_thermometer_desc(struct descriptor *desc)
att_put_u16(val, atval);
gatt_write_char(ch->t->attrib, desc->handle, atval, 2,
- measurement_cb, msg);
+ write_ccc_cb, msg);
return;
}
@@ -720,9 +720,8 @@ static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
return write_attr_interval(t, msg, value);
}
-static void enable_final_measurement(gpointer data, gpointer user_data)
+static void write_ccc(struct thermometer *t, const char *uuid, uint16_t value)
{
- struct thermometer *t = data;
struct characteristic *ch;
struct descriptor *desc;
bt_uuid_t btuuid;
@@ -732,116 +731,55 @@ static void enable_final_measurement(gpointer data, gpointer user_data)
if (t->attrib == NULL)
return;
- ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
+ ch = get_characteristic(t, uuid);
if (ch == NULL) {
- DBG("Temperature measurement characteristic not found");
+ DBG("Characteristic %s not found", uuid);
return;
}
bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
desc = get_descriptor(ch, &btuuid);
if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
+ DBG("CCC descriptor for %s not found", uuid);
return;
}
- atval[0] = 0x02;
- atval[1] = 0x00;
- msg = g_strdup("Enable final measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+ att_put_u16(value, atval);
+
+ msg = g_strdup_printf("Write CCC: %04x for %s", value, uuid);
+
+ gatt_write_char(t->attrib, desc->handle, atval, sizeof(atval),
+ write_ccc_cb, msg);
}
-static void enable_intermediate_measurement(gpointer data, gpointer user_data)
+static void enable_final_measurement(gpointer data, gpointer user_data)
{
struct thermometer *t = data;
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
-
- if (t->attrib == NULL || !t->intermediate)
- return;
- ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
- if (ch == NULL) {
- DBG("Intermediate measurement characteristic not found");
- return;
- }
+ write_ccc(t, TEMPERATURE_MEASUREMENT_UUID,
+ GATT_CLIENT_CHARAC_CFG_IND_BIT);
+}
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
+static void enable_intermediate_measurement(gpointer data, gpointer user_data)
+{
+ struct thermometer *t = data;
- atval[0] = 0x01;
- atval[1] = 0x00;
- msg = g_strdup("Enable intermediate measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+ write_ccc(t, INTERMEDIATE_TEMPERATURE_UUID,
+ GATT_CLIENT_CHARAC_CFG_NOTIF_BIT);
}
static void disable_final_measurement(gpointer data, gpointer user_data)
{
struct thermometer *t = data;
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
- if (t->attrib == NULL)
- return;
-
- ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
- if (ch == NULL) {
- DBG("Temperature measurement characteristic not found");
- return;
- }
-
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
-
- atval[0] = 0x00;
- atval[1] = 0x00;
- msg = g_strdup("Disable final measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+ write_ccc(t, TEMPERATURE_MEASUREMENT_UUID, 0x0000);
}
static void disable_intermediate_measurement(gpointer data, gpointer user_data)
{
struct thermometer *t = data;
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
-
- if (t->attrib == NULL)
- return;
-
- ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
- if (ch == NULL) {
- DBG("Intermediate measurement characteristic not found");
- return;
- }
-
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
- atval[0] = 0x00;
- atval[1] = 0x00;
- msg = g_strdup("Disable intermediate measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+ write_ccc(t, INTERMEDIATE_TEMPERATURE_UUID, 0x0000);
}
static void remove_int_watcher(struct thermometer_adapter *tadapter,
--
1.7.11.3
^ permalink raw reply related
* [PATCH 09/14] thermometer: Add constant definition for watcher interface name
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
profiles/thermometer/thermometer.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index f0c1d67..6f3314a 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -44,6 +44,7 @@
#define THERMOMETER_INTERFACE "org.bluez.Thermometer"
#define THERMOMETER_MANAGER_INTERFACE "org.bluez.ThermometerManager"
+#define THERMOMETER_WATCHER_INTERFACE "org.bluez.ThermometerWatcher"
/* Temperature measurement flag fields */
#define TEMP_UNITS 0x01
@@ -1034,7 +1035,7 @@ static void update_watcher(gpointer data, gpointer user_data)
DBusMessage *msg;
msg = dbus_message_new_method_call(w->srv, w->path,
- "org.bluez.ThermometerWatcher",
+ THERMOMETER_WATCHER_INTERFACE,
"MeasurementReceived");
if (msg == NULL)
return;
--
1.7.11.3
^ permalink raw reply related
* [PATCH 08/14] thermometer: Update driver naming style
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
This patch changes device probe and remove functions name to include
'device' rather than 'driver' name as it better describes what both
do.
Also profile driver name is changed to better describe that it's now
profile driver rather than device driver only.
---
profiles/thermometer/manager.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/profiles/thermometer/manager.c b/profiles/thermometer/manager.c
index 86e3a0f..6057633 100644
--- a/profiles/thermometer/manager.c
+++ b/profiles/thermometer/manager.c
@@ -41,7 +41,7 @@ static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
return g_strcmp0(prim->uuid, uuid);
}
-static int thermometer_driver_probe(struct btd_profile *p,
+static int thermometer_device_probe(struct btd_profile *p,
struct btd_device *device,
GSList *uuids)
{
@@ -60,7 +60,7 @@ static int thermometer_driver_probe(struct btd_profile *p,
return thermometer_register(device, tattr);
}
-static void thermometer_driver_remove(struct btd_profile *p,
+static void thermometer_device_remove(struct btd_profile *p,
struct btd_device *device)
{
thermometer_unregister(device);
@@ -79,10 +79,10 @@ static void thermometer_adapter_remove(struct btd_profile *p,
}
static struct btd_profile thermometer_profile = {
- .name = "thermometer-device-driver",
+ .name = "Health Thermometer GATT driver",
.remote_uuids = BTD_UUIDS(HEALTH_THERMOMETER_UUID),
- .device_probe = thermometer_driver_probe,
- .device_remove = thermometer_driver_remove,
+ .device_probe = thermometer_device_probe,
+ .device_remove = thermometer_device_remove,
.adapter_probe = thermometer_adapter_probe,
.adapter_remove = thermometer_adapter_remove
};
--
1.7.11.3
^ permalink raw reply related
* [PATCH 07/14] thermometer: Reformat MeasurementReceived description
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
MeasurementReceived method description is reformatted to be more
readable and consistent with other API documents.
Special values for Exponent and Mantissa fields specify now only NaN
value as this is only special value defined by HTS specification for
measurement.
---
doc/thermometer-api.txt | 67 +++++++++++++++++++++++++++----------------------
1 file changed, 37 insertions(+), 30 deletions(-)
diff --git a/doc/thermometer-api.txt b/doc/thermometer-api.txt
index b0b0fe2..1665aa1 100644
--- a/doc/thermometer-api.txt
+++ b/doc/thermometer-api.txt
@@ -96,33 +96,40 @@ Service unique name
Interface org.bluez.ThermometerWatcher
Object path freely definable
-Methods void MeasurementReceived(dict measure)
-
- This callback gets called when a measure has been
- scanned in the thermometer. The Time entry in the dict
- will be only present if the device supports storing of
- data. The time value is expressed in seconds since epoch.
- The value represented is (mantissa) x (10**exponent)
- See foot note for special values when treating with
- health devices. The Type entry is only present if the
- measurement type is known. Otherwise, it is undefined.
-
- Dict is defined as below:
- {
- "Exponent" : int8,
- "Mantissa" : int32,
- "Unit" : ("Celsius" or "Fahrenheit"),
- "Time" : uint64,
- "Type" : ("Armpit", "Body", "Ear", "Finger",
- "Intestines", "Mouth", "Rectum", "Toe",
- "Tympanum"),
- "Measurement" : ("Final" or "Intermediate"),
- }
-
- For special cases, the exponent shall always be zero and
- the mantissa should be one of following values:
-
- NRes = -(2**23)
- NaN = +(2**23-1)
- INFINITY = (2**23-2)
- -INFINITY = -(2**23-2)
+Methods void MeasurementReceived(dict measurement)
+
+ This callback gets called when a measurement has been
+ scanned in the thermometer.
+
+ Measurement:
+
+ int16 Exponent:
+ int32 Mantissa:
+
+ Measurement value is calculated as
+ (Mantissa) x (10^Exponent)
+
+ In case of invalid or missing data,
+ Exponent is set to 0 and Mantissa is
+ set to 2^23-1 (0x7FFFFF hexadecimal).
+
+ string Unit:
+
+ Possible values: "Celsius" or "Fahrenheit"
+
+ uint64 Time (optional):
+
+ Time of measurement, if supported by device.
+ Expressed in seconds since epoch.
+
+ string Type (optional):
+
+ Only present if measurement type is known.
+
+ Possible values: "Armpit", "Body", "Ear",
+ "Finger", "Intestines", "Mouth",
+ "Rectum", "Toe", "Tympanum"
+
+ string Measurement:
+
+ Possible values: "Final" or "Intermediate"
--
1.7.11.3
^ permalink raw reply related
* [PATCH 06/14] thermometer: Update test script
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
test/test-thermometer | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/test/test-thermometer b/test/test-thermometer
index 9216264..2ca260f 100755
--- a/test/test-thermometer
+++ b/test/test-thermometer
@@ -16,9 +16,9 @@ from optparse import OptionParser, make_option
class Watcher(dbus.service.Object):
@dbus.service.method("org.bluez.ThermometerWatcher",
- in_signature="a{sv}", out_signature="")
- def MeasurementReceived(self, measure):
- print(measure["Measurement"], " measurement received")
+ in_signature="oa{sv}", out_signature="")
+ def MeasurementReceived(self, device, measure):
+ print("%s measurement received from %s" % (measure["Measurement"], device))
print("Exponent: ", measure["Exponent"])
print("Mantissa: ", measure["Mantissa"])
print("Unit: ", measure["Unit"])
@@ -66,23 +66,23 @@ if __name__ == "__main__":
adapter = dbus.Interface(bus.get_object("org.bluez", adapter_path),
"org.bluez.Adapter")
+ thermometer_manager = dbus.Interface(bus.get_object("org.bluez",
+ adapter_path), "org.bluez.ThermometerManager")
+
device_path = adapter.FindDevice(options.address)
bus.add_signal_receiver(property_changed, bus_name="org.bluez",
dbus_interface="org.bluez.Thermometer",
signal_name="PropertyChanged")
- thermometer = dbus.Interface(bus.get_object("org.bluez",
- device_path), "org.bluez.Thermometer")
-
path = "/test/watcher"
watcher = Watcher(bus, path)
- thermometer.RegisterWatcher(path)
+ thermometer_manager.RegisterWatcher(path)
if len(args) > 0:
if args[0] == "EnableIntermediateMeasurement":
- thermometer.EnableIntermediateMeasurement(path)
+ thermometer_manager.EnableIntermediateMeasurement(path)
else:
print("unknown command")
sys.exit(1)
--
1.7.11.3
^ permalink raw reply related
* [PATCH 05/14] thermometer: Update API document
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
This patch updates Thermometer API document to reflect changes in
Thermometer interface and introduction of ThermometerManager
interface.
---
doc/thermometer-api.txt | 59 +++++++++++++++++++++++++------------------------
1 file changed, 30 insertions(+), 29 deletions(-)
diff --git a/doc/thermometer-api.txt b/doc/thermometer-api.txt
index 2271270..b0b0fe2 100644
--- a/doc/thermometer-api.txt
+++ b/doc/thermometer-api.txt
@@ -3,28 +3,14 @@ BlueZ D-Bus Thermometer API description
Santiago Carot-Nemesio <sancane@gmail.com>
-Health Thermometer Profile hierarchy
-=====================================
-
-Service org.bluez
-Interface org.bluez.Thermometer
-Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
-
-
-Methods void SetProperty(string name, variant value)
-
- Changes the value of the specified property. Only
- read-write properties can be changed. On success
- this will emit a PropertyChanged signal.
+Health Thermometer Manager hierarchy
+============================
- Possible Errors: org.bluez.Error.InvalidArguments
+Service org.bluez
+Interface org.bluez.ThermometerManager
+Object path [variable prefix]/{hci0,hci1,...}
- dict GetProperties()
-
- Returns all properties for the interface. See the
- Properties section for the available properties.
-
- RegisterWatcher(object agent)
+Methods RegisterWatcher(object agent)
Registers a watcher to monitor scanned measurements.
This agent will be notified about final temperature
@@ -36,30 +22,45 @@ Methods void SetProperty(string name, variant value)
Unregisters a watcher.
- Final and intermediate temperatures won't be notified to
- this agent any more.
-
- Possible Errors: org.bluez.Error.InvalidArguments
- org.bluez.Error.NotFound
-
EnableIntermediateMeasurement(object agent)
Enables intermediate measurement notifications for this
- agent if the thermometer supports it.
+ agent. Intermediate measurements will be enabled only
+ for thermometers which support it.
Possible Errors: org.bluez.Error.InvalidArguments
- org.bluez.Error.NotSupported
DisableIntermediateMeasurement(object agent)
Disables intermediate measurement notifications for this
- agent. It will disable notifications in the thermometer
+ agent. It will disable notifications in thermometers
when the last agent removes the watcher for intermediate
measurements.
Possible Errors: org.bluez.Error.InvalidArguments
org.bluez.Error.NotFound
+Health Thermometer Profile hierarchy
+=====================================
+
+Service org.bluez
+Interface org.bluez.Thermometer
+Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+
+Methods void SetProperty(string name, variant value)
+
+ Changes the value of the specified property. Only
+ read-write properties can be changed. On success
+ this will emit a PropertyChanged signal.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ dict GetProperties()
+
+ Returns all properties for the interface. See the
+ Properties section for the available properties.
+
Signals PropertyChanged(string name, variant value)
This signal indicates a changed value of the given
--
1.7.11.3
^ permalink raw reply related
* [PATCH 04/14] thermometer: Include remote device information in MeasurementReceived
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
Since watchers are now registered per-adapter it's necessary to include
remote device information in MeasurementReceived callback.
This patch adds parameter to MeasurementReceived method which is an
object path to remote device object.
---
profiles/thermometer/thermometer.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 4eb67a7..f0c1d67 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -101,13 +101,14 @@ struct watcher {
};
struct measurement {
- int16_t exp;
- int32_t mant;
- uint64_t time;
- gboolean suptime;
- char *unit;
- char *type;
- char *value;
+ struct thermometer *t;
+ int16_t exp;
+ int32_t mant;
+ uint64_t time;
+ gboolean suptime;
+ char *unit;
+ char *type;
+ char *value;
};
struct tmp_interval_data {
@@ -1027,6 +1028,7 @@ static void update_watcher(gpointer data, gpointer user_data)
{
struct watcher *w = data;
struct measurement *m = user_data;
+ const gchar *path = device_get_path(m->t->dev);
DBusMessageIter iter;
DBusMessageIter dict;
DBusMessage *msg;
@@ -1039,6 +1041,8 @@ static void update_watcher(gpointer data, gpointer user_data)
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
@@ -1064,6 +1068,8 @@ static void recv_measurement(struct thermometer *t, struct measurement *m)
{
GSList *wlist;
+ m->t = t;
+
if (g_strcmp0(m->value, "Intermediate") == 0)
wlist = t->tadapter->iwatchers;
else
--
1.7.11.3
^ permalink raw reply related
* [PATCH 03/14] thermometer: Move watcher logic to adapter interface
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
This patch moves watcher related methods to ThermometerManager interface
so watchers can be registered per-adapter instead of per-device.
Final measurement notifications are now enabled on all devices connected
to given adapter when first watcher is registered and disabled when last
watcher is unregistered.
Intermediate measurement notifications are enabled for all devices
connected to given adapter which support this feature.
---
profiles/thermometer/thermometer.c | 134 +++++++++++++++++++------------------
1 file changed, 70 insertions(+), 64 deletions(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index f2568c9..4eb67a7 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -59,6 +59,8 @@
struct thermometer_adapter {
struct btd_adapter *adapter;
GSList *devices;
+ GSList *fwatchers; /* Final measurements */
+ GSList *iwatchers; /* Intermediate measurements */
};
struct thermometer {
@@ -70,8 +72,6 @@ struct thermometer {
guint attindid; /* Att incications id */
guint attnotid; /* Att notif id */
GSList *chars; /* Characteristics */
- GSList *fwatchers; /* Final measurements */
- GSList *iwatchers; /* Intermediate meas */
gboolean intermediate;
uint8_t type;
uint16_t interval;
@@ -94,10 +94,10 @@ struct descriptor {
};
struct watcher {
- struct thermometer *t;
- guint id;
- char *srv;
- char *path;
+ struct thermometer_adapter *tadapter;
+ guint id;
+ char *srv;
+ char *path;
};
struct measurement {
@@ -182,9 +182,6 @@ static void destroy_thermometer(gpointer user_data)
if (t->chars != NULL)
g_slist_free_full(t->chars, destroy_char);
- if (t->fwatchers != NULL)
- g_slist_free_full(t->fwatchers, remove_watcher);
-
btd_device_unref(t->dev);
g_free(t->svc_range);
g_free(t);
@@ -197,6 +194,9 @@ static void destroy_thermometer_adapter(gpointer user_data)
if (tadapter->devices != NULL)
g_slist_free_full(tadapter->devices, destroy_thermometer);
+ if (tadapter->fwatchers != NULL)
+ g_slist_free_full(tadapter->fwatchers, remove_watcher);
+
g_free(tadapter);
}
@@ -400,7 +400,7 @@ static void process_thermometer_desc(struct descriptor *desc)
if (g_strcmp0(ch->attr.uuid,
TEMPERATURE_MEASUREMENT_UUID) == 0) {
- if (g_slist_length(ch->t->fwatchers) == 0)
+ if (g_slist_length(ch->t->tadapter->fwatchers) == 0)
return;
val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
@@ -408,7 +408,7 @@ static void process_thermometer_desc(struct descriptor *desc)
"indication");
} else if (g_strcmp0(ch->attr.uuid,
INTERMEDIATE_TEMPERATURE_UUID) == 0) {
- if (g_slist_length(ch->t->iwatchers) == 0)
+ if (g_slist_length(ch->t->tadapter->iwatchers) == 0)
return;
val = GATT_CLIENT_CHARAC_CFG_NOTIF_BIT;
@@ -718,8 +718,9 @@ static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
return write_attr_interval(t, msg, value);
}
-static void enable_final_measurement(struct thermometer *t)
+static void enable_final_measurement(gpointer data, gpointer user_data)
{
+ struct thermometer *t = data;
struct characteristic *ch;
struct descriptor *desc;
bt_uuid_t btuuid;
@@ -748,15 +749,16 @@ static void enable_final_measurement(struct thermometer *t)
gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
}
-static void enable_intermediate_measurement(struct thermometer *t)
+static void enable_intermediate_measurement(gpointer data, gpointer user_data)
{
+ struct thermometer *t = data;
struct characteristic *ch;
struct descriptor *desc;
bt_uuid_t btuuid;
uint8_t atval[2];
char *msg;
- if (t->attrib == NULL)
+ if (t->attrib == NULL || !t->intermediate)
return;
ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
@@ -778,8 +780,9 @@ static void enable_intermediate_measurement(struct thermometer *t)
gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
}
-static void disable_final_measurement(struct thermometer *t)
+static void disable_final_measurement(gpointer data, gpointer user_data)
{
+ struct thermometer *t = data;
struct characteristic *ch;
struct descriptor *desc;
bt_uuid_t btuuid;
@@ -808,8 +811,9 @@ static void disable_final_measurement(struct thermometer *t)
gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
}
-static void disable_intermediate_measurement(struct thermometer *t)
+static void disable_intermediate_measurement(gpointer data, gpointer user_data)
{
+ struct thermometer *t = data;
struct characteristic *ch;
struct descriptor *desc;
bt_uuid_t btuuid;
@@ -838,31 +842,34 @@ static void disable_intermediate_measurement(struct thermometer *t)
gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
}
-static void remove_int_watcher(struct thermometer *t, struct watcher *w)
+static void remove_int_watcher(struct thermometer_adapter *tadapter,
+ struct watcher *w)
{
- if (!g_slist_find(t->iwatchers, w))
+ if (!g_slist_find(tadapter->iwatchers, w))
return;
- t->iwatchers = g_slist_remove(t->iwatchers, w);
+ tadapter->iwatchers = g_slist_remove(tadapter->iwatchers, w);
- if (g_slist_length(t->iwatchers) == 0)
- disable_intermediate_measurement(t);
+ if (g_slist_length(tadapter->iwatchers) == 0)
+ g_slist_foreach(tadapter->devices,
+ disable_intermediate_measurement, 0);
}
static void watcher_exit(DBusConnection *conn, void *user_data)
{
struct watcher *watcher = user_data;
- struct thermometer *t = watcher->t;
+ struct thermometer_adapter *tadapter = watcher->tadapter;
DBG("Thermometer watcher %s disconnected", watcher->path);
- remove_int_watcher(t, watcher);
+ remove_int_watcher(tadapter, watcher);
- t->fwatchers = g_slist_remove(t->fwatchers, watcher);
+ tadapter->fwatchers = g_slist_remove(tadapter->fwatchers, watcher);
g_dbus_remove_watch(btd_get_dbus_connection(), watcher->id);
- if (g_slist_length(t->fwatchers) == 0)
- disable_final_measurement(t);
+ if (g_slist_length(tadapter->fwatchers) == 0)
+ g_slist_foreach(tadapter->devices,
+ disable_final_measurement, 0);
}
static struct watcher *find_watcher(GSList *list, const char *sender,
@@ -888,7 +895,7 @@ static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
void *data)
{
const char *sender = dbus_message_get_sender(msg);
- struct thermometer *t = data;
+ struct thermometer_adapter *tadapter = data;
struct watcher *watcher;
char *path;
@@ -896,7 +903,7 @@ static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
DBUS_TYPE_INVALID))
return btd_error_invalid_args(msg);
- watcher = find_watcher(t->fwatchers, sender, path);
+ watcher = find_watcher(tadapter->fwatchers, sender, path);
if (watcher != NULL)
return btd_error_already_exists(msg);
@@ -905,14 +912,14 @@ static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
watcher = g_new0(struct watcher, 1);
watcher->srv = g_strdup(sender);
watcher->path = g_strdup(path);
- watcher->t = t;
+ watcher->tadapter = tadapter;
watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit,
watcher, destroy_watcher);
- if (g_slist_length(t->fwatchers) == 0)
- enable_final_measurement(t);
+ if (g_slist_length(tadapter->fwatchers) == 0)
+ g_slist_foreach(tadapter->devices, enable_final_measurement, 0);
- t->fwatchers = g_slist_prepend(t->fwatchers, watcher);
+ tadapter->fwatchers = g_slist_prepend(tadapter->fwatchers, watcher);
return dbus_message_new_method_return(msg);
}
@@ -921,7 +928,7 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
void *data)
{
const char *sender = dbus_message_get_sender(msg);
- struct thermometer *t = data;
+ struct thermometer_adapter *tadapter = data;
struct watcher *watcher;
char *path;
@@ -929,19 +936,20 @@ static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
DBUS_TYPE_INVALID))
return btd_error_invalid_args(msg);
- watcher = find_watcher(t->fwatchers, sender, path);
+ watcher = find_watcher(tadapter->fwatchers, sender, path);
if (watcher == NULL)
return btd_error_does_not_exist(msg);
DBG("Thermometer watcher %s unregistered", path);
- remove_int_watcher(t, watcher);
+ remove_int_watcher(tadapter, watcher);
- t->fwatchers = g_slist_remove(t->fwatchers, watcher);
+ tadapter->fwatchers = g_slist_remove(tadapter->fwatchers, watcher);
g_dbus_remove_watch(btd_get_dbus_connection(), watcher->id);
- if (g_slist_length(t->fwatchers) == 0)
- disable_final_measurement(t);
+ if (g_slist_length(tadapter->fwatchers) == 0)
+ g_slist_foreach(tadapter->devices,
+ disable_final_measurement, 0);
return dbus_message_new_method_return(msg);
}
@@ -950,30 +958,28 @@ static DBusMessage *enable_intermediate(DBusConnection *conn, DBusMessage *msg,
void *data)
{
const char *sender = dbus_message_get_sender(msg);
- struct thermometer *t = data;
+ struct thermometer_adapter *ta = data;
struct watcher *watcher;
char *path;
- if (!t->intermediate)
- return btd_error_not_supported(msg);
-
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID))
return btd_error_invalid_args(msg);
- watcher = find_watcher(t->fwatchers, sender, path);
+ watcher = find_watcher(ta->fwatchers, sender, path);
if (watcher == NULL)
return btd_error_does_not_exist(msg);
- if (find_watcher(t->iwatchers, sender, path))
+ if (find_watcher(ta->iwatchers, sender, path))
return btd_error_already_exists(msg);
DBG("Intermediate measurement watcher %s registered", path);
- if (g_slist_length(t->iwatchers) == 0)
- enable_intermediate_measurement(t);
+ if (g_slist_length(ta->iwatchers) == 0)
+ g_slist_foreach(ta->devices,
+ enable_intermediate_measurement, 0);
- t->iwatchers = g_slist_prepend(t->iwatchers, watcher);
+ ta->iwatchers = g_slist_prepend(ta->iwatchers, watcher);
return dbus_message_new_method_return(msg);
}
@@ -982,7 +988,7 @@ static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
void *data)
{
const char *sender = dbus_message_get_sender(msg);
- struct thermometer *t = data;
+ struct thermometer_adapter *ta = data;
struct watcher *watcher;
char *path;
@@ -990,13 +996,13 @@ static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
DBUS_TYPE_INVALID))
return btd_error_invalid_args(msg);
- watcher = find_watcher(t->iwatchers, sender, path);
+ watcher = find_watcher(ta->iwatchers, sender, path);
if (watcher == NULL)
return btd_error_does_not_exist(msg);
DBG("Intermediate measurement %s unregistered", path);
- remove_int_watcher(t, watcher);
+ remove_int_watcher(ta, watcher);
return dbus_message_new_method_return(msg);
}
@@ -1008,18 +1014,6 @@ static const GDBusMethodTable thermometer_methods[] = {
{ GDBUS_ASYNC_METHOD("SetProperty",
GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL,
set_property) },
- { GDBUS_METHOD("RegisterWatcher",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- register_watcher) },
- { GDBUS_METHOD("UnregisterWatcher",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- unregister_watcher) },
- { GDBUS_METHOD("EnableIntermediateMeasurement",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- enable_intermediate) },
- { GDBUS_METHOD("DisableIntermediateMeasurement",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- disable_intermediate) },
{ }
};
@@ -1071,9 +1065,9 @@ static void recv_measurement(struct thermometer *t, struct measurement *m)
GSList *wlist;
if (g_strcmp0(m->value, "Intermediate") == 0)
- wlist = t->iwatchers;
+ wlist = t->tadapter->iwatchers;
else
- wlist = t->fwatchers;
+ wlist = t->tadapter->fwatchers;
g_slist_foreach(wlist, update_watcher, m);
}
@@ -1333,6 +1327,18 @@ void thermometer_unregister(struct btd_device *device)
}
static const GDBusMethodTable thermometer_manager_methods[] = {
+ { GDBUS_METHOD("RegisterWatcher",
+ GDBUS_ARGS({ "agent", "o" }), NULL,
+ register_watcher) },
+ { GDBUS_METHOD("UnregisterWatcher",
+ GDBUS_ARGS({ "agent", "o" }), NULL,
+ unregister_watcher) },
+ { GDBUS_METHOD("EnableIntermediateMeasurement",
+ GDBUS_ARGS({ "agent", "o" }), NULL,
+ enable_intermediate) },
+ { GDBUS_METHOD("DisableIntermediateMeasurement",
+ GDBUS_ARGS({ "agent", "o" }), NULL,
+ disable_intermediate) },
{ }
};
--
1.7.11.3
^ permalink raw reply related
* [PATCH 02/14] thermometer: Register ThermometerManager interface on adapter path
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
profiles/thermometer/thermometer.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index c8a6826..f2568c9 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -42,7 +42,8 @@
#include "gatt.h"
#include "thermometer.h"
-#define THERMOMETER_INTERFACE "org.bluez.Thermometer"
+#define THERMOMETER_INTERFACE "org.bluez.Thermometer"
+#define THERMOMETER_MANAGER_INTERFACE "org.bluez.ThermometerManager"
/* Temperature measurement flag fields */
#define TEMP_UNITS 0x01
@@ -189,6 +190,16 @@ static void destroy_thermometer(gpointer user_data)
g_free(t);
}
+static void destroy_thermometer_adapter(gpointer user_data)
+{
+ struct thermometer_adapter *tadapter = user_data;
+
+ if (tadapter->devices != NULL)
+ g_slist_free_full(tadapter->devices, destroy_thermometer);
+
+ g_free(tadapter);
+}
+
static gint cmp_adapter(gconstpointer a, gconstpointer b)
{
const struct thermometer_adapter *tadapter = a;
@@ -1321,6 +1332,10 @@ void thermometer_unregister(struct btd_device *device)
device_get_path(t->dev), THERMOMETER_INTERFACE);
}
+static const GDBusMethodTable thermometer_manager_methods[] = {
+ { }
+};
+
int thermometer_adapter_register(struct btd_adapter *adapter)
{
struct thermometer_adapter *tadapter;
@@ -1328,6 +1343,18 @@ int thermometer_adapter_register(struct btd_adapter *adapter)
tadapter = g_new0(struct thermometer_adapter, 1);
tadapter->adapter = adapter;
+ if (!g_dbus_register_interface(btd_get_dbus_connection(),
+ adapter_get_path(adapter),
+ THERMOMETER_MANAGER_INTERFACE,
+ thermometer_manager_methods,
+ NULL, NULL, tadapter,
+ destroy_thermometer_adapter)) {
+ error("D-Bus failed to register %s interface",
+ THERMOMETER_MANAGER_INTERFACE);
+ destroy_thermometer_adapter(tadapter);
+ return -EIO;
+ }
+
thermometer_adapters = g_slist_prepend(thermometer_adapters, tadapter);
return 0;
@@ -1342,4 +1369,8 @@ void thermometer_adapter_unregister(struct btd_adapter *adapter)
return;
thermometer_adapters = g_slist_remove(thermometer_adapters, tadapter);
+
+ g_dbus_unregister_interface(btd_get_dbus_connection(),
+ adapter_get_path(tadapter->adapter),
+ THERMOMETER_MANAGER_INTERFACE);
}
--
1.7.11.3
^ permalink raw reply related
* [PATCH 01/14] thermometer: Store thermometer devices per-adapter
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1348584763-22824-1-git-send-email-andrzej.kaczmarek@tieto.com>
This patch replaces global list of thermometer devices with per-adapter
lists.
---
profiles/thermometer/manager.c | 16 +++++-
profiles/thermometer/thermometer.c | 114 ++++++++++++++++++++++++++++++-------
profiles/thermometer/thermometer.h | 2 +
3 files changed, 110 insertions(+), 22 deletions(-)
diff --git a/profiles/thermometer/manager.c b/profiles/thermometer/manager.c
index d965976..86e3a0f 100644
--- a/profiles/thermometer/manager.c
+++ b/profiles/thermometer/manager.c
@@ -66,11 +66,25 @@ static void thermometer_driver_remove(struct btd_profile *p,
thermometer_unregister(device);
}
+static int thermometer_adapter_probe(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ return thermometer_adapter_register(adapter);
+}
+
+static void thermometer_adapter_remove(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ thermometer_adapter_unregister(adapter);
+}
+
static struct btd_profile thermometer_profile = {
.name = "thermometer-device-driver",
.remote_uuids = BTD_UUIDS(HEALTH_THERMOMETER_UUID),
.device_probe = thermometer_driver_probe,
- .device_remove = thermometer_driver_remove
+ .device_remove = thermometer_driver_remove,
+ .adapter_probe = thermometer_adapter_probe,
+ .adapter_remove = thermometer_adapter_remove
};
int thermometer_manager_init(void)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 77dcb26..c8a6826 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -55,23 +55,29 @@
#define TEMPERATURE_TYPE_SIZE 1
#define MEASUREMENT_INTERVAL_SIZE 2
+struct thermometer_adapter {
+ struct btd_adapter *adapter;
+ GSList *devices;
+};
+
struct thermometer {
- struct btd_device *dev; /* Device reference */
- GAttrib *attrib; /* GATT connection */
- struct att_range *svc_range; /* Thermometer range */
- guint attioid; /* Att watcher id */
- guint attindid; /* Att incications id */
- guint attnotid; /* Att notifications id */
- GSList *chars; /* Characteristics */
- GSList *fwatchers; /* Final measurements */
- GSList *iwatchers; /* Intermediate measurements */
- gboolean intermediate;
- uint8_t type;
- uint16_t interval;
- uint16_t max;
- uint16_t min;
- gboolean has_type;
- gboolean has_interval;
+ struct btd_device *dev; /* Device reference */
+ struct thermometer_adapter *tadapter;
+ GAttrib *attrib; /* GATT connection */
+ struct att_range *svc_range; /* Thermometer range */
+ guint attioid; /* Att watcher id */
+ guint attindid; /* Att incications id */
+ guint attnotid; /* Att notif id */
+ GSList *chars; /* Characteristics */
+ GSList *fwatchers; /* Final measurements */
+ GSList *iwatchers; /* Intermediate meas */
+ gboolean intermediate;
+ uint8_t type;
+ uint16_t interval;
+ uint16_t max;
+ uint16_t min;
+ gboolean has_type;
+ gboolean has_interval;
};
struct characteristic {
@@ -108,7 +114,7 @@ struct tmp_interval_data {
uint16_t interval;
};
-static GSList *thermometers = NULL;
+static GSList *thermometer_adapters = NULL;
const char *temp_type[] = {
"<reserved>",
@@ -183,6 +189,17 @@ static void destroy_thermometer(gpointer user_data)
g_free(t);
}
+static gint cmp_adapter(gconstpointer a, gconstpointer b)
+{
+ const struct thermometer_adapter *tadapter = a;
+ const struct btd_adapter *adapter = b;
+
+ if (adapter == tadapter->adapter)
+ return 0;
+
+ return -1;
+}
+
static gint cmp_device(gconstpointer a, gconstpointer b)
{
const struct thermometer *t = a;
@@ -231,6 +248,17 @@ static gint cmp_descriptor(gconstpointer a, gconstpointer b)
return bt_uuid_cmp(&desc->uuid, uuid);
}
+static struct thermometer_adapter *
+find_thermometer_adapter(struct btd_adapter *adapter)
+{
+ GSList *l = g_slist_find_custom(thermometer_adapters, adapter,
+ cmp_adapter);
+ if (!l)
+ return NULL;
+
+ return l->data;
+}
+
static struct characteristic *get_characteristic(struct thermometer *t,
const char *uuid)
{
@@ -1233,13 +1261,25 @@ int thermometer_register(struct btd_device *device, struct gatt_primary *tattr)
{
const gchar *path = device_get_path(device);
struct thermometer *t;
+ struct btd_adapter *adapter;
+ struct thermometer_adapter *tadapter;
+
+ adapter = device_get_adapter(device);
+
+ tadapter = find_thermometer_adapter(adapter);
+
+ if (tadapter == NULL)
+ return -1;
t = g_new0(struct thermometer, 1);
t->dev = btd_device_ref(device);
+ t->tadapter = tadapter;
t->svc_range = g_new0(struct att_range, 1);
t->svc_range->start = tattr->range.start;
t->svc_range->end = tattr->range.end;
+ tadapter->devices = g_slist_prepend(tadapter->devices, t);
+
if (!g_dbus_register_interface(btd_get_dbus_connection(),
path, THERMOMETER_INTERFACE,
thermometer_methods, thermometer_signals,
@@ -1250,8 +1290,6 @@ int thermometer_register(struct btd_device *device, struct gatt_primary *tattr)
return -EIO;
}
- thermometers = g_slist_prepend(thermometers, t);
-
t->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
attio_disconnected_cb, t);
return 0;
@@ -1260,14 +1298,48 @@ int thermometer_register(struct btd_device *device, struct gatt_primary *tattr)
void thermometer_unregister(struct btd_device *device)
{
struct thermometer *t;
+ struct btd_adapter *adapter;
+ struct thermometer_adapter *tadapter;
GSList *l;
- l = g_slist_find_custom(thermometers, device, cmp_device);
+ adapter = device_get_adapter(device);
+
+ tadapter = find_thermometer_adapter(adapter);
+
+ if (tadapter == NULL)
+ return;
+
+ l = g_slist_find_custom(tadapter->devices, device, cmp_device);
if (l == NULL)
return;
t = l->data;
- thermometers = g_slist_remove(thermometers, t);
+
+ tadapter->devices = g_slist_remove(tadapter->devices, t);
+
g_dbus_unregister_interface(btd_get_dbus_connection(),
device_get_path(t->dev), THERMOMETER_INTERFACE);
}
+
+int thermometer_adapter_register(struct btd_adapter *adapter)
+{
+ struct thermometer_adapter *tadapter;
+
+ tadapter = g_new0(struct thermometer_adapter, 1);
+ tadapter->adapter = adapter;
+
+ thermometer_adapters = g_slist_prepend(thermometer_adapters, tadapter);
+
+ return 0;
+}
+
+void thermometer_adapter_unregister(struct btd_adapter *adapter)
+{
+ struct thermometer_adapter *tadapter;
+
+ tadapter = find_thermometer_adapter(adapter);
+ if (tadapter == NULL)
+ return;
+
+ thermometer_adapters = g_slist_remove(thermometer_adapters, tadapter);
+}
diff --git a/profiles/thermometer/thermometer.h b/profiles/thermometer/thermometer.h
index 2744ed6..ca83c31 100644
--- a/profiles/thermometer/thermometer.h
+++ b/profiles/thermometer/thermometer.h
@@ -22,3 +22,5 @@
int thermometer_register(struct btd_device *device, struct gatt_primary *tattr);
void thermometer_unregister(struct btd_device *device);
+int thermometer_adapter_register(struct btd_adapter *adapter);
+void thermometer_adapter_unregister(struct btd_adapter *adapter);
--
1.7.11.3
^ permalink raw reply related
* [PATCH 00/14] Thermometer watchers API change + fixes
From: Andrzej Kaczmarek @ 2012-09-25 14:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
Hi,
Here's series of patches to move watchers from per-device to per-adapter
interface (basically the same as done for HRP, see other series of patches).
This applies to both final and intermediate temperature watchers - once
watcher is registered, all connected devices are setup to send measurement
notifications and the opposite when last watcher is unregistered.
This major change is done in patches 1-6.
Patches 7-11 contain some code and documentation refactoring, i.e. to
remove duplicated code.
Patches 12-14 are trival coding style fixes.
Unfortunately, I wasn't able to fully test this code due to lack of proper
thermometer device and sample device from CC2540 devkit does not quite
work as expected (e.g. I can see CCC is written properly when watcher is
registered but remote does not send any indications for unknown reason).
Andrzej Kaczmarek (14):
thermometer: Store thermometer devices per-adapter
thermometer: Register ThermometerManager interface on adapter path
thermometer: Move watcher logic to adapter interface
thermometer: Include remote device information in MeasurementReceived
thermometer: Update API document
thermometer: Update test script
thermometer: Reformat MeasurementReceived description
thermometer: Update driver naming style
thermometer: Add constant definition for watcher interface name
thermometer: Add common function to write characteristics CCC
thermometer: Refactor processing of measurement characteristic value
thermometer: Fix whitespace
thermometer: Fix indentation
thermometer: Fix missing braces
doc/thermometer-api.txt | 126 +++++-----
profiles/thermometer/manager.c | 24 +-
profiles/thermometer/thermometer.c | 486 +++++++++++++++++++++----------------
profiles/thermometer/thermometer.h | 2 +
test/test-thermometer | 16 +-
5 files changed, 372 insertions(+), 282 deletions(-)
--
1.7.11.3
^ 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