From: Mikel Astiz <mikel.astiz@xxxxxxxxxxxx> Merging the three audio profiles (AVDTP, A2DP sink and A2DP source) into one was convenient in the past was doesn't fit very well the new btd_profile approach. The split is also more consistent with the approach of the HFP/HSP profile. --- profiles/audio/a2dp.c | 88 ++++++++++++++++++-------------------- profiles/audio/a2dp.h | 4 +- profiles/audio/manager.c | 107 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 135 insertions(+), 64 deletions(-) diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c index 7799420..6bfc8c2 100644 --- a/profiles/audio/a2dp.c +++ b/profiles/audio/a2dp.c @@ -1167,73 +1167,67 @@ static struct a2dp_server *find_server(GSList *list, const bdaddr_t *src) return NULL; } -int a2dp_register(const bdaddr_t *src, GKeyFile *config) +int a2dp_server_register(const bdaddr_t *src, GKeyFile *config) { - gboolean source = TRUE, sink = FALSE; gboolean delay_reporting = FALSE; - char *str; - GError *err = NULL; struct a2dp_server *server; + int av_err; - if (!config) - goto proceed; + server = find_server(servers, src); + if (server) + return 0; - str = g_key_file_get_string(config, "General", "Enable", &err); + server = g_new0(struct a2dp_server, 1); - if (err) { - DBG("audio.conf: %s", err->message); - g_clear_error(&err); - } else { - if (strstr(str, "Sink")) - source = TRUE; - if (strstr(str, "Source")) - sink = TRUE; - g_free(str); + av_err = avdtp_init(src, config, &server->version); + if (av_err < 0) { + g_free(server); + return av_err; } - str = g_key_file_get_string(config, "General", "Disable", &err); + bacpy(&server->src, src); + servers = g_slist_append(servers, server); - if (err) { - DBG("audio.conf: %s", err->message); - g_clear_error(&err); - } else { - if (strstr(str, "Sink")) - source = FALSE; - if (strstr(str, "Source")) - sink = FALSE; - g_free(str); - } + if (config) + delay_reporting = g_key_file_get_boolean(config, "A2DP", + "DelayReporting", NULL); -proceed: + if (delay_reporting) + server->version = 0x0103; + else + server->version = 0x0102; + + return 0; +} + +int a2dp_source_register(const bdaddr_t *src, GKeyFile *config) +{ + struct a2dp_server *server; server = find_server(servers, src); if (!server) { - int av_err; + DBG("AVDTP not registered"); + return -EPROTONOSUPPORT; - server = g_new0(struct a2dp_server, 1); + } - av_err = avdtp_init(src, config, &server->version); - if (av_err < 0) { - g_free(server); - return av_err; - } + server->source_enabled = TRUE; - bacpy(&server->src, src); - servers = g_slist_append(servers, server); - } + return 0; +} - if (config) - delay_reporting = g_key_file_get_boolean(config, "A2DP", - "DelayReporting", NULL); +int a2dp_sink_register(const bdaddr_t *src, GKeyFile *config) +{ + struct a2dp_server *server; - if (delay_reporting) - server->version = 0x0103; - else - server->version = 0x0102; + server = find_server(servers, src); + if (!server) { + DBG("AVDTP not registered"); + return -EPROTONOSUPPORT; - server->source_enabled = source; + } - server->sink_enabled = sink; + server->sink_enabled = TRUE; return 0; } diff --git a/profiles/audio/a2dp.h b/profiles/audio/a2dp.h index 736bc66..c471499 100644 --- a/profiles/audio/a2dp.h +++ b/profiles/audio/a2dp.h @@ -64,7 +64,9 @@ typedef void (*a2dp_stream_cb_t) (struct avdtp *session, struct avdtp_error *err, void *user_data); -int a2dp_register(const bdaddr_t *src, GKeyFile *config); +int a2dp_server_register(const bdaddr_t *src, GKeyFile *config); +int a2dp_source_register(const bdaddr_t *src, GKeyFile *config); +int a2dp_sink_register(const bdaddr_t *src, GKeyFile *config); void a2dp_unregister(const bdaddr_t *src); struct a2dp_sep *a2dp_add_sep(const bdaddr_t *src, uint8_t type, diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c index 19aeb24..d7c1717 100644 --- a/profiles/audio/manager.c +++ b/profiles/audio/manager.c @@ -128,7 +128,7 @@ static void audio_remove(struct btd_profile *p, struct btd_device *device) audio_device_unregister(dev); } -static int a2dp_probe(struct btd_profile *p, struct btd_device *device, +static int a2dp_source_probe(struct btd_profile *p, struct btd_device *device, GSList *uuids) { struct audio_device *audio_dev; @@ -139,13 +139,23 @@ static int a2dp_probe(struct btd_profile *p, struct btd_device *device, return -1; } - if (g_slist_find_custom(uuids, A2DP_SINK_UUID, bt_uuid_strcmp) && - audio_dev->sink == NULL) - audio_dev->sink = sink_init(audio_dev); + audio_dev->source = source_init(audio_dev); - if (g_slist_find_custom(uuids, A2DP_SOURCE_UUID, bt_uuid_strcmp) && - audio_dev->source == NULL) - audio_dev->source = source_init(audio_dev); + return 0; +} + +static int a2dp_sink_probe(struct btd_profile *p, struct btd_device *device, + GSList *uuids) +{ + struct audio_device *audio_dev; + + audio_dev = get_audio_dev(device); + if (!audio_dev) { + DBG("unable to get a device object"); + return -1; + } + + audio_dev->sink = sink_init(audio_dev); return 0; } @@ -232,7 +242,7 @@ static int a2dp_server_probe(struct btd_profile *p, if (!adp) return -EINVAL; - err = a2dp_register(adapter_get_address(adapter), config); + err = a2dp_server_register(adapter_get_address(adapter), config); if (err < 0) audio_adapter_unref(adp); @@ -255,6 +265,40 @@ static void a2dp_server_remove(struct btd_profile *p, audio_adapter_unref(adp); } +static int a2dp_source_server_probe(struct btd_profile *p, + struct btd_adapter *adapter) +{ + struct audio_adapter *adp; + const gchar *path = adapter_get_path(adapter); + + DBG("path %s", path); + + adp = audio_adapter_get(adapter); + if (!adp) + return -EINVAL; + + audio_adapter_unref(adp); /* Referenced by a2dp server */ + + return a2dp_source_register(adapter_get_address(adapter), config); +} + +static int a2dp_sink_server_probe(struct btd_profile *p, + struct btd_adapter *adapter) +{ + struct audio_adapter *adp; + const gchar *path = adapter_get_path(adapter); + + DBG("path %s", path); + + adp = audio_adapter_get(adapter); + if (!adp) + return -EINVAL; + + audio_adapter_unref(adp); /* Referenced by a2dp server */ + + return a2dp_sink_register(adapter_get_address(adapter), config); +} + static int avrcp_server_probe(struct btd_profile *p, struct btd_adapter *adapter) { @@ -325,19 +369,38 @@ static void media_server_remove(struct btd_adapter *adapter) audio_adapter_unref(adp); } -static struct btd_profile a2dp_profile = { - .name = "audio-a2dp", +static struct btd_profile avdtp_profile = { + .name = "audio-avdtp", .priority = BTD_PROFILE_PRIORITY_MEDIUM, - .remote_uuids = BTD_UUIDS(A2DP_SOURCE_UUID, A2DP_SINK_UUID, - ADVANCED_AUDIO_UUID), - .device_probe = a2dp_probe, - .device_remove = audio_remove, + .remote_uuids = BTD_UUIDS(ADVANCED_AUDIO_UUID), .adapter_probe = a2dp_server_probe, .adapter_remove = a2dp_server_remove, }; +static struct btd_profile a2dp_source_profile = { + .name = "audio-source", + .priority = BTD_PROFILE_PRIORITY_MEDIUM, + + .remote_uuids = BTD_UUIDS(A2DP_SOURCE_UUID), + .device_probe = a2dp_source_probe, + .device_remove = audio_remove, + + .adapter_probe = a2dp_source_server_probe, +}; + +static struct btd_profile a2dp_sink_profile = { + .name = "audio-sink", + .priority = BTD_PROFILE_PRIORITY_MEDIUM, + + .remote_uuids = BTD_UUIDS(A2DP_SINK_UUID), + .device_probe = a2dp_sink_probe, + .device_remove = audio_remove, + + .adapter_probe = a2dp_sink_server_probe, +}; + static struct btd_profile avrcp_profile = { .name = "audio-avrcp", @@ -409,7 +472,13 @@ int audio_manager_init(GKeyFile *conf) proceed: if (enabled.source || enabled.sink) - btd_profile_register(&a2dp_profile); + btd_profile_register(&avdtp_profile); + + if (enabled.source) + btd_profile_register(&a2dp_source_profile); + + if (enabled.sink) + btd_profile_register(&a2dp_sink_profile); if (enabled.control) btd_profile_register(&avrcp_profile); @@ -426,8 +495,14 @@ void audio_manager_exit(void) config = NULL; } + if (enabled.source) + btd_profile_unregister(&a2dp_source_profile); + + if (enabled.sink) + btd_profile_unregister(&a2dp_sink_profile); + if (enabled.source || enabled.sink) - btd_profile_unregister(&a2dp_profile); + btd_profile_unregister(&avdtp_profile); if (enabled.control) btd_profile_unregister(&avrcp_profile); -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html