2011-07-14 06:28:47

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 1/2] Fix possible invalid read/free on manager.c

From: Luiz Augusto von Dentz <[email protected]>

Invalid read of size 4
at 0x178A20: adapter_get_address (string3.h:52)
by 0x174C28: adapter_cmp (manager.c:324)
by 0x4EA95B0: g_slist_find_custom (in /lib64/libglib-2.0.so.0.2908.0)
by 0x174ED9: manager_find_adapter (manager.c:333)
by 0x16ABFA: sdp_record_remove (sdpd-database.c:270)
by 0x16A4D6: remove_record_from_server (sdpd-service.c:286)
by 0x12A947: avrcp_unregister (control.c:972)
by 0x1208CC: avrcp_server_remove (manager.c:1066)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x178985: adapter_remove (adapter.c:2326)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
Address 0x603ccd0 is 16 bytes inside a block of size 448 free'd
at 0x4A055FE: free (vg_replace_malloc.c:366)
by 0x4E938F2: g_free (in /lib64/libglib-2.0.so.0.2908.0)
by 0x11EB59: remove_interface (object.c:563)
by 0x11F380: g_dbus_unregister_interface (object.c:715)
by 0x1787EC: btd_adapter_unref (adapter.c:2496)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
by 0x174E96: manager_cleanup (manager.c:301)
by 0x11CCE8: main (main.c:305)

Invalid read of size 2
at 0x178A25: adapter_get_address (string3.h:52)
by 0x174C28: adapter_cmp (manager.c:324)
by 0x4EA95B0: g_slist_find_custom (in /lib64/libglib-2.0.so.0.2908.0)
by 0x174ED9: manager_find_adapter (manager.c:333)
by 0x16ABFA: sdp_record_remove (sdpd-database.c:270)
by 0x16A4D6: remove_record_from_server (sdpd-service.c:286)
by 0x12A947: avrcp_unregister (control.c:972)
by 0x1208CC: avrcp_server_remove (manager.c:1066)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x178985: adapter_remove (adapter.c:2326)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
Address 0x603ccd4 is 20 bytes inside a block of size 448 free'd
at 0x4A055FE: free (vg_replace_malloc.c:366)
by 0x4E938F2: g_free (in /lib64/libglib-2.0.so.0.2908.0)
by 0x11EB59: remove_interface (object.c:563)
by 0x11F380: g_dbus_unregister_interface (object.c:715)
by 0x1787EC: btd_adapter_unref (adapter.c:2496)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
by 0x174E96: manager_cleanup (manager.c:301)
by 0x11CCE8: main (main.c:305)
---
src/adapter.c | 2 --
src/manager.c | 16 +++++++++++++---
2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 0909a22..415a6b8 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2576,8 +2576,6 @@ void adapter_remove(struct btd_adapter *adapter)

/* Return adapter to down state if it was not up on init */
adapter_ops->restore_powered(adapter->dev_id);
-
- btd_adapter_unref(adapter);
}

uint16_t adapter_get_dev_id(struct btd_adapter *adapter)
diff --git a/src/manager.c b/src/manager.c
index a725588..15a1746 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -270,6 +270,14 @@ struct btd_adapter *manager_get_default_adapter(void)
return manager_find_adapter_by_id(default_adapter_id);
}

+static void remove_adapter(void *data)
+{
+ struct btd_adapter *adapter = data;
+
+ adapter_remove(adapter);
+ btd_adapter_unref(adapter);
+}
+
static void manager_remove_adapter(struct btd_adapter *adapter)
{
uint16_t dev_id = adapter_get_dev_id(adapter);
@@ -290,7 +298,7 @@ static void manager_remove_adapter(struct btd_adapter *adapter)
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID);

- adapter_remove(adapter);
+ remove_adapter(adapter);

if (adapters == NULL)
btd_start_exit_timer();
@@ -298,9 +306,11 @@ static void manager_remove_adapter(struct btd_adapter *adapter)

void manager_cleanup(DBusConnection *conn, const char *path)
{
- g_slist_free_full(adapters, (GDestroyNotify) adapter_remove);
+ while (adapters) {
+ remove_adapter(adapters->data);
+ adapters = g_slist_remove(adapters, adapters->data);
+ }

- adapters = NULL;
btd_start_exit_timer();

g_dbus_unregister_interface(conn, "/", MANAGER_INTERFACE);
--
1.7.6



2011-07-14 17:45:27

by Dmitriy Paliy

[permalink] [raw]
Subject: Re: [PATCH BlueZ 1/2] Fix possible invalid read/free on manager.c

Hi Luiz,

On Thu, Jul 14, 2011 at 9:28 AM, Luiz Augusto von Dentz
<[email protected]> wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> ?Invalid read of size 4
> ? ?at 0x178A20: adapter_get_address (string3.h:52)
> ? ?by 0x174C28: adapter_cmp (manager.c:324)
> ? ?by 0x4EA95B0: g_slist_find_custom (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x174ED9: manager_find_adapter (manager.c:333)
> ? ?by 0x16ABFA: sdp_record_remove (sdpd-database.c:270)
> ? ?by 0x16A4D6: remove_record_from_server (sdpd-service.c:286)
> ? ?by 0x12A947: avrcp_unregister (control.c:972)
> ? ?by 0x1208CC: avrcp_server_remove (manager.c:1066)
> ? ?by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x178985: adapter_remove (adapter.c:2326)
> ? ?by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
> ?Address 0x603ccd0 is 16 bytes inside a block of size 448 free'd
> ? ?at 0x4A055FE: free (vg_replace_malloc.c:366)
> ? ?by 0x4E938F2: g_free (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x11EB59: remove_interface (object.c:563)
> ? ?by 0x11F380: g_dbus_unregister_interface (object.c:715)
> ? ?by 0x1787EC: btd_adapter_unref (adapter.c:2496)
> ? ?by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x174E96: manager_cleanup (manager.c:301)
> ? ?by 0x11CCE8: main (main.c:305)
>
> ?Invalid read of size 2
> ? ?at 0x178A25: adapter_get_address (string3.h:52)
> ? ?by 0x174C28: adapter_cmp (manager.c:324)
> ? ?by 0x4EA95B0: g_slist_find_custom (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x174ED9: manager_find_adapter (manager.c:333)
> ? ?by 0x16ABFA: sdp_record_remove (sdpd-database.c:270)
> ? ?by 0x16A4D6: remove_record_from_server (sdpd-service.c:286)
> ? ?by 0x12A947: avrcp_unregister (control.c:972)
> ? ?by 0x1208CC: avrcp_server_remove (manager.c:1066)
> ? ?by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x178985: adapter_remove (adapter.c:2326)
> ? ?by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
> ?Address 0x603ccd4 is 20 bytes inside a block of size 448 free'd
> ? ?at 0x4A055FE: free (vg_replace_malloc.c:366)
> ? ?by 0x4E938F2: g_free (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x11EB59: remove_interface (object.c:563)
> ? ?by 0x11F380: g_dbus_unregister_interface (object.c:715)
> ? ?by 0x1787EC: btd_adapter_unref (adapter.c:2496)
> ? ?by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
> ? ?by 0x174E96: manager_cleanup (manager.c:301)
> ? ?by 0x11CCE8: main (main.c:305)
> ---
> ?src/adapter.c | ? ?2 --
> ?src/manager.c | ? 16 +++++++++++++---
> ?2 files changed, 13 insertions(+), 5 deletions(-)

Wouldn't it be better to shorten commit messages like this one? It is
not very convenient to have full screen message that doesn't bring
much addition explanation to its title.

Thanks,
Dmitriy

2011-07-14 17:18:11

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH BlueZ 1/2] Fix possible invalid read/free on manager.c

Hi Luiz,

On Thu, Jul 14, 2011, Luiz Augusto von Dentz wrote:
> +static void remove_adapter(void *data)
> +{
> + struct btd_adapter *adapter = data;
> +
> + adapter_remove(adapter);
> + btd_adapter_unref(adapter);
> +}

The only places that call this function don't anymore use generic
pointers so it can actually have struct btd_adapter instead of void.
However, since this function is getting so simple I think it'd be more
transparent if you just did these calls in the two places where it's
necessary and don't have this extra helper function at all.

Johan

2011-07-14 06:28:48

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 2/2] Fix possible invalid read/free on media.c

From: Luiz Augusto von Dentz <[email protected]>

This also fix the circular dependency of media.c and a2dp.c

Invalid read of size 8
at 0x4EA8CC2: g_slice_free_chain_with_offset (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AF33: path_free (media.c:417)
by 0x11EB39: remove_interface (object.c:563)
by 0x11F360: g_dbus_unregister_interface (object.c:715)
by 0x120C49: media_server_remove (manager.c:1098)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x178915: adapter_remove (adapter.c:2326)
by 0x17535F: btd_manager_unregister_adapter (manager.c:293)
by 0x154081: device_event (hciops.c:2643)
by 0x1543C1: io_stack_event (hciops.c:2763)
by 0x4E8C88C: g_main_context_dispatch (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4E8D087: ??? (in /lib64/libglib-2.0.so.0.2908.0)
Address 0x63f6638 is 8 bytes inside a block of size 16 free'd
at 0x4A055FE: free (vg_replace_malloc.c:366)
by 0x4E938F2: g_free (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA854E: g_slice_free1 (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA930C: g_slist_remove (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AE53: media_endpoint_remove (media.c:118)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AF33: path_free (media.c:417)
by 0x11EB39: remove_interface (object.c:563)
by 0x11F360: g_dbus_unregister_interface (object.c:715)
by 0x120C49: media_server_remove (manager.c:1098)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)

Invalid write of size 4
at 0x4A08D20: memset (mc_replace_strmem.c:751)
by 0x4EA8CAB: g_slice_free_chain_with_offset (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AF33: path_free (media.c:417)
by 0x11EB39: remove_interface (object.c:563)
by 0x11F360: g_dbus_unregister_interface (object.c:715)
by 0x120C49: media_server_remove (manager.c:1098)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x178915: adapter_remove (adapter.c:2326)
by 0x17535F: btd_manager_unregister_adapter (manager.c:293)
by 0x154081: device_event (hciops.c:2643)
by 0x1543C1: io_stack_event (hciops.c:2763)
by 0x4E8C88C: g_main_context_dispatch (in /lib64/libglib-2.0.so.0.2908.0)
Address 0x63f6630 is 0 bytes inside a block of size 16 free'd
at 0x4A055FE: free (vg_replace_malloc.c:366)
by 0x4E938F2: g_free (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA854E: g_slice_free1 (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA930C: g_slist_remove (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AE53: media_endpoint_remove (media.c:118)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AF33: path_free (media.c:417)
by 0x11EB39: remove_interface (object.c:563)
by 0x11F360: g_dbus_unregister_interface (object.c:715)
by 0x120C49: media_server_remove (manager.c:1098)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)

Invalid write of size 4
at 0x4A08D2B: memset (mc_replace_strmem.c:751)
by 0x4EA8CAB: g_slice_free_chain_with_offset (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AF33: path_free (media.c:417)
by 0x11EB39: remove_interface (object.c:563)
by 0x11F360: g_dbus_unregister_interface (object.c:715)
by 0x120C49: media_server_remove (manager.c:1098)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x178915: adapter_remove (adapter.c:2326)
by 0x17535F: btd_manager_unregister_adapter (manager.c:293)
by 0x154081: device_event (hciops.c:2643)
by 0x1543C1: io_stack_event (hciops.c:2763)
by 0x4E8C88C: g_main_context_dispatch (in /lib64/libglib-2.0.so.0.2908.0)
Address 0x63f6638 is 8 bytes inside a block of size 16 free'd
at 0x4A055FE: free (vg_replace_malloc.c:366)
by 0x4E938F2: g_free (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA854E: g_slice_free1 (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA930C: g_slist_remove (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AE53: media_endpoint_remove (media.c:118)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AF33: path_free (media.c:417)
by 0x11EB39: remove_interface (object.c:563)
by 0x11F360: g_dbus_unregister_interface (object.c:715)
by 0x120C49: media_server_remove (manager.c:1098)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)

Invalid free() / delete / delete[]
at 0x4A055FE: free (vg_replace_malloc.c:366)
by 0x4E938F2: g_free (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA8CB3: g_slice_free_chain_with_offset (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AF33: path_free (media.c:417)
by 0x11EB39: remove_interface (object.c:563)
by 0x11F360: g_dbus_unregister_interface (object.c:715)
by 0x120C49: media_server_remove (manager.c:1098)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x178915: adapter_remove (adapter.c:2326)
by 0x17535F: btd_manager_unregister_adapter (manager.c:293)
by 0x154081: device_event (hciops.c:2643)
by 0x1543C1: io_stack_event (hciops.c:2763)
Address 0x63f6630 is 0 bytes inside a block of size 16 free'd
at 0x4A055FE: free (vg_replace_malloc.c:366)
by 0x4E938F2: g_free (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA854E: g_slice_free1 (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA930C: g_slist_remove (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AE53: media_endpoint_remove (media.c:118)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
by 0x4EA984A: g_slist_free_full (in /lib64/libglib-2.0.so.0.2908.0)
by 0x13AF33: path_free (media.c:417)
by 0x11EB39: remove_interface (object.c:563)
by 0x11F360: g_dbus_unregister_interface (object.c:715)
by 0x120C49: media_server_remove (manager.c:1098)
by 0x4EA9826: g_slist_foreach (in /lib64/libglib-2.0.so.0.2908.0)
---
audio/a2dp.c | 78 ++++---
audio/a2dp.h | 29 +++-
audio/media.c | 676 +++++++++++++++++++++++++++++++----------------------
audio/media.h | 17 --
audio/transport.c | 3 +-
5 files changed, 464 insertions(+), 339 deletions(-)

diff --git a/audio/a2dp.c b/audio/a2dp.c
index 72a0df5..6e14913 100644
--- a/audio/a2dp.c
+++ b/audio/a2dp.c
@@ -44,8 +44,6 @@
#include "sink.h"
#include "source.h"
#include "unix.h"
-#include "media.h"
-#include "transport.h"
#include "a2dp.h"
#include "sdpd.h"

@@ -64,7 +62,7 @@

struct a2dp_sep {
struct a2dp_server *server;
- struct media_endpoint *endpoint;
+ struct a2dp_endpoint *endpoint;
uint8_t type;
uint8_t codec;
struct avdtp_local_sep *lsep;
@@ -75,6 +73,8 @@ struct a2dp_sep {
gboolean locked;
gboolean suspending;
gboolean starting;
+ void *user_data;
+ GDestroyNotify destroy;
};

struct a2dp_setup_cb {
@@ -372,8 +372,8 @@ static void stream_state_changed(struct avdtp_stream *stream,

sep->stream = NULL;

- if (sep->endpoint)
- media_endpoint_clear_configuration(sep->endpoint);
+ if (sep->endpoint && sep->endpoint->clear_configuration)
+ sep->endpoint->clear_configuration(sep, sep->user_data);
}

static gboolean auto_config(gpointer data)
@@ -638,7 +638,7 @@ static gboolean mpeg_getcap_ind(struct avdtp *session,
return TRUE;
}

-static void endpoint_setconf_cb(struct media_endpoint *endpoint, void *ret,
+static void endpoint_setconf_cb(struct a2dp_sep *sep, void *ret,
int size, void *user_data)
{
struct a2dp_setup *setup = user_data;
@@ -701,11 +701,12 @@ static gboolean endpoint_setconf_ind(struct avdtp *session,
goto done;
}

- ret = media_endpoint_set_configuration(a2dp_sep->endpoint,
+ ret = a2dp_sep->endpoint->set_configuration(a2dp_sep,
setup->dev, codec->data,
cap->length - sizeof(*codec),
- endpoint_setconf_cb, setup);
- if (ret)
+ endpoint_setconf_cb, setup,
+ a2dp_sep->user_data);
+ if (ret == 0)
return TRUE;

avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
@@ -741,8 +742,8 @@ static gboolean endpoint_getcap_ind(struct avdtp *session,

*caps = g_slist_append(*caps, media_transport);

- length = media_endpoint_get_capabilities(a2dp_sep->endpoint,
- &capabilities);
+ length = a2dp_sep->endpoint->get_capabilities(a2dp_sep, &capabilities,
+ a2dp_sep->user_data);

codec_caps = g_malloc0(sizeof(*codec_caps) + length);
codec_caps->media_type = AVDTP_MEDIA_TYPE_AUDIO;
@@ -765,7 +766,7 @@ static gboolean endpoint_getcap_ind(struct avdtp *session,
return TRUE;
}

-static void endpoint_open_cb(struct media_endpoint *endpoint, void *ret,
+static void endpoint_open_cb(struct a2dp_sep *sep, void *ret,
int size, void *user_data)
{
struct a2dp_setup *setup = user_data;
@@ -828,15 +829,16 @@ static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
if (a2dp_sep->endpoint) {
struct avdtp_service_capability *service;
struct avdtp_media_codec_capability *codec;
+ int err;

service = avdtp_stream_get_codec(stream);
codec = (struct avdtp_media_codec_capability *) service->data;

- if (media_endpoint_set_configuration(a2dp_sep->endpoint, dev,
- codec->data, service->length -
- sizeof(*codec),
- endpoint_open_cb, setup) ==
- TRUE)
+ err = a2dp_sep->endpoint->set_configuration(a2dp_sep, dev,
+ codec->data, service->length -
+ sizeof(*codec), endpoint_open_cb,
+ setup, a2dp_sep->user_data);
+ if (err == 0)
return;

setup->stream = NULL;
@@ -1254,18 +1256,17 @@ static gboolean endpoint_delayreport_ind(struct avdtp *session,
uint8_t *err, void *user_data)
{
struct a2dp_sep *a2dp_sep = user_data;
- struct media_transport *transport;

if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
DBG("Sink %p: DelayReport_Ind", sep);
else
DBG("Source %p: DelayReport_Ind", sep);

- transport = media_endpoint_get_transport(a2dp_sep->endpoint);
- if (transport == NULL)
+ if (a2dp_sep->endpoint == NULL ||
+ a2dp_sep->endpoint->set_delay == NULL)
return FALSE;

- media_transport_update_delay(transport, delay);
+ a2dp_sep->endpoint->set_delay(a2dp_sep, delay, a2dp_sep->user_data);

return TRUE;
}
@@ -1559,23 +1560,25 @@ proceed:
if (source) {
for (i = 0; i < sbc_srcs; i++)
a2dp_add_sep(src, AVDTP_SEP_TYPE_SOURCE,
- A2DP_CODEC_SBC, delay_reporting, NULL, NULL);
+ A2DP_CODEC_SBC, delay_reporting,
+ NULL, NULL, NULL, NULL);

for (i = 0; i < mpeg12_srcs; i++)
a2dp_add_sep(src, AVDTP_SEP_TYPE_SOURCE,
A2DP_CODEC_MPEG12, delay_reporting,
- NULL, NULL);
+ NULL, NULL, NULL, NULL);
}
server->sink_enabled = sink;
if (sink) {
for (i = 0; i < sbc_sinks; i++)
a2dp_add_sep(src, AVDTP_SEP_TYPE_SINK,
- A2DP_CODEC_SBC, delay_reporting, NULL, NULL);
+ A2DP_CODEC_SBC, delay_reporting,
+ NULL, NULL, NULL, NULL);

for (i = 0; i < mpeg12_sinks; i++)
a2dp_add_sep(src, AVDTP_SEP_TYPE_SINK,
A2DP_CODEC_MPEG12, delay_reporting,
- NULL, NULL);
+ NULL, NULL, NULL, NULL);
}

return 0;
@@ -1583,8 +1586,8 @@ proceed:

static void a2dp_unregister_sep(struct a2dp_sep *sep)
{
- if (sep->endpoint) {
- media_endpoint_release(sep->endpoint);
+ if (sep->destroy) {
+ sep->destroy(sep->user_data);
sep->endpoint = NULL;
}

@@ -1625,7 +1628,9 @@ void a2dp_unregister(const bdaddr_t *src)

struct a2dp_sep *a2dp_add_sep(const bdaddr_t *src, uint8_t type,
uint8_t codec, gboolean delay_reporting,
- struct media_endpoint *endpoint, int *err)
+ struct a2dp_endpoint *endpoint,
+ void *user_data, GDestroyNotify destroy,
+ int *err)
{
struct a2dp_server *server;
struct a2dp_sep *sep;
@@ -1678,6 +1683,8 @@ proceed:
sep->codec = codec;
sep->type = type;
sep->delay_reporting = delay_reporting;
+ sep->user_data = user_data;
+ sep->destroy = destroy;

if (type == AVDTP_SEP_TYPE_SOURCE) {
l = &server->sources;
@@ -1927,8 +1934,8 @@ static gboolean select_capabilities(struct avdtp *session,
return TRUE;
}

-static void select_cb(struct media_endpoint *endpoint, void *ret, int size,
- void *user_data)
+static void select_cb(struct a2dp_sep *sep, void *ret, int size,
+ void *user_data)
{
struct a2dp_setup *setup = user_data;
struct avdtp_service_capability *media_transport, *media_codec;
@@ -1981,7 +1988,7 @@ static struct a2dp_sep *a2dp_find_sep(struct avdtp *session, GSList *list,
if (sep->endpoint == NULL)
continue;

- name = media_endpoint_get_sender(sep->endpoint);
+ name = sep->endpoint->get_name(sep, sep->user_data);
if (g_strcmp0(sender, name) != 0)
continue;
}
@@ -2028,6 +2035,7 @@ unsigned int a2dp_select_capabilities(struct avdtp *session,
struct a2dp_sep *sep;
struct avdtp_service_capability *service;
struct avdtp_media_codec_capability *codec;
+ int err;

sep = a2dp_select_sep(session, type, sender);
if (!sep) {
@@ -2068,10 +2076,10 @@ unsigned int a2dp_select_capabilities(struct avdtp *session,
service = avdtp_get_codec(setup->rsep);
codec = (struct avdtp_media_codec_capability *) service->data;

- if (media_endpoint_select_configuration(sep->endpoint, codec->data,
- service->length - sizeof(*codec),
- select_cb, setup) ==
- TRUE)
+ err = sep->endpoint->select_configuration(sep, codec->data,
+ service->length - sizeof(*codec),
+ select_cb, setup, sep->user_data);
+ if (err == 0)
return cb_data->id;

fail:
diff --git a/audio/a2dp.h b/audio/a2dp.h
index 5c4232d..b50bc33 100644
--- a/audio/a2dp.h
+++ b/audio/a2dp.h
@@ -121,6 +121,31 @@ struct mpeg_codec_cap {

struct a2dp_sep;

+typedef void (*a2dp_endpoint_cb_t) (struct a2dp_sep *sep, void *ret,
+ int size, void *user_data);
+
+struct a2dp_endpoint {
+ const char *(*get_name) (struct a2dp_sep *sep, void *user_data);
+ size_t (*get_capabilities) (struct a2dp_sep *sep,
+ uint8_t **capabilities,
+ void *user_data);
+ int (*select_configuration) (struct a2dp_sep *sep,
+ uint8_t *capabilities,
+ size_t length,
+ a2dp_endpoint_cb_t cb,
+ void *cb_data,
+ void *user_data);
+ int (*set_configuration) (struct a2dp_sep *sep,
+ struct audio_device *dev,
+ uint8_t *configuration,
+ size_t length,
+ a2dp_endpoint_cb_t cb,
+ void *cb_data,
+ void *user_data);
+ void (*clear_configuration) (struct a2dp_sep *sep, void *user_data);
+ void (*set_delay) (struct a2dp_sep *sep, uint16_t delay,
+ void *user_data);
+};

typedef void (*a2dp_select_cb_t) (struct avdtp *session,
struct a2dp_sep *sep, GSList *caps,
@@ -138,7 +163,9 @@ void a2dp_unregister(const bdaddr_t *src);

struct a2dp_sep *a2dp_add_sep(const bdaddr_t *src, uint8_t type,
uint8_t codec, gboolean delay_reporting,
- struct media_endpoint *endpoint, int *err);
+ struct a2dp_endpoint *endpoint,
+ void *user_data, GDestroyNotify destroy,
+ int *err);
void a2dp_remove_sep(struct a2dp_sep *sep);

struct a2dp_sep *a2dp_get(struct avdtp *session, struct avdtp_remote_sep *sep);
diff --git a/audio/media.c b/audio/media.c
index 57bf7c9..bfd80d9 100644
--- a/audio/media.c
+++ b/audio/media.c
@@ -105,20 +105,11 @@ static void media_endpoint_cancel(struct media_endpoint *endpoint)
endpoint->request = NULL;
}

-static void media_endpoint_remove(struct media_endpoint *endpoint)
+static void media_endpoint_destroy(struct media_endpoint *endpoint)
{
struct media_adapter *adapter = endpoint->adapter;

- if (g_slist_find(adapter->endpoints, endpoint) == NULL)
- return;
-
- info("Endpoint unregistered: sender=%s path=%s", endpoint->sender,
- endpoint->path);
-
- adapter->endpoints = g_slist_remove(adapter->endpoints, endpoint);
-
- if (endpoint->sep)
- a2dp_remove_sep(endpoint->sep);
+ DBG("sender=%s path=%s", endpoint->sender, endpoint->path);

if (endpoint->hs_watch)
headset_remove_state_cb(endpoint->hs_watch);
@@ -137,6 +128,23 @@ static void media_endpoint_remove(struct media_endpoint *endpoint)
g_free(endpoint);
}

+static void media_endpoint_remove(struct media_endpoint *endpoint)
+{
+ struct media_adapter *adapter = endpoint->adapter;
+
+ if (endpoint->sep) {
+ a2dp_remove_sep(endpoint->sep);
+ return;
+ }
+
+ info("Endpoint unregistered: sender=%s path=%s", endpoint->sender,
+ endpoint->path);
+
+ adapter->endpoints = g_slist_remove(adapter->endpoints, endpoint);
+
+ media_endpoint_destroy(endpoint);
+}
+
static void media_endpoint_exit(DBusConnection *connection, void *user_data)
{
struct media_endpoint *endpoint = user_data;
@@ -156,6 +164,233 @@ static void headset_setconf_cb(struct media_endpoint *endpoint, void *ret,
headset_set_state(dev, HEADSET_STATE_DISCONNECTED);
}

+static void clear_configuration(struct media_endpoint *endpoint)
+{
+ 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;
+
+ msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
+ MEDIA_ENDPOINT_INTERFACE,
+ "ClearConfiguration");
+ if (msg == NULL) {
+ error("Couldn't allocate D-Bus message");
+ goto done;
+ }
+
+ path = media_transport_get_path(endpoint->transport);
+ dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID);
+ g_dbus_send_message(conn, msg);
+done:
+ endpoint->transport = NULL;
+ media_transport_destroy(transport);
+}
+
+static void endpoint_reply(DBusPendingCall *call, void *user_data)
+{
+ struct media_endpoint *endpoint = user_data;
+ struct endpoint_request *request = endpoint->request;
+ DBusMessage *reply;
+ DBusError err;
+ gboolean value;
+ void *ret = NULL;
+ int size = -1;
+
+ /* steal_reply will always return non-NULL since the callback
+ * is only called after a reply has been received */
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&err);
+ if (dbus_set_error_from_message(&err, reply)) {
+ error("Endpoint replied with an error: %s",
+ err.name);
+
+ /* Clear endpoint configuration in case of NO_REPLY error */
+ if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
+ if (request->cb)
+ request->cb(endpoint, NULL, size,
+ request->user_data);
+ clear_configuration(endpoint);
+ dbus_message_unref(reply);
+ dbus_error_free(&err);
+ return;
+ }
+
+ dbus_error_free(&err);
+ goto done;
+ }
+
+ dbus_error_init(&err);
+ if (dbus_message_is_method_call(request->msg, MEDIA_ENDPOINT_INTERFACE,
+ "SelectConfiguration")) {
+ DBusMessageIter args, array;
+ uint8_t *configuration;
+
+ dbus_message_iter_init(reply, &args);
+
+ dbus_message_iter_recurse(&args, &array);
+
+ dbus_message_iter_get_fixed_array(&array, &configuration, &size);
+
+ ret = configuration;
+ goto done;
+ } else if (!dbus_message_get_args(reply, &err, DBUS_TYPE_INVALID)) {
+ error("Wrong reply signature: %s", err.message);
+ dbus_error_free(&err);
+ goto done;
+ }
+
+ size = 1;
+ value = TRUE;
+ ret = &value;
+
+done:
+ dbus_message_unref(reply);
+
+ if (request->cb)
+ request->cb(endpoint, ret, size, request->user_data);
+
+ endpoint_request_free(request);
+ endpoint->request = NULL;
+}
+
+static gboolean media_endpoint_async_call(DBusConnection *conn,
+ DBusMessage *msg,
+ struct media_endpoint *endpoint,
+ media_endpoint_cb_t cb,
+ void *user_data)
+{
+ 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) */
+ if (dbus_connection_send_with_reply(conn, msg, &request->call,
+ REQUEST_TIMEOUT) == FALSE) {
+ error("D-Bus send failed");
+ g_free(request);
+ return FALSE;
+ }
+
+ dbus_pending_call_set_notify(request->call, endpoint_reply, endpoint, NULL);
+
+ request->msg = msg;
+ request->cb = cb;
+ request->user_data = user_data;
+ endpoint->request = request;
+
+ DBG("Calling %s: name = %s path = %s", dbus_message_get_member(msg),
+ dbus_message_get_destination(msg),
+ dbus_message_get_path(msg));
+
+ return TRUE;
+}
+
+static gboolean select_configuration(struct media_endpoint *endpoint,
+ uint8_t *capabilities,
+ size_t length,
+ media_endpoint_cb_t cb,
+ void *user_data)
+{
+ DBusConnection *conn;
+ DBusMessage *msg;
+
+ if (endpoint->request != NULL)
+ return FALSE;
+
+ conn = endpoint->adapter->conn;
+
+ msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
+ MEDIA_ENDPOINT_INTERFACE,
+ "SelectConfiguration");
+ if (msg == NULL) {
+ error("Couldn't allocate D-Bus message");
+ return FALSE;
+ }
+
+ dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &capabilities, length,
+ DBUS_TYPE_INVALID);
+
+ return media_endpoint_async_call(conn, msg, endpoint, cb, user_data);
+}
+
+static gboolean set_configuration(struct media_endpoint *endpoint,
+ struct audio_device *device,
+ uint8_t *configuration, size_t size,
+ media_endpoint_cb_t cb,
+ void *user_data)
+{
+ DBusConnection *conn;
+ DBusMessage *msg;
+ const char *path;
+ DBusMessageIter iter;
+
+ if (endpoint->transport != NULL || endpoint->request != NULL)
+ return FALSE;
+
+ conn = endpoint->adapter->conn;
+
+ endpoint->transport = media_transport_create(conn, endpoint, device,
+ configuration, size);
+ if (endpoint->transport == NULL)
+ return FALSE;
+
+ msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
+ MEDIA_ENDPOINT_INTERFACE,
+ "SetConfiguration");
+ if (msg == NULL) {
+ error("Couldn't allocate D-Bus message");
+ return FALSE;
+ }
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ path = media_transport_get_path(endpoint->transport);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+ transport_get_properties(endpoint->transport, &iter);
+
+ return media_endpoint_async_call(conn, msg, endpoint, cb, user_data);
+}
+
+static void release_endpoint(struct media_endpoint *endpoint)
+{
+ DBusMessage *msg;
+
+ DBG("sender=%s path=%s", endpoint->sender, endpoint->path);
+
+ /* already exit */
+ if (endpoint->watch == 0)
+ goto done;
+
+ msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
+ MEDIA_ENDPOINT_INTERFACE,
+ "Release");
+ if (msg == NULL) {
+ error("Couldn't allocate D-Bus message");
+ return;
+ }
+
+ g_dbus_send_message(endpoint->adapter->conn, msg);
+
+done:
+ media_endpoint_remove(endpoint);
+}
+
static void headset_state_changed(struct audio_device *dev,
headset_state_t old_state,
headset_state_t new_state,
@@ -163,28 +398,144 @@ static void headset_state_changed(struct audio_device *dev,
{
struct media_endpoint *endpoint = user_data;

- DBG("");
-
- switch (new_state) {
- case HEADSET_STATE_DISCONNECTED:
- if (endpoint->transport &&
- media_transport_get_dev(endpoint->transport) == dev) {
-
- DBG("Clear endpoint %p", endpoint);
- media_endpoint_clear_configuration(endpoint);
- }
- break;
- case HEADSET_STATE_CONNECTING:
- media_endpoint_set_configuration(endpoint, dev, NULL, 0,
- headset_setconf_cb, dev);
- break;
- case HEADSET_STATE_CONNECTED:
- break;
- case HEADSET_STATE_PLAY_IN_PROGRESS:
- break;
- case HEADSET_STATE_PLAYING:
- break;
+ DBG("");
+
+ switch (new_state) {
+ case HEADSET_STATE_DISCONNECTED:
+ if (endpoint->transport &&
+ media_transport_get_dev(endpoint->transport) == dev) {
+
+ DBG("Clear endpoint %p", endpoint);
+ clear_configuration(endpoint);
+ }
+ break;
+ case HEADSET_STATE_CONNECTING:
+ set_configuration(endpoint, dev, NULL, 0, headset_setconf_cb,
+ dev);
+ break;
+ case HEADSET_STATE_CONNECTED:
+ break;
+ case HEADSET_STATE_PLAY_IN_PROGRESS:
+ break;
+ case HEADSET_STATE_PLAYING:
+ break;
+ }
+}
+
+static const char *a2dp_get_name(struct a2dp_sep *sep, void *user_data)
+{
+ struct media_endpoint *endpoint = user_data;
+
+ return endpoint->sender;
+}
+
+static size_t a2dp_get_capabilities(struct a2dp_sep *sep,
+ uint8_t **capabilities,
+ void *user_data)
+{
+ struct media_endpoint *endpoint = user_data;
+
+ *capabilities = endpoint->capabilities;
+ return endpoint->size;
+}
+
+struct a2dp_data {
+ a2dp_endpoint_cb_t cb;
+ void *user_data;
+};
+
+static void endpoint_cb(struct media_endpoint *endpoint,
+ void *ret, int size, void *user_data)
+{
+ struct a2dp_data *data = user_data;
+
+ data->cb(endpoint->sep, ret, size, data->user_data);
+ g_free(data);
+}
+
+static int a2dp_select_configuration(struct a2dp_sep *sep,
+ uint8_t *capabilities,
+ size_t length,
+ a2dp_endpoint_cb_t cb,
+ void *cb_data,
+ void *user_data)
+{
+ struct media_endpoint *endpoint = user_data;
+ struct a2dp_data *data;
+
+ data = g_new0(struct a2dp_data, 1);
+ data->cb = cb;
+ data->user_data = cb_data;
+
+ if (select_configuration(endpoint, capabilities, length,
+ endpoint_cb, data) == TRUE)
+ return 0;
+
+ g_free(data);
+ return -ENOMEM;
+}
+
+static int a2dp_set_configuration(struct a2dp_sep *sep,
+ struct audio_device *dev,
+ uint8_t *configuration,
+ size_t length,
+ a2dp_endpoint_cb_t cb,
+ void *cb_data,
+ void *user_data)
+{
+ struct media_endpoint *endpoint = user_data;
+ struct a2dp_data *data;
+
+ data = g_new0(struct a2dp_data, 1);
+ data->cb = cb;
+ data->user_data = cb_data;
+
+ if (set_configuration(endpoint, dev, configuration, length,
+ endpoint_cb, data) == TRUE)
+ return 0;
+
+ g_free(data);
+ return -ENOMEM;
+}
+
+static void a2dp_clear_configuration(struct a2dp_sep *sep, void *user_data)
+{
+ struct media_endpoint *endpoint = user_data;
+
+ clear_configuration(endpoint);
+}
+
+static void a2dp_set_delay(struct a2dp_sep *sep, uint16_t delay,
+ void *user_data)
+{
+ struct media_endpoint *endpoint = user_data;
+
+ if (endpoint->transport == NULL)
+ return;
+
+ media_transport_update_delay(endpoint->transport, delay);
+}
+
+static struct a2dp_endpoint a2dp_endpoint = {
+ .get_name = a2dp_get_name,
+ .get_capabilities = a2dp_get_capabilities,
+ .select_configuration = a2dp_select_configuration,
+ .set_configuration = a2dp_set_configuration,
+ .clear_configuration = a2dp_clear_configuration,
+ .set_delay = a2dp_set_delay
+};
+
+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;
}
+
+ endpoint->sep = NULL;
+ release_endpoint(endpoint);
}

static struct media_endpoint *media_endpoint_create(struct media_adapter *adapter,
@@ -216,13 +567,15 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0) {
endpoint->sep = a2dp_add_sep(&adapter->src,
AVDTP_SEP_TYPE_SOURCE, codec,
- delay_reporting, endpoint, err);
+ 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, endpoint, err);
+ AVDTP_SEP_TYPE_SOURCE, codec,
+ delay_reporting, &a2dp_endpoint,
+ endpoint, a2dp_destroy_endpoint, err);
if (endpoint->sep == NULL)
goto failed;
} else if (strcasecmp(uuid, HFP_AG_UUID) == 0 ||
@@ -234,9 +587,8 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
dev = manager_find_device(NULL, &adapter->src, BDADDR_ANY,
AUDIO_HEADSET_INTERFACE, TRUE);
if (dev)
- media_endpoint_set_configuration(endpoint, dev, NULL,
- 0, headset_setconf_cb,
- dev);
+ set_configuration(endpoint, dev, NULL, 0,
+ headset_setconf_cb, dev);
} else {
if (err)
*err = -EINVAL;
@@ -285,11 +637,6 @@ static struct media_endpoint *media_adapter_find_endpoint(
return NULL;
}

-const char *media_endpoint_get_sender(struct media_endpoint *endpoint)
-{
- return endpoint->sender;
-}
-
static int parse_properties(DBusMessageIter *props, const char **uuid,
gboolean *delay_reporting, uint8_t *codec,
uint8_t **capabilities, int *size)
@@ -414,8 +761,8 @@ static void path_free(void *data)
{
struct media_adapter *adapter = data;

- g_slist_free_full(adapter->endpoints,
- (GDestroyNotify) media_endpoint_release);
+ while (adapter->endpoints)
+ release_endpoint(adapter->endpoints->data);

dbus_connection_unref(adapter->conn);

@@ -465,239 +812,6 @@ void media_unregister(const char *path)
}
}

-size_t media_endpoint_get_capabilities(struct media_endpoint *endpoint,
- uint8_t **capabilities)
-{
- *capabilities = endpoint->capabilities;
- return endpoint->size;
-}
-
-static void endpoint_reply(DBusPendingCall *call, void *user_data)
-{
- struct media_endpoint *endpoint = user_data;
- struct endpoint_request *request = endpoint->request;
- DBusMessage *reply;
- DBusError err;
- gboolean value;
- void *ret = NULL;
- int size = -1;
-
- /* steal_reply will always return non-NULL since the callback
- * is only called after a reply has been received */
- reply = dbus_pending_call_steal_reply(call);
-
- dbus_error_init(&err);
- if (dbus_set_error_from_message(&err, reply)) {
- error("Endpoint replied with an error: %s",
- err.name);
-
- /* Clear endpoint configuration in case of NO_REPLY error */
- if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
- if (request->cb)
- request->cb(endpoint, NULL, size,
- request->user_data);
- media_endpoint_clear_configuration(endpoint);
- dbus_message_unref(reply);
- dbus_error_free(&err);
- return;
- }
-
- dbus_error_free(&err);
- goto done;
- }
-
- dbus_error_init(&err);
- if (dbus_message_is_method_call(request->msg, MEDIA_ENDPOINT_INTERFACE,
- "SelectConfiguration")) {
- DBusMessageIter args, array;
- uint8_t *configuration;
-
- dbus_message_iter_init(reply, &args);
-
- dbus_message_iter_recurse(&args, &array);
-
- dbus_message_iter_get_fixed_array(&array, &configuration, &size);
-
- ret = configuration;
- goto done;
- } else if (!dbus_message_get_args(reply, &err, DBUS_TYPE_INVALID)) {
- error("Wrong reply signature: %s", err.message);
- dbus_error_free(&err);
- goto done;
- }
-
- size = 1;
- value = TRUE;
- ret = &value;
-
-done:
- dbus_message_unref(reply);
-
- if (request->cb)
- request->cb(endpoint, ret, size, request->user_data);
-
- endpoint_request_free(request);
- endpoint->request = NULL;
-}
-
-static gboolean media_endpoint_async_call(DBusConnection *conn,
- DBusMessage *msg,
- struct media_endpoint *endpoint,
- media_endpoint_cb_t cb,
- void *user_data)
-{
- 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) */
- if (dbus_connection_send_with_reply(conn, msg, &request->call,
- REQUEST_TIMEOUT) == FALSE) {
- error("D-Bus send failed");
- g_free(request);
- return FALSE;
- }
-
- dbus_pending_call_set_notify(request->call, endpoint_reply, endpoint, NULL);
-
- request->msg = msg;
- request->cb = cb;
- request->user_data = user_data;
- endpoint->request = request;
-
- DBG("Calling %s: name = %s path = %s", dbus_message_get_member(msg),
- dbus_message_get_destination(msg),
- dbus_message_get_path(msg));
-
- return TRUE;
-}
-
-gboolean media_endpoint_set_configuration(struct media_endpoint *endpoint,
- struct audio_device *device,
- uint8_t *configuration, size_t size,
- media_endpoint_cb_t cb,
- void *user_data)
-{
- DBusConnection *conn;
- DBusMessage *msg;
- const char *path;
- DBusMessageIter iter;
-
- if (endpoint->transport != NULL || endpoint->request != NULL)
- return FALSE;
-
- conn = endpoint->adapter->conn;
-
- endpoint->transport = media_transport_create(conn, endpoint, device,
- configuration, size);
- if (endpoint->transport == NULL)
- return FALSE;
-
- msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
- MEDIA_ENDPOINT_INTERFACE,
- "SetConfiguration");
- if (msg == NULL) {
- error("Couldn't allocate D-Bus message");
- return FALSE;
- }
-
- dbus_message_iter_init_append(msg, &iter);
-
- path = media_transport_get_path(endpoint->transport);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
-
- transport_get_properties(endpoint->transport, &iter);
-
- return media_endpoint_async_call(conn, msg, endpoint, cb, user_data);
-}
-
-gboolean media_endpoint_select_configuration(struct media_endpoint *endpoint,
- uint8_t *capabilities,
- size_t length,
- media_endpoint_cb_t cb,
- void *user_data)
-{
- DBusConnection *conn;
- DBusMessage *msg;
-
- if (endpoint->request != NULL)
- return FALSE;
-
- conn = endpoint->adapter->conn;
-
- msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
- MEDIA_ENDPOINT_INTERFACE,
- "SelectConfiguration");
- if (msg == NULL) {
- error("Couldn't allocate D-Bus message");
- return FALSE;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &capabilities, length,
- DBUS_TYPE_INVALID);
-
- return media_endpoint_async_call(conn, msg, endpoint, cb, user_data);
-}
-
-void media_endpoint_clear_configuration(struct media_endpoint *endpoint)
-{
- 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;
-
- msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
- MEDIA_ENDPOINT_INTERFACE,
- "ClearConfiguration");
- if (msg == NULL) {
- error("Couldn't allocate D-Bus message");
- goto done;
- }
-
- path = media_transport_get_path(endpoint->transport);
- dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID);
- g_dbus_send_message(conn, msg);
-done:
- endpoint->transport = NULL;
- media_transport_destroy(transport);
-}
-
-void media_endpoint_release(struct media_endpoint *endpoint)
-{
- DBusMessage *msg;
-
- DBG("sender=%s path=%s", endpoint->sender, endpoint->path);
-
- /* already exit */
- if (endpoint->watch == 0)
- return;
-
- msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
- MEDIA_ENDPOINT_INTERFACE,
- "Release");
- if (msg == NULL) {
- error("Couldn't allocate D-Bus message");
- return;
- }
-
- g_dbus_send_message(endpoint->adapter->conn, msg);
-
- media_endpoint_remove(endpoint);
-}
-
struct a2dp_sep *media_endpoint_get_sep(struct media_endpoint *endpoint)
{
return endpoint->sep;
@@ -712,9 +826,3 @@ uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint)
{
return endpoint->codec;
}
-
-struct media_transport *media_endpoint_get_transport(
- struct media_endpoint *endpoint)
-{
- return endpoint->transport;
-}
diff --git a/audio/media.h b/audio/media.h
index d089103..ee9a51e 100644
--- a/audio/media.h
+++ b/audio/media.h
@@ -30,23 +30,6 @@ typedef void (*media_endpoint_cb_t) (struct media_endpoint *endpoint,
int media_register(DBusConnection *conn, const char *path, const bdaddr_t *src);
void media_unregister(const char *path);

-const char *media_endpoint_get_sender(struct media_endpoint *endpoint);
-
-size_t media_endpoint_get_capabilities(struct media_endpoint *endpoint,
- uint8_t **capabilities);
-gboolean media_endpoint_set_configuration(struct media_endpoint *endpoint,
- struct audio_device *device,
- uint8_t *configuration, size_t size,
- media_endpoint_cb_t cb,
- void *user_data);
-gboolean media_endpoint_select_configuration(struct media_endpoint *endpoint,
- uint8_t *capabilities,
- size_t length,
- media_endpoint_cb_t cb,
- void *user_data);
-void media_endpoint_clear_configuration(struct media_endpoint *endpoint);
-void media_endpoint_release(struct media_endpoint *endpoint);
-
struct a2dp_sep *media_endpoint_get_sep(struct media_endpoint *endpoint);
const char *media_endpoint_get_uuid(struct media_endpoint *endpoint);
uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint);
diff --git a/audio/transport.c b/audio/transport.c
index cd2de37..f915262 100644
--- a/audio/transport.c
+++ b/audio/transport.c
@@ -99,7 +99,6 @@ void media_transport_destroy(struct media_transport *transport)
char *path;

path = g_strdup(transport->path);
-
g_dbus_unregister_interface(transport->conn, path,
MEDIA_TRANSPORT_INTERFACE);

@@ -922,4 +921,4 @@ void media_transport_update_delay(struct media_transport *transport,
struct audio_device *media_transport_get_dev(struct media_transport *transport)
{
return transport->device;
-}
\ No newline at end of file
+}
--
1.7.6