summaryrefslogtreecommitdiff
path: root/audio
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2009-06-15 11:59:18 -0300
committerJohan Hedberg <johan.hedberg@nokia.com>2009-06-15 18:10:39 +0300
commite7e1be5d17f182e5d4119fc47cc18732511e363e (patch)
tree399b67d4d07f59469733fc58e0c55ceca3efeb78 /audio
parentb472464eb89eb97789863c39a8a16cc9de097ee2 (diff)
downloadbluez-e7e1be5d17f182e5d4119fc47cc18732511e363e.tar.gz
Fix bug which cause authorization to be denied in certain headsets.
Some headsets (Nokia HS-12W) connects first on avrcp and only then on hfp so in case Trusted property is not set this will cause agent_authorize to return -EBUSY and drop hfp connection. The proper solution would be to group all connections requests only sending one authorization so the agent either accept them all or not, but that would require API changes which we are avoiding right now, so the current fix only send one connection request which the reponse is used for the rest of the connections.
Diffstat (limited to 'audio')
-rw-r--r--audio/avdtp.c2
-rw-r--r--audio/control.c4
-rw-r--r--audio/device.c42
-rw-r--r--audio/device.h6
-rw-r--r--audio/manager.c8
5 files changed, 55 insertions, 7 deletions
diff --git a/audio/avdtp.c b/audio/avdtp.c
index 4ed0689e4..dbf471950 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -2096,7 +2096,7 @@ 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 = btd_request_authorization(&src, &dst, ADVANCED_AUDIO_UUID,
+ perr = audio_device_request_authorization(dev, ADVANCED_AUDIO_UUID,
auth_cb, session);
if (perr < 0) {
avdtp_unref(session);
diff --git a/audio/control.c b/audio/control.c
index 3f1cb00e1..1bc89561e 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -714,8 +714,8 @@ static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
if (!bt_io_accept(chan, avctp_connect_cb, dev->control,
NULL, NULL))
goto drop;
- } else if (btd_request_authorization(&src, &dst,
- AVRCP_TARGET_UUID, auth_cb, dev->control) < 0)
+ } else if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID,
+ auth_cb, dev->control) < 0)
goto drop;
return;
diff --git a/audio/device.c b/audio/device.c
index 630d1b547..4ef9c3f15 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -71,12 +71,18 @@ 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;
DBusMessage *conn_req;
DBusMessage *dc_req;
@@ -653,3 +659,39 @@ 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;
+
+ 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);
+ }
+}
+
+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;
+
+ 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;
+
+ return btd_request_authorization(&dev->src, &dev->dst, uuid, auth_cb,
+ dev);
+}
diff --git a/audio/device.h b/audio/device.h
index 714a8adfe..4a4805731 100644
--- a/audio/device.h
+++ b/audio/device.h
@@ -79,3 +79,9 @@ void audio_device_unregister(struct audio_device *device);
gboolean audio_device_is_connected(struct audio_device *dev,
const char *interface);
+
+typedef void (*authorization_cb) (DBusError *derr, void *user_data);
+
+int audio_device_request_authorization(struct audio_device *dev,
+ const char *uuid, authorization_cb cb,
+ void *user_data);
diff --git a/audio/manager.c b/audio/manager.c
index 7afed76c9..208476b2b 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -482,8 +482,8 @@ static void ag_confirm(GIOChannel *chan, gpointer data)
headset_set_state(device, HEADSET_STATE_CONNECT_IN_PROGRESS);
- perr = btd_request_authorization(&device->src, &device->dst,
- server_uuid, headset_auth_cb, device);
+ perr = audio_device_request_authorization(device, server_uuid,
+ headset_auth_cb, device);
if (perr < 0) {
debug("Authorization denied: %s", strerror(-perr));
headset_set_state(device, HEADSET_STATE_DISCONNECTED);
@@ -561,8 +561,8 @@ static void hf_io_cb(GIOChannel *chan, gpointer data)
goto drop;
}
- perr = btd_request_authorization(&device->src, &device->dst,
- server_uuid, gateway_auth_cb, device);
+ perr = audio_device_request_authorization(device, server_uuid,
+ gateway_auth_cb, device);
if (perr < 0) {
debug("Authorization denied!");
goto drop;