linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect
@ 2012-11-21 12:10 Luiz Augusto von Dentz
  2012-11-21 12:10 ` [PATCH BlueZ 2/6] audio: Split A2DP into two btd_profile Luiz Augusto von Dentz
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

We should with higher priority first.
---
 src/device.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/device.c b/src/device.c
index 0053098..fd29a7f 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1299,7 +1299,7 @@ static gint profile_prio_cmp(gconstpointer a, gconstpointer b)
 {
 	const struct btd_profile *p1 = a, *p2 = b;
 
-	return p1->priority - p2->priority;
+	return p2->priority - p1->priority;
 }
 
 static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 2/6] audio: Split A2DP into two btd_profile
  2012-11-21 12:10 [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Luiz Augusto von Dentz
@ 2012-11-21 12:10 ` Luiz Augusto von Dentz
  2012-11-21 12:10 ` [PATCH BlueZ 3/6] source: Add profile .connect and .disconnect Luiz Augusto von Dentz
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth

From: Mikel Astiz <mikel.astiz@bmw-carit.de>

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 other
existing profiles.
---
 profiles/audio/a2dp.c    | 80 +++++++++++++++++++++++------------------------
 profiles/audio/a2dp.h    |  3 +-
 profiles/audio/manager.c | 81 +++++++++++++++++++++++++++++++-----------------
 3 files changed, 92 insertions(+), 72 deletions(-)

diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 50c0f43..177f653 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1166,63 +1166,59 @@ static struct a2dp_server *find_server(GSList *list, const bdaddr_t *src)
 	return NULL;
 }
 
-int a2dp_register(const bdaddr_t *src, GKeyFile *config)
+static struct a2dp_server *a2dp_server_register(const bdaddr_t *src,
+							GKeyFile *config)
 {
-	gboolean source = TRUE, sink = FALSE;
-	char *str;
-	GError *err = NULL;
 	struct a2dp_server *server;
+	int av_err;
 
-	if (!config)
-		goto proceed;
+	server = g_new0(struct a2dp_server, 1);
 
-	str = g_key_file_get_string(config, "General", "Enable", &err);
-
-	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);
+	if (av_err < 0) {
+		DBG("AVDTP not registered");
+		g_free(server);
+		return NULL;
 	}
 
-	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);
-	}
+	return server;
+}
 
-proceed:
+int a2dp_source_register(const bdaddr_t *src, GKeyFile *config)
+{
+	struct a2dp_server *server;
 
 	server = find_server(servers, src);
-	if (!server) {
-		int av_err;
+	if (server != NULL)
+		goto done;
 
-		server = g_new0(struct a2dp_server, 1);
+	server = a2dp_server_register(src, config);
+	if (server == NULL)
+		return -EPROTONOSUPPORT;
 
-		av_err = avdtp_init(src, config);
-		if (av_err < 0) {
-			g_free(server);
-			return av_err;
-		}
+done:
+	server->source_enabled = TRUE;
 
-		bacpy(&server->src, src);
-		servers = g_slist_append(servers, server);
-	}
+	return 0;
+}
 
-	server->source_enabled = source;
+int a2dp_sink_register(const bdaddr_t *src, GKeyFile *config)
+{
+	struct a2dp_server *server;
 
-	server->sink_enabled = sink;
+	server = find_server(servers, src);
+	if (server != NULL)
+		goto done;
+
+	server = a2dp_server_register(src, config);
+	if (server == NULL)
+		return -EPROTONOSUPPORT;
+
+done:
+	server->sink_enabled = TRUE;
 
 	return 0;
 }
diff --git a/profiles/audio/a2dp.h b/profiles/audio/a2dp.h
index 736bc66..ded1060 100644
--- a/profiles/audio/a2dp.h
+++ b/profiles/audio/a2dp.h
@@ -64,7 +64,8 @@ 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_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 e453e26..2f36efd 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -122,7 +122,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;
@@ -133,13 +133,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;
 }
@@ -213,12 +223,11 @@ static struct audio_adapter *audio_adapter_get(struct btd_adapter *adapter)
 	return adp;
 }
 
-static int a2dp_server_probe(struct btd_profile *p,
+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);
-	int err;
 
 	DBG("path %s", path);
 
@@ -226,14 +235,12 @@ static int a2dp_server_probe(struct btd_profile *p,
 	if (!adp)
 		return -EINVAL;
 
-	err = a2dp_register(adapter_get_address(adapter), config);
-	if (err < 0)
-		audio_adapter_unref(adp);
+	audio_adapter_unref(adp); /* Referenced by a2dp server */
 
-	return err;
+	return a2dp_source_register(adapter_get_address(adapter), config);
 }
 
-static void a2dp_server_remove(struct btd_profile *p,
+static int a2dp_sink_server_probe(struct btd_profile *p,
 						struct btd_adapter *adapter)
 {
 	struct audio_adapter *adp;
@@ -241,12 +248,13 @@ static void a2dp_server_remove(struct btd_profile *p,
 
 	DBG("path %s", path);
 
-	adp = find_adapter(adapters, adapter);
+	adp = audio_adapter_get(adapter);
 	if (!adp)
-		return;
+		return -EINVAL;
 
-	a2dp_unregister(adapter_get_address(adapter));
-	audio_adapter_unref(adp);
+	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,
@@ -319,17 +327,26 @@ 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 a2dp_source_profile = {
+	.name		= "audio-source",
 	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
 
-	.remote_uuids	= BTD_UUIDS(A2DP_SOURCE_UUID, A2DP_SINK_UUID,
-							ADVANCED_AUDIO_UUID),
-	.device_probe	= a2dp_probe,
+	.remote_uuids	= BTD_UUIDS(A2DP_SOURCE_UUID),
+	.device_probe	= a2dp_source_probe,
 	.device_remove	= audio_remove,
 
-	.adapter_probe	= a2dp_server_probe,
-	.adapter_remove = a2dp_server_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 = {
@@ -402,8 +419,11 @@ int audio_manager_init(GKeyFile *conf)
 		max_connected_headsets = i;
 
 proceed:
-	if (enabled.source || enabled.sink)
-		btd_profile_register(&a2dp_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);
@@ -420,8 +440,11 @@ void audio_manager_exit(void)
 		config = NULL;
 	}
 
-	if (enabled.source || enabled.sink)
-		btd_profile_unregister(&a2dp_profile);
+	if (enabled.source)
+		btd_profile_unregister(&a2dp_source_profile);
+
+	if (enabled.sink)
+		btd_profile_unregister(&a2dp_sink_profile);
 
 	if (enabled.control)
 		btd_profile_unregister(&avrcp_profile);
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 3/6] source: Add profile .connect and .disconnect
  2012-11-21 12:10 [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Luiz Augusto von Dentz
  2012-11-21 12:10 ` [PATCH BlueZ 2/6] audio: Split A2DP into two btd_profile Luiz Augusto von Dentz
@ 2012-11-21 12:10 ` Luiz Augusto von Dentz
  2012-11-21 12:10 ` [PATCH BlueZ 4/6] sink: " Luiz Augusto von Dentz
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth

From: Mikel Astiz <mikel.astiz@bmw-carit.de>

Add the connection and disconnection hooks to the a2dp_source
btd_profile.
---
 profiles/audio/manager.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index 2f36efd..eaae018 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -74,6 +74,12 @@ struct audio_adapter {
 	gint ref;
 };
 
+struct profile_req {
+	struct btd_device	*device;
+	struct btd_profile	*profile;
+	btd_profile_cb		cb;
+};
+
 static gboolean auto_connect = TRUE;
 static int max_connected_headsets = 1;
 static GKeyFile *config = NULL;
@@ -176,6 +182,86 @@ static int avrcp_probe(struct btd_profile *p, struct btd_device *device,
 	return 0;
 }
 
+static struct profile_req *new_profile_request(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	struct profile_req *req;
+
+	req  = g_new0(struct profile_req, 1);
+	req->device = dev;
+	req->profile = profile;
+	req->cb = cb;
+
+	return req;
+}
+
+static void profile_cb(struct audio_device *dev, int err, void *data)
+{
+	struct profile_req *req = data;
+
+	if (req->cb)
+		req->cb(req->profile, req->device, err);
+
+	g_free(req);
+}
+
+static int a2dp_source_connect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = source_connect(audio_dev, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
+static int a2dp_source_disconnect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = source_disconnect(audio_dev, FALSE, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
 static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
 {
 	adp->ref++;
@@ -335,6 +421,10 @@ static struct btd_profile a2dp_source_profile = {
 	.device_probe	= a2dp_source_probe,
 	.device_remove	= audio_remove,
 
+	.auto_connect	= true,
+	.connect	= a2dp_source_connect,
+	.disconnect	= a2dp_source_disconnect,
+
 	.adapter_probe	= a2dp_source_server_probe,
 };
 
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 4/6] sink: Add profile .connect and .disconnect
  2012-11-21 12:10 [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Luiz Augusto von Dentz
  2012-11-21 12:10 ` [PATCH BlueZ 2/6] audio: Split A2DP into two btd_profile Luiz Augusto von Dentz
  2012-11-21 12:10 ` [PATCH BlueZ 3/6] source: Add profile .connect and .disconnect Luiz Augusto von Dentz
@ 2012-11-21 12:10 ` Luiz Augusto von Dentz
  2012-11-21 12:10 ` [PATCH BlueZ 5/6] control: Expose internal connection API Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth

From: Mikel Astiz <mikel.astiz@bmw-carit.de>

Add the connection and disconnection hooks to the a2dp_sink btd_profile.
---
 profiles/audio/manager.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index eaae018..dad46a9 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -262,6 +262,62 @@ static int a2dp_source_disconnect(struct btd_device *dev,
 	return 0;
 }
 
+static int a2dp_sink_connect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = sink_connect(audio_dev, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
+static int a2dp_sink_disconnect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = sink_disconnect(audio_dev, FALSE, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
 static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
 {
 	adp->ref++;
@@ -436,6 +492,10 @@ static struct btd_profile a2dp_sink_profile = {
 	.device_probe	= a2dp_sink_probe,
 	.device_remove	= audio_remove,
 
+	.auto_connect	= true,
+	.connect	= a2dp_sink_connect,
+	.disconnect	= a2dp_sink_disconnect,
+
 	.adapter_probe	= a2dp_sink_server_probe,
 };
 
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 5/6] control: Expose internal connection API
  2012-11-21 12:10 [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2012-11-21 12:10 ` [PATCH BlueZ 4/6] sink: " Luiz Augusto von Dentz
@ 2012-11-21 12:10 ` Luiz Augusto von Dentz
  2012-11-21 12:10 ` [PATCH BlueZ 6/6] control: Add profile .connect and .disconnect Luiz Augusto von Dentz
  2012-11-21 12:37 ` [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Johan Hedberg
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Separate the D-Bus code from the internal connection handling code,
exposing an internal API in case some internal codepath/plugin is
interested in using it.
---
 profiles/audio/control.c | 118 ++++++++++++++++++++++++++++++++++++-----------
 profiles/audio/control.h |   4 ++
 2 files changed, 96 insertions(+), 26 deletions(-)

diff --git a/profiles/audio/control.c b/profiles/audio/control.c
index 1620128..b2bfb0a 100644
--- a/profiles/audio/control.c
+++ b/profiles/audio/control.c
@@ -61,12 +61,28 @@
 
 static unsigned int avctp_id = 0;
 
+struct pending_request {
+	audio_device_cb cb;
+	void *data;
+	unsigned int id;
+};
+
 struct control {
 	struct avctp *session;
 	gboolean target;
-	DBusMessage *connect;
+	struct pending_request *connect;
 };
 
+static void pending_request_free(struct audio_device *dev,
+					struct pending_request *pending,
+					int err)
+{
+	if (pending->cb)
+		pending->cb(dev, err, pending->data);
+
+	g_free(pending);
+}
+
 static void state_changed(struct audio_device *dev, avctp_state_t old_state,
 				avctp_state_t new_state, void *user_data)
 {
@@ -79,11 +95,7 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
 		control->session = NULL;
 
 		if (control->connect) {
-			DBusMessage *reply = btd_error_failed(control->connect,
-							"Unable to connect");
-
-			g_dbus_send_message(btd_get_dbus_connection(), reply);
-			dbus_message_unref(control->connect);
+			pending_request_free(dev, control->connect, -EIO);
 			control->connect = NULL;
 		}
 
@@ -105,9 +117,7 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
 		break;
 	case AVCTP_STATE_CONNECTED:
 		if (control->connect) {
-			g_dbus_send_reply(conn, control->connect,
-							DBUS_TYPE_INVALID);
-			dbus_message_unref(control->connect);
+			pending_request_free(dev, control->connect, 0);
 			control->connect = NULL;
 		}
 
@@ -143,41 +153,97 @@ static DBusMessage *control_is_connected(DBusConnection *conn,
 	return reply;
 }
 
-static DBusMessage *control_connect(DBusConnection *conn, DBusMessage *msg,
-								void *data)
+int control_connect(struct audio_device *dev, audio_device_cb cb, void *data)
 {
-	struct audio_device *device = data;
-	struct control *control = device->control;
+	struct control *control = dev->control;
+	struct pending_request *pending;
 
 	if (control->session)
-		return btd_error_already_connected(msg);
+		return -EALREADY;
 
 	if (!control->target)
-		return btd_error_not_supported(msg);
+		return -ENOTSUP;
 
 	if (control->connect)
-		return btd_error_in_progress(msg);
+		return -EINPROGRESS;
 
-	control->session = avctp_connect(&device->src, &device->dst);
+	control->session = avctp_connect(&dev->src, &dev->dst);
 	if (!control->session)
-		return btd_error_failed(msg, "Unable to connect");
+		return -EIO;
 
-	control->connect = dbus_message_ref(msg);
+	pending = g_new0(struct pending_request, 1);
+	pending->cb = cb;
+	pending->data = data;
+	control->connect = pending;
 
-	return NULL;
+	return 0;
 }
 
-static DBusMessage *control_disconnect(DBusConnection *conn, DBusMessage *msg,
+static void generic_cb(struct audio_device *dev, int err, void *data)
+{
+	DBusMessage *msg = data;
+	DBusMessage *reply;
+
+	if (err < 0) {
+		reply = btd_error_failed(msg, strerror(-err));
+		g_dbus_send_message(btd_get_dbus_connection(), reply);
+		dbus_message_unref(msg);
+		return;
+	}
+
+	g_dbus_send_reply(btd_get_dbus_connection(), msg, DBUS_TYPE_INVALID);
+
+	dbus_message_unref(msg);
+}
+
+static DBusMessage *connect_control(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
 	struct audio_device *device = data;
-	struct control *control = device->control;
+	int err;
+
+	err = control_connect(device, generic_cb, msg);
+	if (err < 0)
+		return btd_error_failed(msg, strerror(-err));
+
+	dbus_message_ref(msg);
+
+	return NULL;
+}
+
+int control_disconnect(struct audio_device *dev, audio_device_cb cb,
+								void *data)
+{
+	struct control *control = dev->control;
 
 	if (!control->session)
-		return btd_error_not_connected(msg);
+		return -ENOTCONN;
+
+	/* cancel pending connect */
+	if (control->connect) {
+		pending_request_free(dev, control->connect, -ECANCELED);
+		control->connect = NULL;
+	}
 
 	avctp_disconnect(control->session);
 
+	if (cb)
+		cb(dev, 0, data);
+
+	return 0;
+
+}
+
+static DBusMessage *disconnect_control(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	struct audio_device *device = data;
+	int err;
+
+	err = control_disconnect(device, NULL, NULL);
+	if (err < 0)
+		return btd_error_failed(msg, strerror(-err));
+
 	return dbus_message_new_method_return(msg);
 }
 
@@ -259,8 +325,8 @@ static const GDBusMethodTable control_methods[] = {
 	{ GDBUS_DEPRECATED_METHOD("IsConnected",
 				NULL, GDBUS_ARGS({ "connected", "b" }),
 				control_is_connected) },
-	{ GDBUS_ASYNC_METHOD("Connect", NULL, NULL, control_connect) },
-	{ GDBUS_METHOD("Disconnect", NULL, NULL, control_disconnect) },
+	{ GDBUS_ASYNC_METHOD("Connect", NULL, NULL, connect_control) },
+	{ GDBUS_METHOD("Disconnect", NULL, NULL, disconnect_control) },
 	{ GDBUS_METHOD("Play", NULL, NULL, control_play) },
 	{ GDBUS_METHOD("Pause", NULL, NULL, control_pause) },
 	{ GDBUS_METHOD("Stop", NULL, NULL, control_stop) },
@@ -294,7 +360,7 @@ static void path_unregister(void *data)
 		avctp_disconnect(control->session);
 
 	if (control->connect)
-		dbus_message_unref(control->connect);
+		pending_request_free(dev, control->connect, -ECANCELED);
 
 	g_free(control);
 	dev->control = NULL;
diff --git a/profiles/audio/control.h b/profiles/audio/control.h
index 5f4f728..800a151 100644
--- a/profiles/audio/control.h
+++ b/profiles/audio/control.h
@@ -28,3 +28,7 @@ struct control *control_init(struct audio_device *dev, GSList *uuids);
 void control_update(struct control *control, GSList *uuids);
 void control_unregister(struct audio_device *dev);
 gboolean control_is_active(struct audio_device *dev);
+
+int control_connect(struct audio_device *dev, audio_device_cb cb, void *data);
+int control_disconnect(struct audio_device *dev, audio_device_cb cb,
+								void *data);
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 6/6] control: Add profile .connect and .disconnect
  2012-11-21 12:10 [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Luiz Augusto von Dentz
                   ` (3 preceding siblings ...)
  2012-11-21 12:10 ` [PATCH BlueZ 5/6] control: Expose internal connection API Luiz Augusto von Dentz
@ 2012-11-21 12:10 ` Luiz Augusto von Dentz
  2012-11-21 12:37 ` [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Johan Hedberg
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Add the connection and disconnection hooks to the avrcp btd_profile.
---
 profiles/audio/manager.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index dad46a9..714489a 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -318,6 +318,62 @@ static int a2dp_sink_disconnect(struct btd_device *dev,
 	return 0;
 }
 
+static int avrcp_control_connect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = control_connect(audio_dev, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
+static int avrcp_control_disconnect(struct btd_device *dev,
+						struct btd_profile *profile,
+						btd_profile_cb cb)
+{
+	const gchar *path = device_get_path(dev);
+	struct audio_device *audio_dev;
+	struct profile_req *req;
+	int err;
+
+	DBG("path %s", path);
+
+	audio_dev = get_audio_dev(dev);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	req = new_profile_request(dev, profile, cb);
+
+	err = control_disconnect(audio_dev, profile_cb, req);
+	if (err < 0) {
+		g_free(req);
+		return err;
+	}
+
+	return 0;
+}
+
 static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
 {
 	adp->ref++;
@@ -506,6 +562,10 @@ static struct btd_profile avrcp_profile = {
 	.device_probe	= avrcp_probe,
 	.device_remove	= audio_remove,
 
+	.auto_connect	= true,
+	.connect	= avrcp_control_connect,
+	.disconnect	= avrcp_control_disconnect,
+
 	.adapter_probe	= avrcp_server_probe,
 	.adapter_remove = avrcp_server_remove,
 };
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect
  2012-11-21 12:10 [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Luiz Augusto von Dentz
                   ` (4 preceding siblings ...)
  2012-11-21 12:10 ` [PATCH BlueZ 6/6] control: Add profile .connect and .disconnect Luiz Augusto von Dentz
@ 2012-11-21 12:37 ` Johan Hedberg
  5 siblings, 0 replies; 7+ messages in thread
From: Johan Hedberg @ 2012-11-21 12:37 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

On Wed, Nov 21, 2012, Luiz Augusto von Dentz wrote:
> We should with higher priority first.
> ---
>  src/device.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

All patches in this set have been applied. Thanks.

Johan

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-11-21 12:37 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-21 12:10 [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Luiz Augusto von Dentz
2012-11-21 12:10 ` [PATCH BlueZ 2/6] audio: Split A2DP into two btd_profile Luiz Augusto von Dentz
2012-11-21 12:10 ` [PATCH BlueZ 3/6] source: Add profile .connect and .disconnect Luiz Augusto von Dentz
2012-11-21 12:10 ` [PATCH BlueZ 4/6] sink: " Luiz Augusto von Dentz
2012-11-21 12:10 ` [PATCH BlueZ 5/6] control: Expose internal connection API Luiz Augusto von Dentz
2012-11-21 12:10 ` [PATCH BlueZ 6/6] control: Add profile .connect and .disconnect Luiz Augusto von Dentz
2012-11-21 12:37 ` [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect Johan Hedberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).