a2dp: Implement MediaTransport.Endpoint
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 4 Jan 2019 19:24:18 +0000 (16:24 -0300)
committerhimanshu <h.himanshu@samsung.com>
Wed, 22 Jan 2020 10:32:11 +0000 (16:02 +0530)
This implements MediaTransport.Endpoint property which exposes what
endpoint is being used by the transport.

Change-Id: I423a774f8b5bd57f34ac206f65f81b7cfa1a6806
Signed-off-by: himanshu <h.himanshu@samsung.com>
profiles/audio/a2dp.c
profiles/audio/a2dp.h
profiles/audio/media.c
profiles/audio/transport.c
profiles/audio/transport.h

index 7d17aa1..3e6796e 100644 (file)
@@ -116,7 +116,7 @@ struct a2dp_setup {
        struct a2dp_channel *chan;
        struct avdtp *session;
        struct a2dp_sep *sep;
-       struct avdtp_remote_sep *rsep;
+       struct a2dp_remote_sep *rsep;
        struct avdtp_stream *stream;
        struct avdtp_error *err;
        avdtp_set_configuration_cb setconf_cb;
@@ -1138,6 +1138,24 @@ static gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep,
        return TRUE;
 }
 
+static bool match_remote_sep(const void *data, const void *user_data)
+{
+       const struct a2dp_remote_sep *sep = data;
+       const struct avdtp_remote_sep *rsep = user_data;
+
+       return sep->sep == rsep;
+}
+
+static struct a2dp_remote_sep *find_remote_sep(struct a2dp_channel *chan,
+                                               struct a2dp_sep *sep)
+{
+       struct avdtp_remote_sep *rsep;
+
+       rsep = avdtp_find_remote_sep(chan->session, sep->lsep);
+
+       return queue_find(chan->seps, match_remote_sep, rsep);
+}
+
 static gboolean a2dp_reconfigure(gpointer data)
 {
        struct a2dp_setup *setup = data;
@@ -1147,14 +1165,14 @@ static gboolean a2dp_reconfigure(gpointer data)
        struct avdtp_service_capability *cap;
 
        if (setup->rsep) {
-               cap = avdtp_get_codec(setup->rsep);
+               cap = avdtp_get_codec(setup->rsep->sep);
                rsep_codec = (struct avdtp_media_codec_capability *) cap->data;
        }
 
        if (!setup->rsep || sep->codec != rsep_codec->media_codec_type)
-               setup->rsep = avdtp_find_remote_sep(setup->session, sep->lsep);
+               setup->rsep = find_remote_sep(setup->chan, sep);
 
-       posix_err = avdtp_set_configuration(setup->session, setup->rsep,
+       posix_err = avdtp_set_configuration(setup->session, setup->rsep->sep,
                                                sep->lsep,
                                                setup->caps,
                                                &setup->stream);
@@ -1170,6 +1188,16 @@ failed:
        return FALSE;
 }
 
+static struct a2dp_remote_sep *get_remote_sep(struct a2dp_channel *chan,
+                                               struct avdtp_stream *stream)
+{
+       struct avdtp_remote_sep *rsep;
+
+       rsep = avdtp_stream_get_remote_sep(stream);
+
+       return queue_find(chan->seps, match_remote_sep, rsep);
+}
+
 static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
                        struct avdtp_stream *stream, struct avdtp_error *err,
                        void *user_data)
@@ -1194,7 +1222,7 @@ static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
        }
 
        if (!setup->rsep)
-               setup->rsep = avdtp_stream_get_remote_sep(stream);
+               setup->rsep = get_remote_sep(setup->chan, stream);
 
        if (setup->reconfigure)
                g_timeout_add(RECONFIGURE_TIMEOUT, a2dp_reconfigure, setup);
@@ -1439,10 +1467,23 @@ static struct a2dp_server *find_server(GSList *list, struct btd_adapter *a)
        return NULL;
 }
 
+static void remote_sep_free(void *data)
+{
+       struct a2dp_remote_sep *sep = data;
+
+       free(sep->path);
+       free(sep);
+}
+
 static void remove_remote_sep(void *data)
 {
        struct a2dp_remote_sep *sep = data;
 
+       if (!sep->path) {
+               remote_sep_free(sep);
+               return;
+       }
+
        g_dbus_unregister_interface(btd_get_dbus_connection(), sep->path,
                                                MEDIA_ENDPOINT_INTERFACE);
 }
@@ -2198,7 +2239,7 @@ static int a2dp_reconfig(struct a2dp_channel *chan, const char *sender,
                return -ENOMEM;
 
        setup->sep = lsep;
-       setup->rsep = rsep->sep;
+       setup->rsep = rsep;
 
        setup_add_caps(setup, caps, size);
 
@@ -2226,7 +2267,7 @@ static int a2dp_reconfig(struct a2dp_channel *chan, const char *sender,
                }
        }
 
-       err = avdtp_set_configuration(setup->session, setup->rsep,
+       err = avdtp_set_configuration(setup->session, setup->rsep->sep,
                                                lsep->lsep,
                                                setup->caps,
                                                &setup->stream);
@@ -2360,14 +2401,6 @@ static const GDBusPropertyTable sep_properties[] = {
        { }
 };
 
-static void remote_sep_free(void *data)
-{
-       struct a2dp_remote_sep *sep = data;
-
-       free(sep->path);
-       free(sep);
-}
-
 static void register_remote_sep(void *data, void *user_data)
 {
        struct avdtp_remote_sep *rsep = data;
@@ -2377,6 +2410,10 @@ static void register_remote_sep(void *data, void *user_data)
        sep = new0(struct a2dp_remote_sep, 1);
        sep->chan = setup->chan;
        sep->sep = rsep;
+
+       if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL))
+               goto done;
+
        asprintf(&sep->path, "%s/sep%d", device_get_path(setup->chan->device),
                                                        avdtp_get_seid(rsep));
 
@@ -2385,9 +2422,13 @@ static void register_remote_sep(void *data, void *user_data)
                                sep_methods, NULL, sep_properties,
                                sep, remote_sep_free) == FALSE) {
                error("Could not register remote sep %s", sep->path);
-               remote_sep_free(sep);
+               free(sep->path);
+               sep->path = NULL;
        }
 
+       DBG("Found remote SEP: %s", sep->path);
+
+done:
        queue_push_tail(setup->chan->seps, sep);
 }
 
@@ -2455,14 +2496,14 @@ unsigned int a2dp_select_capabilities(struct avdtp *session,
        cb_data->user_data = user_data;
 
        setup->sep = sep;
-       setup->rsep = avdtp_find_remote_sep(session, sep->lsep);
+       setup->rsep = find_remote_sep(setup->chan, sep);
 
        if (setup->rsep == NULL) {
                error("Could not find remote sep");
                goto fail;
        }
 
-       service = avdtp_get_codec(setup->rsep);
+       service = avdtp_get_codec(setup->rsep->sep);
        codec = (struct avdtp_media_codec_capability *) service->data;
 
        err = sep->endpoint->select_configuration(sep, codec->data,
@@ -2556,13 +2597,13 @@ unsigned int a2dp_config(struct avdtp *session, struct a2dp_sep *sep,
                        break;
                }
 
-               setup->rsep = avdtp_find_remote_sep(session, sep->lsep);
+               setup->rsep = find_remote_sep(setup->chan, sep);
                if (setup->rsep == NULL) {
                        error("No matching ACP and INT SEPs found");
                        goto failed;
                }
 
-               posix_err = avdtp_set_configuration(session, setup->rsep,
+               posix_err = avdtp_set_configuration(session, setup->rsep->sep,
                                                        sep->lsep, caps,
                                                        &setup->stream);
                if (posix_err < 0) {
@@ -2804,6 +2845,16 @@ struct btd_device *a2dp_setup_get_device(struct a2dp_setup *setup)
        return avdtp_get_device(setup->session);
 }
 
+const char *a2dp_setup_remote_path(struct a2dp_setup *setup)
+{
+       if (setup->rsep) {
+               if (setup->rsep->path)
+                       return setup->rsep->path;
+       }
+
+       return NULL;
+}
+
 static int a2dp_source_probe(struct btd_service *service)
 {
        struct btd_device *dev = btd_service_get_device(service);
index 7f38c75..19466a4 100755 (executable)
@@ -91,4 +91,5 @@ gboolean a2dp_sep_lock(struct a2dp_sep *sep, struct avdtp *session);
 gboolean a2dp_sep_unlock(struct a2dp_sep *sep, struct avdtp *session);
 struct avdtp_stream *a2dp_sep_get_stream(struct a2dp_sep *sep);
 struct btd_device *a2dp_setup_get_device(struct a2dp_setup *setup);
+const char *a2dp_setup_remote_path(struct a2dp_setup *setup);
 struct avdtp *a2dp_avdtp_get(struct btd_device *device);
index 9c8c724..d178138 100755 (executable)
@@ -624,8 +624,9 @@ static gboolean set_configuration(struct media_endpoint *endpoint,
        if (transport != NULL)
                return FALSE;
 
-       transport = media_transport_create(device, configuration, size,
-                                                               endpoint);
+       transport = media_transport_create(device,
+                                       a2dp_setup_remote_path(data->setup),
+                                       configuration, size, endpoint);
        if (transport == NULL)
                return FALSE;
 
index adb5fc6..8a60a77 100755 (executable)
@@ -97,6 +97,7 @@ struct a2dp_transport {
 struct media_transport {
        char                    *path;          /* Transport object path */
        struct btd_device       *device;        /* Transport device */
+       const char              *remote_endpoint; /* Transport remote SEP */
        struct media_endpoint   *endpoint;      /* Transport endpoint */
        struct media_owner      *owner;         /* Transport owner */
        uint8_t                 *configuration; /* Transport configuration */
@@ -729,6 +730,24 @@ static void set_volume(const GDBusPropertyTable *property,
        avrcp_set_volume(transport->device, volume, notify);
 }
 
+static gboolean endpoint_exists(const GDBusPropertyTable *property, void *data)
+{
+       struct media_transport *transport = data;
+
+       return transport->remote_endpoint != NULL;
+}
+
+static gboolean get_endpoint(const GDBusPropertyTable *property,
+                                       DBusMessageIter *iter, void *data)
+{
+       struct media_transport *transport = data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
+                                       &transport->remote_endpoint);
+
+       return TRUE;
+}
+
 static const GDBusMethodTable transport_methods[] = {
        { GDBUS_ASYNC_METHOD("Acquire",
                        NULL,
@@ -756,6 +775,8 @@ static const GDBusPropertyTable transport_properties[] = {
        { "Delay", "q", get_delay, NULL, delay_exists },
 #endif
        { "Volume", "q", get_volume, set_volume, volume_exists },
+       { "Endpoint", "o", get_endpoint, NULL, endpoint_exists,
+                               G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
        { }
 };
 
@@ -880,6 +901,7 @@ static int media_transport_init_sink(struct media_transport *transport)
 }
 
 struct media_transport *media_transport_create(struct btd_device *device,
+                                               const char *remote_endpoint,
                                                uint8_t *configuration,
                                                size_t size, void *data)
 {
@@ -894,8 +916,10 @@ struct media_transport *media_transport_create(struct btd_device *device,
        transport->configuration = g_new(uint8_t, size);
        memcpy(transport->configuration, configuration, size);
        transport->size = size;
-       transport->path = g_strdup_printf("%s/fd%d", device_get_path(device),
-                                                                       fd++);
+       transport->remote_endpoint = remote_endpoint;
+       transport->path = g_strdup_printf("%s/fd%d",
+                               remote_endpoint ? remote_endpoint :
+                               device_get_path(device), fd++);
        transport->fd = -1;
 
        uuid = media_endpoint_get_uuid(endpoint);
index d529550..3ce75a1 100755 (executable)
@@ -25,6 +25,7 @@
 struct media_transport;
 
 struct media_transport *media_transport_create(struct btd_device *device,
+                                               const char *remote_endpoint,
                                                uint8_t *configuration,
                                                size_t size, void *data);