[RFC v0 2/5] audio: Split AVRCP into two btd_profile

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Mikel Astiz <mikel.astiz@xxxxxxxxxxxx>

Register a separate btd_profile for each role of AVRCP.
---
 profiles/audio/audio.conf |  2 +-
 profiles/audio/avrcp.c    | 80 ++++++++++++++++++++++++++++++++++++-----------
 profiles/audio/avrcp.h    |  6 ++--
 profiles/audio/manager.c  | 80 ++++++++++++++++++++++++++++++++++++++++-------
 profiles/audio/manager.h  |  1 +
 5 files changed, 137 insertions(+), 32 deletions(-)

diff --git a/profiles/audio/audio.conf b/profiles/audio/audio.conf
index f556610..566454b 100644
--- a/profiles/audio/audio.conf
+++ b/profiles/audio/audio.conf
@@ -8,5 +8,5 @@
 #Master=true
 
 # If we want to disable support for specific services
-# Defaults to supporting the services: Sink, Control
+# Defaults to supporting the services: Sink, Control, Target
 #Disable=Source
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index b32c422..22dd1a5 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -2305,41 +2305,63 @@ static struct avrcp_server *avrcp_server_register(const bdaddr_t *src,
 	return server;
 }
 
-int avrcp_register(const bdaddr_t *src, GKeyFile *config)
+int avrcp_target_register(const bdaddr_t *src, GKeyFile *config)
 {
 	sdp_record_t *record;
 	struct avrcp_server *server;
 
+	server = find_server(servers, src);
+	if (server != NULL)
+		goto done;
+
 	server = avrcp_server_register(src, config);
 	if (server == NULL)
 		return -EPROTONOSUPPORT;
 
+done:
 	record = avrcp_tg_record();
 	if (!record) {
 		error("Unable to allocate new service record");
-		avrcp_unregister(src);
+		avrcp_target_unregister(src);
 		return -1;
 	}
 
 	if (add_record_to_server(src, record) < 0) {
 		error("Unable to register AVRCP target service record");
-		avrcp_unregister(src);
+		avrcp_target_unregister(src);
 		sdp_record_free(record);
 		return -1;
 	}
 	server->tg_record_id = record->handle;
 
+	return 0;
+}
+
+int avrcp_control_register(const bdaddr_t *src, GKeyFile *config)
+{
+	sdp_record_t *record;
+	struct avrcp_server *server;
+
+	server = find_server(servers, src);
+	if (server != NULL)
+		goto done;
+
+	server = avrcp_server_register(src, config);
+	if (server == NULL)
+		return -EPROTONOSUPPORT;
+
+done:
 	record = avrcp_ct_record();
 	if (!record) {
 		error("Unable to allocate new service record");
-		avrcp_unregister(src);
+		avrcp_control_unregister(src);
 		return -1;
 	}
 
 	if (add_record_to_server(src, record) < 0) {
 		error("Unable to register AVRCP service record");
 		sdp_record_free(record);
-		avrcp_unregister(src);
+		avrcp_control_unregister(src);
 		return -1;
 	}
 	server->ct_record_id = record->handle;
@@ -2347,25 +2369,13 @@ int avrcp_register(const bdaddr_t *src, GKeyFile *config)
 	return 0;
 }
 
-void avrcp_unregister(const bdaddr_t *src)
+static void avrcp_server_unregister(struct avrcp_server *server)
 {
-	struct avrcp_server *server;
-
-	server = find_server(servers, src);
-	if (!server)
-		return;
-
 	g_slist_free_full(server->sessions, g_free);
 	g_slist_free_full(server->players, player_destroy);
 
 	servers = g_slist_remove(servers, server);
 
-	if (server->ct_record_id != 0)
-		remove_record_from_server(server->ct_record_id);
-
-	if (server->tg_record_id != 0)
-		remove_record_from_server(server->tg_record_id);
-
 	avctp_unregister(&server->src);
 	g_free(server);
 
@@ -2378,6 +2388,40 @@ void avrcp_unregister(const bdaddr_t *src)
 	}
 }
 
+void avrcp_target_unregister(const bdaddr_t *src)
+{
+	struct avrcp_server *server;
+
+	server = find_server(servers, src);
+	if (!server)
+		return;
+
+	if (server->tg_record_id != 0) {
+		remove_record_from_server(server->tg_record_id);
+		server->tg_record_id = 0;
+	}
+
+	if (server->ct_record_id == 0)
+		avrcp_server_unregister(server);
+}
+
+void avrcp_control_unregister(const bdaddr_t *src)
+{
+	struct avrcp_server *server;
+
+	server = find_server(servers, src);
+	if (!server)
+		return;
+
+	if (server->ct_record_id != 0) {
+		remove_record_from_server(server->ct_record_id);
+		server->ct_record_id = 0;
+	}
+
+	if (server->tg_record_id == 0)
+		avrcp_server_unregister(server);
+}
+
 struct avrcp_player *avrcp_register_player(const bdaddr_t *src,
 						struct avrcp_player_cb *cb,
 						void *user_data,
diff --git a/profiles/audio/avrcp.h b/profiles/audio/avrcp.h
index e607fb1..cddf40b 100644
--- a/profiles/audio/avrcp.h
+++ b/profiles/audio/avrcp.h
@@ -92,8 +92,10 @@ struct avrcp_player_cb {
 							void *user_data);
 };
 
-int avrcp_register(const bdaddr_t *src, GKeyFile *config);
-void avrcp_unregister(const bdaddr_t *src);
+int avrcp_target_register(const bdaddr_t *src, GKeyFile *config);
+void avrcp_target_unregister(const bdaddr_t *src);
+int avrcp_control_register(const bdaddr_t *src, GKeyFile *config);
+void avrcp_control_unregister(const bdaddr_t *src);
 
 gboolean avrcp_connect(struct audio_device *dev);
 void avrcp_disconnect(struct audio_device *dev);
diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index 422316e..976a879 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -82,6 +82,7 @@ static struct enabled_interfaces enabled = {
 	.sink		= TRUE,
 	.source		= FALSE,
 	.control	= TRUE,
+	.target		= TRUE,
 };
 
 static struct audio_adapter *find_adapter(GSList *list,
@@ -371,7 +372,7 @@ static int a2dp_sink_server_probe(struct btd_profile *p,
 	return a2dp_sink_register(adapter_get_address(adapter), config);
 }
 
-static int avrcp_server_probe(struct btd_profile *p,
+static int avrcp_target_server_probe(struct btd_profile *p,
 						struct btd_adapter *adapter)
 {
 	struct audio_adapter *adp;
@@ -384,14 +385,50 @@ static int avrcp_server_probe(struct btd_profile *p,
 	if (!adp)
 		return -EINVAL;
 
-	err = avrcp_register(adapter_get_address(adapter), config);
+	err = avrcp_target_register(adapter_get_address(adapter), config);
 	if (err < 0)
 		audio_adapter_unref(adp);
 
 	return err;
 }
 
-static void avrcp_server_remove(struct btd_profile *p,
+static int avrcp_control_server_probe(struct btd_profile *p,
+						struct btd_adapter *adapter)
+{
+	struct audio_adapter *adp;
+	const gchar *path = adapter_get_path(adapter);
+	int err;
+
+	DBG("path %s", path);
+
+	adp = audio_adapter_get(adapter);
+	if (!adp)
+		return -EINVAL;
+
+	err = avrcp_control_register(adapter_get_address(adapter), config);
+	if (err < 0)
+		audio_adapter_unref(adp);
+
+	return err;
+}
+
+static void avrcp_target_server_remove(struct btd_profile *p,
+						struct btd_adapter *adapter)
+{
+	struct audio_adapter *adp;
+	const gchar *path = adapter_get_path(adapter);
+
+	DBG("path %s", path);
+
+	adp = find_adapter(adapters, adapter);
+	if (!adp)
+		return;
+
+	avrcp_target_unregister(adapter_get_address(adapter));
+	audio_adapter_unref(adp);
+}
+
+static void avrcp_control_server_remove(struct btd_profile *p,
 						struct btd_adapter *adapter)
 {
 	struct audio_adapter *adp;
@@ -403,7 +440,7 @@ static void avrcp_server_remove(struct btd_profile *p,
 	if (!adp)
 		return;
 
-	avrcp_unregister(adapter_get_address(adapter));
+	avrcp_control_unregister(adapter_get_address(adapter));
 	audio_adapter_unref(adp);
 }
 
@@ -471,10 +508,21 @@ static struct btd_profile a2dp_sink_profile = {
 	.adapter_probe	= a2dp_sink_server_probe,
 };
 
-static struct btd_profile avrcp_profile = {
-	.name		= "audio-avrcp",
+static struct btd_profile avrcp_target_profile = {
+	.name		= "audio-avrcp-target",
+
+	.remote_uuids	= BTD_UUIDS(AVRCP_TARGET_UUID),
+	.device_probe	= avrcp_probe,
+	.device_remove	= audio_remove,
+
+	.adapter_probe	= avrcp_target_server_probe,
+	.adapter_remove = avrcp_target_server_remove,
+};
+
+static struct btd_profile avrcp_control_profile = {
+	.name		= "audio-avrcp-control",
 
-	.remote_uuids	= BTD_UUIDS(AVRCP_TARGET_UUID, AVRCP_REMOTE_UUID),
+	.remote_uuids	= BTD_UUIDS(AVRCP_REMOTE_UUID),
 	.device_probe	= avrcp_probe,
 	.device_remove	= audio_remove,
 
@@ -482,8 +530,8 @@ static struct btd_profile avrcp_profile = {
 	.connect	= avrcp_control_connect,
 	.disconnect	= avrcp_control_disconnect,
 
-	.adapter_probe	= avrcp_server_probe,
-	.adapter_remove = avrcp_server_remove,
+	.adapter_probe	= avrcp_control_server_probe,
+	.adapter_remove = avrcp_control_server_remove,
 };
 
 static struct btd_adapter_driver media_driver = {
@@ -531,6 +579,8 @@ int audio_manager_init(GKeyFile *conf)
 			enabled.source = TRUE;
 		else if (g_str_equal(list[i], "Control"))
 			enabled.control = TRUE;
+		else if (g_str_equal(list[i], "Target"))
+			enabled.target = TRUE;
 	}
 	g_strfreev(list);
 
@@ -543,6 +593,8 @@ int audio_manager_init(GKeyFile *conf)
 			enabled.source = FALSE;
 		else if (g_str_equal(list[i], "Control"))
 			enabled.control = FALSE;
+		else if (g_str_equal(list[i], "Target"))
+			enabled.target = FALSE;
 	}
 	g_strfreev(list);
 
@@ -554,7 +606,10 @@ proceed:
 		btd_profile_register(&a2dp_sink_profile);
 
 	if (enabled.control)
-		btd_profile_register(&avrcp_profile);
+		btd_profile_register(&avrcp_control_profile);
+
+	if (enabled.target)
+		btd_profile_register(&avrcp_target_profile);
 
 	btd_register_adapter_driver(&media_driver);
 
@@ -575,7 +630,10 @@ void audio_manager_exit(void)
 		btd_profile_unregister(&a2dp_sink_profile);
 
 	if (enabled.control)
-		btd_profile_unregister(&avrcp_profile);
+		btd_profile_unregister(&avrcp_control_profile);
+
+	if (enabled.target)
+		btd_profile_unregister(&avrcp_target_profile);
 
 	btd_unregister_adapter_driver(&media_driver);
 }
diff --git a/profiles/audio/manager.h b/profiles/audio/manager.h
index 2b924dc..fc5362b 100644
--- a/profiles/audio/manager.h
+++ b/profiles/audio/manager.h
@@ -26,6 +26,7 @@ struct enabled_interfaces {
 	gboolean sink;
 	gboolean source;
 	gboolean control;
+	gboolean target;
 	gboolean media_player;
 };
 
-- 
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


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux