summaryrefslogtreecommitdiffstats
path: root/audio/control.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-09-08 18:20:29 -0300
committerLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-09-08 18:20:29 -0300
commit957d01bac7a4c448bbe0a15de613af7927d1c7d0 (patch)
tree4c279a27c3284d9434a08cc5802b97bf846c6479 /audio/control.c
parent75b61c0a4f415fdb6518b9cf99f9b5d4b8072c5f (diff)
Fix a2dp and avrcp drivers to not rely on BDADDR_ANY.
Diffstat (limited to 'audio/control.c')
-rw-r--r--audio/control.c87
1 files changed, 60 insertions, 27 deletions
diff --git a/audio/control.c b/audio/control.c
index a1014d48..15e38c99 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -97,11 +97,7 @@
static DBusConnection *connection = NULL;
-static uint32_t tg_record_id = 0;
-static uint32_t ct_record_id = 0;
-
-static GIOChannel *avctp_server = NULL;
-
+static GSList *servers = NULL;
static GSList *sessions = NULL;
typedef enum {
@@ -150,6 +146,13 @@ struct avrcp_header {
#error "Unknown byte order"
#endif
+struct avctp_server {
+ bdaddr_t src;
+ GIOChannel *io;
+ uint32_t tg_record_id;
+ uint32_t ct_record_id;
+};
+
struct avctp {
struct audio_device *dev;
@@ -703,7 +706,7 @@ drop:
close(session->sock);
}
-static GIOChannel *avctp_server_socket(gboolean master)
+static GIOChannel *avctp_server_socket(const bdaddr_t *src, gboolean master)
{
GIOChannel *io;
int lm = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
@@ -711,7 +714,7 @@ static GIOChannel *avctp_server_socket(gboolean master)
if (master)
lm |= L2CAP_LM_MASTER;
- io = bt_l2cap_listen(BDADDR_ANY, AVCTP_PSM, 0, lm, avctp_server_cb,
+ io = bt_l2cap_listen(src, AVCTP_PSM, 0, lm, avctp_server_cb,
NULL);
if (!io) {
error("Unable to allocate new io channel");
@@ -810,14 +813,12 @@ void avrcp_disconnect(struct audio_device *dev)
control->session = NULL;
}
-int avrcp_init(DBusConnection *conn, GKeyFile *config)
+int avrcp_register(DBusConnection *conn, const bdaddr_t *src, GKeyFile *config)
{
sdp_record_t *record;
gboolean tmp, master = TRUE;
GError *err = NULL;
-
- if (avctp_server)
- return 0;
+ struct avctp_server *server;
if (config) {
tmp = g_key_file_get_boolean(config, "General",
@@ -829,7 +830,12 @@ int avrcp_init(DBusConnection *conn, GKeyFile *config)
master = tmp;
}
- connection = dbus_connection_ref(conn);
+ server = g_new0(struct avctp_server, 1);
+ if (!server)
+ return -ENOMEM;
+
+ if (!connection)
+ connection = dbus_connection_ref(conn);
record = avrcp_tg_record();
if (!record) {
@@ -837,12 +843,12 @@ int avrcp_init(DBusConnection *conn, GKeyFile *config)
return -1;
}
- if (add_record_to_server(BDADDR_ANY, record) < 0) {
+ if (add_record_to_server(src, record) < 0) {
error("Unable to register AVRCP target service record");
sdp_record_free(record);
return -1;
}
- tg_record_id = record->handle;
+ server->tg_record_id = record->handle;
record = avrcp_ct_record();
if (!record) {
@@ -850,34 +856,61 @@ int avrcp_init(DBusConnection *conn, GKeyFile *config)
return -1;
}
- if (add_record_to_server(BDADDR_ANY, record) < 0) {
+ if (add_record_to_server(src, record) < 0) {
error("Unable to register AVRCP controller service record");
sdp_record_free(record);
return -1;
}
- ct_record_id = record->handle;
+ server->ct_record_id = record->handle;
- avctp_server = avctp_server_socket(master);
- if (!avctp_server)
+ server->io = avctp_server_socket(src, master);
+ if (!server->io) {
+ remove_record_from_server(server->ct_record_id);
+ remove_record_from_server(server->tg_record_id);
+ g_free(server);
return -1;
+ }
+
+ bacpy(&server->src, src);
+
+ servers = g_slist_append(servers, server);
return 0;
}
-void avrcp_exit(void)
+static struct avctp_server *find_server(GSList *list, const bdaddr_t *src)
{
- if (!avctp_server)
+ GSList *l;
+
+ for (l = list; l; l = l->next) {
+ struct avctp_server *server = l->data;
+
+ if (bacmp(&server->src, src) == 0)
+ return server;
+ }
+
+ return NULL;
+}
+
+void avrcp_unregister(const bdaddr_t *src)
+{
+ struct avctp_server *server;
+
+ server = find_server(servers, src);
+ if (!server)
return;
- g_io_channel_close(avctp_server);
- g_io_channel_unref(avctp_server);
- avctp_server = NULL;
+ servers = g_slist_remove(servers, server);
- remove_record_from_server(ct_record_id);
- ct_record_id = 0;
+ remove_record_from_server(server->ct_record_id);
+ remove_record_from_server(server->tg_record_id);
- remove_record_from_server(tg_record_id);
- tg_record_id = 0;
+ g_io_channel_close(server->io);
+ g_io_channel_unref(server->io);
+ g_free(server);
+
+ if (servers)
+ return;
dbus_connection_unref(connection);
connection = NULL;