2012-05-04 13:14:34

by Mikel Astiz

[permalink] [raw]
Subject: [PATCH BlueZ v3 0/6] Multiple Bluetooth SCO connections (userspace)

From: Mikel Astiz <[email protected]>

This version is exactly the same as v2 with the exception of the minor fixes pointed out by Luiz and Vinicius.

>From original cover letter:

This patch series includes patches that have been useful to connect two HCI-based SCO links simultaneously. This can be used for example to connect to HSP headsets at the same time.

The patch series is divided in three groups: kernel patches, BlueZ userspace patches and PulseAudio patches for module-bluetooth-device.

The kernel patches include some code cleanup and more importantly a dynamically changing alternate setting in btusb driver. These ideas have been taken from the patches I found in [1]. The last patch, “Bluetooth: Remove outgoing MTU check” should be considered with care, since there probably are better approaches to solve this (WIP).

The BlueZ userspace patches add some necessary infrastructure to support such use-cases.

The PulseAudio patches provide some changes to be able to test the rest of the code. The first three patches have been reused from a previously submitted patch series, and only the last two patches are relevant for this purpose. They provide some simple workarounds and should not be considered a proper solution.

As I said, the easiest may to test these patches is by using two Bluetooth headsets. You should use the Media API (Enable=Media in audio.conf), connect both headsets, and use pacmd to set their profile to hsp.

[1] http://bluetooth-alsa.sourceforge.net/future.html

Mikel Astiz (6):
audio: Fix gateway state check
audio: Add multiple device search to manager
media: Support multiple transports per endpoint
media: Split media_endpoint_create
media: Create multiple transports if needed
media: Enable parallel requests to endpoint

audio/device.c | 2 +-
audio/manager.c | 25 +++++-
audio/manager.h | 6 ++
audio/media.c | 271 ++++++++++++++++++++++++++++++++++++-------------------
4 files changed, 207 insertions(+), 97 deletions(-)

--
1.7.7.6



2012-05-07 16:57:41

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ v3 0/6] Multiple Bluetooth SCO connections (userspace)

Hi Mikel,

On Fri, May 4, 2012 at 6:14 AM, Mikel Astiz <[email protected]> wrote:
> From: Mikel Astiz <[email protected]>
>
> This version is exactly the same as v2 with the exception of the minor fixes pointed out by Luiz and Vinicius.
>
> From original cover letter:
>
> This patch series includes patches that have been useful to connect two HCI-based SCO links simultaneously. This can be used for example to connect to HSP headsets at the same time.
>
> The patch series is divided in three groups: kernel patches, BlueZ userspace patches and PulseAudio patches for module-bluetooth-device.
>
> The kernel patches include some code cleanup and more importantly a dynamically changing alternate setting in btusb driver. These ideas have been taken from the patches I found in [1]. The last patch, ?Bluetooth: Remove outgoing MTU check? should be considered with care, since there probably are better approaches to solve this (WIP).
>
> The BlueZ userspace patches add some necessary infrastructure to support such use-cases.
>
> The PulseAudio patches provide some changes to be able to test the rest of the code. The first three patches have been reused from a previously submitted patch series, and only the last two patches are relevant for this purpose. They provide some simple workarounds and should not be considered a proper solution.
>
> As I said, the easiest may to test these patches is by using two Bluetooth headsets. You should use the Media API (Enable=Media in audio.conf), connect both headsets, and use pacmd to set their profile to hsp.
>
> [1] http://bluetooth-alsa.sourceforge.net/future.html
>
> Mikel Astiz (6):
> ?audio: Fix gateway state check
> ?audio: Add multiple device search to manager
> ?media: Support multiple transports per endpoint
> ?media: Split media_endpoint_create
> ?media: Create multiple transports if needed
> ?media: Enable parallel requests to endpoint
>
> ?audio/device.c ?| ? ?2 +-
> ?audio/manager.c | ? 25 +++++-
> ?audio/manager.h | ? ?6 ++
> ?audio/media.c ? | ?271 ++++++++++++++++++++++++++++++++++++-------------------
> ?4 files changed, 207 insertions(+), 97 deletions(-)
>
> --
> 1.7.7.6

All 6 patches are now upstream, thanks.



--
Luiz Augusto von Dentz

2012-05-04 13:14:39

by Mikel Astiz

[permalink] [raw]
Subject: [PATCH BlueZ v3 5/6] media: Create multiple transports if needed

From: Mikel Astiz <[email protected]>

During endpoint registration one than one device might be connected.
Thus all matching devices should have one transport each.
---
audio/media.c | 26 ++++++++++++++++++++------
1 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/audio/media.c b/audio/media.c
index 88b994f..9c7a103 100644
--- a/audio/media.c
+++ b/audio/media.c
@@ -688,30 +688,44 @@ static gboolean endpoint_init_a2dp_sink(struct media_endpoint *endpoint,

static gboolean endpoint_init_ag(struct media_endpoint *endpoint, int *err)
{
- struct audio_device *dev;
+ GSList *list;
+ GSList *l;

endpoint->hs_watch = headset_add_state_cb(headset_state_changed,
endpoint);
- dev = manager_find_device(NULL, &endpoint->adapter->src, BDADDR_ANY,
+ list = manager_find_devices(NULL, &endpoint->adapter->src, BDADDR_ANY,
AUDIO_HEADSET_INTERFACE, TRUE);
- if (dev)
+
+ for (l = list; l != NULL; l = l->next) {
+ struct audio_device *dev = l->data;
+
set_configuration(endpoint, dev, NULL, 0,
headset_setconf_cb, dev, NULL);
+ }
+
+ g_slist_free(list);

return TRUE;
}

static gboolean endpoint_init_hs(struct media_endpoint *endpoint, int *err)
{
- struct audio_device *dev;
+ GSList *list;
+ GSList *l;

endpoint->ag_watch = gateway_add_state_cb(gateway_state_changed,
endpoint);
- dev = manager_find_device(NULL, &endpoint->adapter->src, BDADDR_ANY,
+ list = manager_find_devices(NULL, &endpoint->adapter->src, BDADDR_ANY,
AUDIO_GATEWAY_INTERFACE, TRUE);
- if (dev)
+
+ for (l = list; l != NULL; l = l->next) {
+ struct audio_device *dev = l->data;
+
set_configuration(endpoint, dev, NULL, 0,
gateway_setconf_cb, dev, NULL);
+ }
+
+ g_slist_free(list);

return TRUE;
}
--
1.7.7.6


2012-05-04 13:14:40

by Mikel Astiz

[permalink] [raw]
Subject: [PATCH BlueZ v3 6/6] media: Enable parallel requests to endpoint

From: Mikel Astiz <[email protected]>

If endpoint is handling several devices, it should be able to handle
multiple requests, one per each.
---
audio/media.c | 46 ++++++++++++++++++++++++----------------------
1 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/audio/media.c b/audio/media.c
index 9c7a103..61ec153 100644
--- a/audio/media.c
+++ b/audio/media.c
@@ -67,6 +67,7 @@ struct media_adapter {
};

struct endpoint_request {
+ struct media_endpoint *endpoint;
DBusMessage *msg;
DBusPendingCall *call;
media_endpoint_cb_t cb;
@@ -85,7 +86,7 @@ struct media_endpoint {
guint hs_watch;
guint ag_watch;
guint watch;
- struct endpoint_request *request;
+ GSList *requests;
struct media_adapter *adapter;
GSList *transports;
};
@@ -127,15 +128,22 @@ static void endpoint_request_free(struct endpoint_request *request)
g_free(request);
}

-static void media_endpoint_cancel(struct media_endpoint *endpoint)
+static void media_endpoint_cancel(struct endpoint_request *request)
{
- struct endpoint_request *request = endpoint->request;
+ struct media_endpoint *endpoint = request->endpoint;

if (request->call)
dbus_pending_call_cancel(request->call);

+ endpoint->requests = g_slist_remove(endpoint->requests, request);
+
endpoint_request_free(request);
- endpoint->request = NULL;
+}
+
+static void media_endpoint_cancel_all(struct media_endpoint *endpoint)
+{
+ while (endpoint->requests != NULL)
+ media_endpoint_cancel(endpoint->requests->data);
}

static void media_endpoint_destroy(struct media_endpoint *endpoint)
@@ -150,8 +158,7 @@ static void media_endpoint_destroy(struct media_endpoint *endpoint)
if (endpoint->ag_watch)
gateway_remove_state_cb(endpoint->ag_watch);

- if (endpoint->request)
- media_endpoint_cancel(endpoint);
+ media_endpoint_cancel_all(endpoint);

g_slist_free_full(endpoint->transports,
(GDestroyNotify) media_transport_destroy);
@@ -228,8 +235,7 @@ done:

static void clear_endpoint(struct media_endpoint *endpoint)
{
- if (endpoint->request)
- media_endpoint_cancel(endpoint);
+ media_endpoint_cancel_all(endpoint);

while (endpoint->transports != NULL)
clear_configuration(endpoint, endpoint->transports->data);
@@ -237,8 +243,8 @@ static void clear_endpoint(struct media_endpoint *endpoint)

static void endpoint_reply(DBusPendingCall *call, void *user_data)
{
- struct media_endpoint *endpoint = user_data;
- struct endpoint_request *request = endpoint->request;
+ struct endpoint_request *request = user_data;
+ struct media_endpoint *endpoint = request->endpoint;
DBusMessage *reply;
DBusError err;
gboolean value;
@@ -299,9 +305,8 @@ done:
if (request->cb)
request->cb(endpoint, ret, size, request->user_data);

- if (endpoint->request)
- endpoint_request_free(endpoint->request);
- endpoint->request = NULL;
+ endpoint->requests = g_slist_remove(endpoint->requests, request);
+ endpoint_request_free(request);
}

static gboolean media_endpoint_async_call(DBusConnection *conn,
@@ -313,9 +318,6 @@ static gboolean media_endpoint_async_call(DBusConnection *conn,
{
struct endpoint_request *request;

- if (endpoint->request)
- return FALSE;
-
request = g_new0(struct endpoint_request, 1);

/* Timeout should be less than avdtp request timeout (4 seconds) */
@@ -326,13 +328,16 @@ static gboolean media_endpoint_async_call(DBusConnection *conn,
return FALSE;
}

- dbus_pending_call_set_notify(request->call, endpoint_reply, endpoint, NULL);
+ dbus_pending_call_set_notify(request->call, endpoint_reply, request,
+ NULL);

+ request->endpoint = endpoint;
request->msg = msg;
request->cb = cb;
request->destroy = destroy;
request->user_data = user_data;
- endpoint->request = request;
+
+ endpoint->requests = g_slist_append(endpoint->requests, request);

DBG("Calling %s: name = %s path = %s", dbus_message_get_member(msg),
dbus_message_get_destination(msg),
@@ -351,9 +356,6 @@ static gboolean select_configuration(struct media_endpoint *endpoint,
DBusConnection *conn;
DBusMessage *msg;

- if (endpoint->request != NULL)
- return FALSE;
-
conn = endpoint->adapter->conn;

msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
@@ -412,7 +414,7 @@ static gboolean set_configuration(struct media_endpoint *endpoint,

transport = find_device_transport(endpoint, device);

- if (transport != NULL || endpoint->request != NULL)
+ if (transport != NULL)
return FALSE;

conn = endpoint->adapter->conn;
--
1.7.7.6


2012-05-04 13:14:38

by Mikel Astiz

[permalink] [raw]
Subject: [PATCH BlueZ v3 4/6] media: Split media_endpoint_create

From: Mikel Astiz <[email protected]>

This function is starting to be too long and needs to be split.

After this patch, the resulting code should be exactly equivalent as the
previous implementation.
---
audio/media.c | 119 +++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 78 insertions(+), 41 deletions(-)

diff --git a/audio/media.c b/audio/media.c
index fd5a369..88b994f 100644
--- a/audio/media.c
+++ b/audio/media.c
@@ -658,6 +658,64 @@ static void gateway_state_changed(struct audio_device *dev,
}
}

+static gboolean endpoint_init_a2dp_source(struct media_endpoint *endpoint,
+ gboolean delay_reporting,
+ int *err)
+{
+ endpoint->sep = a2dp_add_sep(&endpoint->adapter->src,
+ AVDTP_SEP_TYPE_SOURCE, endpoint->codec,
+ delay_reporting, &a2dp_endpoint,
+ endpoint, a2dp_destroy_endpoint, err);
+ if (endpoint->sep == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean endpoint_init_a2dp_sink(struct media_endpoint *endpoint,
+ gboolean delay_reporting,
+ int *err)
+{
+ endpoint->sep = a2dp_add_sep(&endpoint->adapter->src,
+ AVDTP_SEP_TYPE_SINK, endpoint->codec,
+ delay_reporting, &a2dp_endpoint,
+ endpoint, a2dp_destroy_endpoint, err);
+ if (endpoint->sep == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean endpoint_init_ag(struct media_endpoint *endpoint, int *err)
+{
+ struct audio_device *dev;
+
+ endpoint->hs_watch = headset_add_state_cb(headset_state_changed,
+ endpoint);
+ dev = manager_find_device(NULL, &endpoint->adapter->src, BDADDR_ANY,
+ AUDIO_HEADSET_INTERFACE, TRUE);
+ if (dev)
+ set_configuration(endpoint, dev, NULL, 0,
+ headset_setconf_cb, dev, NULL);
+
+ return TRUE;
+}
+
+static gboolean endpoint_init_hs(struct media_endpoint *endpoint, int *err)
+{
+ struct audio_device *dev;
+
+ endpoint->ag_watch = gateway_add_state_cb(gateway_state_changed,
+ endpoint);
+ dev = manager_find_device(NULL, &endpoint->adapter->src, BDADDR_ANY,
+ AUDIO_GATEWAY_INTERFACE, TRUE);
+ if (dev)
+ set_configuration(endpoint, dev, NULL, 0,
+ gateway_setconf_cb, dev, NULL);
+
+ return TRUE;
+}
+
static struct media_endpoint *media_endpoint_create(struct media_adapter *adapter,
const char *sender,
const char *path,
@@ -669,6 +727,7 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
int *err)
{
struct media_endpoint *endpoint;
+ gboolean succeeded;

endpoint = g_new0(struct media_endpoint, 1);
endpoint->sender = g_strdup(sender);
@@ -684,46 +743,28 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte

endpoint->adapter = adapter;

- if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0) {
- endpoint->sep = a2dp_add_sep(&adapter->src,
- AVDTP_SEP_TYPE_SOURCE, codec,
- delay_reporting, &a2dp_endpoint,
- endpoint, a2dp_destroy_endpoint, err);
- if (endpoint->sep == NULL)
- goto failed;
- } else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0) {
- endpoint->sep = a2dp_add_sep(&adapter->src,
- AVDTP_SEP_TYPE_SINK, codec,
- delay_reporting, &a2dp_endpoint,
- endpoint, a2dp_destroy_endpoint, err);
- if (endpoint->sep == NULL)
- goto failed;
- } else if (strcasecmp(uuid, HFP_AG_UUID) == 0 ||
- strcasecmp(uuid, HSP_AG_UUID) == 0) {
- struct audio_device *dev;
-
- endpoint->hs_watch = headset_add_state_cb(headset_state_changed,
- endpoint);
- dev = manager_find_device(NULL, &adapter->src, BDADDR_ANY,
- AUDIO_HEADSET_INTERFACE, TRUE);
- if (dev)
- set_configuration(endpoint, dev, NULL, 0,
- headset_setconf_cb, dev, NULL);
- } else if (strcasecmp(uuid, HFP_HS_UUID) == 0 ||
- strcasecmp(uuid, HSP_HS_UUID) == 0) {
- struct audio_device *dev;
+ if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0)
+ succeeded = endpoint_init_a2dp_source(endpoint,
+ delay_reporting, err);
+ else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0)
+ succeeded = endpoint_init_a2dp_sink(endpoint,
+ delay_reporting, err);
+ else if (strcasecmp(uuid, HFP_AG_UUID) == 0 ||
+ strcasecmp(uuid, HSP_AG_UUID) == 0)
+ succeeded = endpoint_init_ag(endpoint, err);
+ else if (strcasecmp(uuid, HFP_HS_UUID) == 0 ||
+ strcasecmp(uuid, HSP_HS_UUID) == 0)
+ succeeded = endpoint_init_hs(endpoint, err);
+ else {
+ succeeded = FALSE;

- endpoint->ag_watch = gateway_add_state_cb(gateway_state_changed,
- endpoint);
- dev = manager_find_device(NULL, &adapter->src, BDADDR_ANY,
- AUDIO_GATEWAY_INTERFACE, TRUE);
- if (dev)
- set_configuration(endpoint, dev, NULL, 0,
- gateway_setconf_cb, dev, NULL);
- } else {
if (err)
*err = -EINVAL;
- goto failed;
+ }
+
+ if (!succeeded) {
+ g_free(endpoint);
+ return NULL;
}

endpoint->watch = g_dbus_add_disconnect_watch(adapter->conn, sender,
@@ -736,10 +777,6 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
if (err)
*err = 0;
return endpoint;
-
-failed:
- g_free(endpoint);
- return NULL;
}

static struct media_endpoint *media_adapter_find_endpoint(
--
1.7.7.6


2012-05-04 13:14:37

by Mikel Astiz

[permalink] [raw]
Subject: [PATCH BlueZ v3 3/6] media: Support multiple transports per endpoint

From: Mikel Astiz <[email protected]>

Several transports may exist for each endpoint, for example if several
HFGW are connected. This should be exposed to the endpoint as one
transport each.
---
audio/media.c | 98 +++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 65 insertions(+), 33 deletions(-)

diff --git a/audio/media.c b/audio/media.c
index c0fd0c3..fd5a369 100644
--- a/audio/media.c
+++ b/audio/media.c
@@ -86,8 +86,8 @@ struct media_endpoint {
guint ag_watch;
guint watch;
struct endpoint_request *request;
- struct media_transport *transport;
struct media_adapter *adapter;
+ GSList *transports;
};

struct media_player {
@@ -153,8 +153,8 @@ static void media_endpoint_destroy(struct media_endpoint *endpoint)
if (endpoint->request)
media_endpoint_cancel(endpoint);

- if (endpoint->transport)
- media_transport_destroy(endpoint->transport);
+ g_slist_free_full(endpoint->transports,
+ (GDestroyNotify) media_transport_destroy);

g_dbus_remove_watch(adapter->conn, endpoint->watch);
g_free(endpoint->capabilities);
@@ -200,18 +200,12 @@ static void headset_setconf_cb(struct media_endpoint *endpoint, void *ret,
headset_shutdown(dev);
}

-static void clear_configuration(struct media_endpoint *endpoint)
+static void clear_configuration(struct media_endpoint *endpoint,
+ struct media_transport *transport)
{
DBusConnection *conn;
DBusMessage *msg;
const char *path;
- struct media_transport *transport = endpoint->transport;
-
- if (endpoint->transport == NULL)
- return;
-
- if (endpoint->request)
- media_endpoint_cancel(endpoint);

conn = endpoint->adapter->conn;

@@ -223,15 +217,24 @@ static void clear_configuration(struct media_endpoint *endpoint)
goto done;
}

- path = media_transport_get_path(endpoint->transport);
+ path = media_transport_get_path(transport);
dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID);
g_dbus_send_message(conn, msg);
done:
- endpoint->transport = NULL;
+ endpoint->transports = g_slist_remove(endpoint->transports, transport);
media_transport_destroy(transport);
}

+static void clear_endpoint(struct media_endpoint *endpoint)
+{
+ if (endpoint->request)
+ media_endpoint_cancel(endpoint);
+
+ while (endpoint->transports != NULL)
+ clear_configuration(endpoint, endpoint->transports->data);
+}
+
static void endpoint_reply(DBusPendingCall *call, void *user_data)
{
struct media_endpoint *endpoint = user_data;
@@ -256,7 +259,7 @@ static void endpoint_reply(DBusPendingCall *call, void *user_data)
if (request->cb)
request->cb(endpoint, NULL, size,
request->user_data);
- clear_configuration(endpoint);
+ clear_endpoint(endpoint);
dbus_message_unref(reply);
dbus_error_free(&err);
return;
@@ -369,6 +372,31 @@ static gboolean select_configuration(struct media_endpoint *endpoint,
destroy);
}

+static gint transport_device_cmp(gconstpointer data, gconstpointer user_data)
+{
+ struct media_transport *transport = (struct media_transport *) data;
+ const struct audio_device *device = user_data;
+
+ if (device == media_transport_get_dev(transport))
+ return 0;
+
+ return -1;
+}
+
+static struct media_transport *find_device_transport(
+ struct media_endpoint *endpoint,
+ struct audio_device *device)
+{
+ GSList *match;
+
+ match = g_slist_find_custom(endpoint->transports, device,
+ transport_device_cmp);
+ if (match == NULL)
+ return NULL;
+
+ return match->data;
+}
+
static gboolean set_configuration(struct media_endpoint *endpoint,
struct audio_device *device,
uint8_t *configuration, size_t size,
@@ -380,15 +408,18 @@ static gboolean set_configuration(struct media_endpoint *endpoint,
DBusMessage *msg;
const char *path;
DBusMessageIter iter;
+ struct media_transport *transport;
+
+ transport = find_device_transport(endpoint, device);

- if (endpoint->transport != NULL || endpoint->request != NULL)
+ if (transport != NULL || endpoint->request != NULL)
return FALSE;

conn = endpoint->adapter->conn;

- endpoint->transport = media_transport_create(conn, endpoint, device,
+ transport = media_transport_create(conn, endpoint, device,
configuration, size);
- if (endpoint->transport == NULL)
+ if (transport == NULL)
return FALSE;

msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
@@ -396,15 +427,18 @@ static gboolean set_configuration(struct media_endpoint *endpoint,
"SetConfiguration");
if (msg == NULL) {
error("Couldn't allocate D-Bus message");
+ media_transport_destroy(transport);
return FALSE;
}

+ endpoint->transports = g_slist_append(endpoint->transports, transport);
+
dbus_message_iter_init_append(msg, &iter);

- path = media_transport_get_path(endpoint->transport);
+ path = media_transport_get_path(transport);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);

- transport_get_properties(endpoint->transport, &iter);
+ transport_get_properties(transport, &iter);

return media_endpoint_async_call(conn, msg, endpoint, cb, user_data,
destroy);
@@ -440,16 +474,17 @@ static void headset_state_changed(struct audio_device *dev,
void *user_data)
{
struct media_endpoint *endpoint = user_data;
+ struct media_transport *transport;

DBG("");

switch (new_state) {
case HEADSET_STATE_DISCONNECTED:
- if (endpoint->transport &&
- media_transport_get_dev(endpoint->transport) == dev) {
+ transport = find_device_transport(endpoint, dev);

+ if (transport != NULL) {
DBG("Clear endpoint %p", endpoint);
- clear_configuration(endpoint);
+ clear_configuration(endpoint, transport);
}
break;
case HEADSET_STATE_CONNECTING:
@@ -551,17 +586,17 @@ static void clear_config(struct a2dp_sep *sep, void *user_data)
{
struct media_endpoint *endpoint = user_data;

- clear_configuration(endpoint);
+ clear_endpoint(endpoint);
}

static void set_delay(struct a2dp_sep *sep, uint16_t delay, void *user_data)
{
struct media_endpoint *endpoint = user_data;

- if (endpoint->transport == NULL)
+ if (endpoint->transports == NULL)
return;

- media_transport_update_delay(endpoint->transport, delay);
+ media_transport_update_delay(endpoint->transports->data, delay);
}

static struct a2dp_endpoint a2dp_endpoint = {
@@ -577,10 +612,7 @@ static void a2dp_destroy_endpoint(void *user_data)
{
struct media_endpoint *endpoint = user_data;

- if (endpoint->transport) {
- media_transport_destroy(endpoint->transport);
- endpoint->transport = NULL;
- }
+ clear_endpoint(endpoint);

endpoint->sep = NULL;
release_endpoint(endpoint);
@@ -603,16 +635,16 @@ static void gateway_state_changed(struct audio_device *dev,
void *user_data)
{
struct media_endpoint *endpoint = user_data;
+ struct media_transport *transport;

DBG("");

switch (new_state) {
case GATEWAY_STATE_DISCONNECTED:
- if (endpoint->transport &&
- media_transport_get_dev(endpoint->transport) == dev) {
-
+ transport = find_device_transport(endpoint, dev);
+ if (transport != NULL) {
DBG("Clear endpoint %p", endpoint);
- clear_configuration(endpoint);
+ clear_configuration(endpoint, transport);
}
break;
case GATEWAY_STATE_CONNECTING:
--
1.7.7.6


2012-05-04 13:14:36

by Mikel Astiz

[permalink] [raw]
Subject: [PATCH BlueZ v3 2/6] audio: Add multiple device search to manager

From: Mikel Astiz <[email protected]>

This method is useful to search for more than one device fulfulling
certain criteria.
---
audio/manager.c | 25 ++++++++++++++++++++++---
audio/manager.h | 6 ++++++
2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/audio/manager.c b/audio/manager.c
index 20453e6..9c7d0d3 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -1300,12 +1300,13 @@ void audio_manager_exit(void)
btd_unregister_device_driver(&audio_driver);
}

-struct audio_device *manager_find_device(const char *path,
+GSList *manager_find_devices(const char *path,
const bdaddr_t *src,
const bdaddr_t *dst,
const char *interface,
gboolean connected)
{
+ GSList *result = NULL;
GSList *l;

for (l = devices; l != NULL; l = l->next) {
@@ -1343,10 +1344,28 @@ struct audio_device *manager_find_device(const char *path,
if (connected && !audio_device_is_active(dev, interface))
continue;

- return dev;
+ result = g_slist_append(result, dev);
}

- return NULL;
+ return result;
+}
+
+struct audio_device *manager_find_device(const char *path,
+ const bdaddr_t *src,
+ const bdaddr_t *dst,
+ const char *interface,
+ gboolean connected)
+{
+ struct audio_device *result;
+ GSList *l;
+
+ l = manager_find_devices(path, src, dst, interface, connected);
+ if (l == NULL)
+ return NULL;
+
+ result = l->data;
+ g_slist_free(l);
+ return result;
}

struct audio_device *manager_get_device(const bdaddr_t *src,
diff --git a/audio/manager.h b/audio/manager.h
index cfc646c..f1d3021 100644
--- a/audio/manager.h
+++ b/audio/manager.h
@@ -46,6 +46,12 @@ struct audio_device *manager_find_device(const char *path,
const char *interface,
gboolean connected);

+GSList *manager_find_devices(const char *path,
+ const bdaddr_t *src,
+ const bdaddr_t *dst,
+ const char *interface,
+ gboolean connected);
+
struct audio_device *manager_get_device(const bdaddr_t *src,
const bdaddr_t *dst,
gboolean create);
--
1.7.7.6


2012-05-04 13:14:35

by Mikel Astiz

[permalink] [raw]
Subject: [PATCH BlueZ v3 1/6] audio: Fix gateway state check

From: Mikel Astiz <[email protected]>

Gateway should be considered active also if connecting or playing.

This could for example lead to manager_find_device() not returning a
device that is connecting, and thus the corresponding endpoint would
never be created in the Media API.
---
audio/device.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/audio/device.c b/audio/device.c
index a9d35f9..ee1ade1 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -701,7 +701,7 @@ gboolean audio_device_is_active(struct audio_device *dev,
control_is_active(dev))
return TRUE;
else if (!strcmp(interface, AUDIO_GATEWAY_INTERFACE) && dev->gateway &&
- gateway_is_connected(dev))
+ gateway_is_active(dev))
return TRUE;

return FALSE;
--
1.7.7.6