linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/6] Add support for HandsfreeGateway to Media
@ 2011-09-06 13:55 Frédéric Dalleau
  2011-09-06 13:55 ` [PATCH v5 1/6] Fix disconnect SCO at same time than RFCOMM Frédéric Dalleau
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: Frédéric Dalleau @ 2011-09-06 13:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

Hi,

The first patch in this series fix the issue remaining in v2.
It also fix a crash because the request_stream callback was run synchronously.
After that various fixes.

Changes from v4 :
Patch 2: take Luiz comment into account and create error domain for
gateway
Patch 4: also make sure gateway is set back to disconnected state in case of
authorize errors.

Best regards,
Frédéric

Frédéric Dalleau (6):
  Fix disconnect SCO at same time than RFCOMM
  Fix asynchronously run request stream cb
  Fix state to "playing" on SCO establishment
  Set state to "connecting" on connection requested
  Fix reference count issue in incoming connections
  Check all states before allowing gw connection

 audio/gateway.c |  194 ++++++++++++++++++++++++++++++++++++++-----------------
 audio/gateway.h |   12 +++-
 audio/manager.c |    8 ++-
 audio/unix.c    |   13 +---
 4 files changed, 155 insertions(+), 72 deletions(-)


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

* [PATCH v5 1/6] Fix disconnect SCO at same time than RFCOMM
  2011-09-06 13:55 [PATCH v5 0/6] Add support for HandsfreeGateway to Media Frédéric Dalleau
@ 2011-09-06 13:55 ` Frédéric Dalleau
  2011-09-21  8:41   ` Luiz Augusto von Dentz
  2011-09-06 13:55 ` [PATCH v5 2/6] Fix asynchronously run request stream cb Frédéric Dalleau
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Frédéric Dalleau @ 2011-09-06 13:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

If RFCOMM disconnects, SCO should be disconnected too.
---
 audio/gateway.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/audio/gateway.c b/audio/gateway.c
index 142b12e..59c91dd 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -222,15 +222,10 @@ static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 static gboolean rfcomm_disconnect_cb(GIOChannel *chan, GIOCondition cond,
 			struct audio_device *dev)
 {
-	struct gateway *gw = dev->gateway;
-
 	if (cond & G_IO_NVAL)
 		return FALSE;
 
-	g_io_channel_shutdown(gw->rfcomm, TRUE, NULL);
-	g_io_channel_unref(gw->rfcomm);
-	gw->rfcomm = NULL;
-	change_state(dev, GATEWAY_STATE_DISCONNECTED);
+	gateway_close(dev);
 
 	return FALSE;
 }
-- 
1.7.1


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

* [PATCH v5 2/6] Fix asynchronously run request stream cb
  2011-09-06 13:55 [PATCH v5 0/6] Add support for HandsfreeGateway to Media Frédéric Dalleau
  2011-09-06 13:55 ` [PATCH v5 1/6] Fix disconnect SCO at same time than RFCOMM Frédéric Dalleau
@ 2011-09-06 13:55 ` Frédéric Dalleau
  2011-09-21  8:45   ` Luiz Augusto von Dentz
  2011-09-06 13:55 ` [PATCH v5 3/6] Fix state to "playing" on SCO establishment Frédéric Dalleau
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Frédéric Dalleau @ 2011-09-06 13:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

Cancel pending callback if stream is canceled
Asynchronously run gateway_config_stream cb
Remove occurences of sco_start_cb
---
 audio/gateway.c |  148 +++++++++++++++++++++++++++++++++++++++----------------
 audio/gateway.h |   11 ++++-
 audio/unix.c    |   13 ++---
 3 files changed, 120 insertions(+), 52 deletions(-)

diff --git a/audio/gateway.c b/audio/gateway.c
index 59c91dd..4c28721 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -60,13 +60,18 @@ struct hf_agent {
 	guint watch;	/* Disconnect watch */
 };
 
+struct connect_cb {
+	unsigned int id;
+	gateway_stream_cb_t cb;
+	void *cb_data;
+};
+
 struct gateway {
 	gateway_state_t state;
 	GIOChannel *rfcomm;
 	GIOChannel *sco;
 	GIOChannel *incoming;
-	gateway_stream_cb_t sco_start_cb;
-	void *sco_start_cb_data;
+	GSList *callbacks;
 	struct hf_agent *agent;
 	DBusMessage *msg;
 	int version;
@@ -83,6 +88,11 @@ static GSList *gateway_callbacks = NULL;
 
 int gateway_close(struct audio_device *device);
 
+GQuark gateway_error_quark(void)
+{
+	return g_quark_from_static_string("gateway-error-quark");
+}
+
 static const char *state2str(gateway_state_t state)
 {
 	switch (state) {
@@ -180,6 +190,41 @@ static gboolean agent_sendfd(struct hf_agent *agent, int fd,
 	return TRUE;
 }
 
+static unsigned int connect_cb_new(struct gateway *gw,
+					gateway_stream_cb_t func,
+					void *user_data)
+{
+	struct connect_cb *cb;
+	static unsigned int free_cb_id = 1;
+
+	if (!func)
+		return 0;
+
+	cb = g_new(struct connect_cb, 1);
+
+	cb->cb = func;
+	cb->cb_data = user_data;
+	cb->id = free_cb_id++;
+
+	gw->callbacks = g_slist_append(gw->callbacks, cb);
+
+	return cb->id;
+}
+
+static void run_connect_cb(struct audio_device *dev, GError *err)
+{
+	struct gateway *gw = dev->gateway;
+	GSList *l;
+
+	for (l = gw->callbacks; l != NULL; l = l->next) {
+		struct connect_cb *cb = l->data;
+		cb->cb(dev, err, cb->cb_data);
+	}
+
+	g_slist_free_full(gw->callbacks, g_free);
+	gw->callbacks = NULL;
+}
+
 static gboolean sco_io_cb(GIOChannel *chan, GIOCondition cond,
 			struct audio_device *dev)
 {
@@ -206,9 +251,6 @@ static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 
 	gw->sco = g_io_channel_ref(chan);
 
-	if (gw->sco_start_cb)
-		gw->sco_start_cb(dev, err, gw->sco_start_cb_data);
-
 	if (err) {
 		error("sco_connect_cb(): %s", err->message);
 		gateway_close(dev);
@@ -217,6 +259,8 @@ static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 
 	g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 				(GIOFunc) sco_io_cb, dev);
+
+	run_connect_cb(dev, NULL);
 }
 
 static gboolean rfcomm_disconnect_cb(GIOChannel *chan, GIOCondition cond,
@@ -270,8 +314,6 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
 
 	if (err) {
 		error("connect(): %s", err->message);
-		if (gw->sco_start_cb)
-			gw->sco_start_cb(dev, err, gw->sco_start_cb_data);
 		goto fail;
 	}
 
@@ -307,7 +349,7 @@ fail:
 		g_dbus_send_message(dev->conn, reply);
 	}
 
-	change_state(dev, GATEWAY_STATE_DISCONNECTED);
+	gateway_close(dev);
 }
 
 static int get_remote_profile_version(sdp_record_t *rec)
@@ -452,7 +494,6 @@ static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
 				BT_IO_OPT_INVALID);
 	if (!io) {
 		error("Unable to connect: %s", gerr->message);
-		gateway_close(dev);
 		goto fail;
 	}
 
@@ -468,16 +509,10 @@ fail:
 		g_dbus_send_message(dev->conn, reply);
 	}
 
-	change_state(dev, GATEWAY_STATE_DISCONNECTED);
-
-	if (!gerr)
-		g_set_error(&gerr, BT_IO_ERROR, BT_IO_ERROR_FAILED,
-				"connect: %s (%d)", strerror(-err), -err);
-
-	if (gw->sco_start_cb)
-		gw->sco_start_cb(dev, gerr, gw->sco_start_cb_data);
+	gateway_close(dev);
 
-	g_error_free(gerr);
+	if (gerr)
+		g_error_free(gerr);
 }
 
 static int get_records(struct audio_device *device)
@@ -510,6 +545,7 @@ static DBusMessage *ag_connect(DBusConnection *conn, DBusMessage *msg,
 
 int gateway_close(struct audio_device *device)
 {
+	GError *gerr = NULL;
 	struct gateway *gw = device->gateway;
 	int sock;
 
@@ -526,11 +562,13 @@ int gateway_close(struct audio_device *device)
 		g_io_channel_shutdown(gw->sco, TRUE, NULL);
 		g_io_channel_unref(gw->sco);
 		gw->sco = NULL;
-		gw->sco_start_cb = NULL;
-		gw->sco_start_cb_data = NULL;
 	}
 
 	change_state(device, GATEWAY_STATE_DISCONNECTED);
+	g_set_error(&gerr, GATEWAY_ERROR,
+			GATEWAY_ERROR_DISCONNECTED, "Disconnected");
+	run_connect_cb(device, gerr);
+	g_error_free(gerr);
 
 	return 0;
 }
@@ -759,22 +797,27 @@ void gateway_start_service(struct audio_device *dev)
 	}
 }
 
+static gboolean request_stream_cb(gpointer data)
+{
+	run_connect_cb(data, NULL);
+	return FALSE;
+}
+
 /* These are functions to be called from unix.c for audio system
  * ifaces (alsa, gstreamer, etc.) */
-gboolean gateway_request_stream(struct audio_device *dev,
+unsigned int gateway_request_stream(struct audio_device *dev,
 				gateway_stream_cb_t cb, void *user_data)
 {
 	struct gateway *gw = dev->gateway;
+	unsigned int id;
 	GError *err = NULL;
 	GIOChannel *io;
 
-	if (!gw->rfcomm) {
-		gw->sco_start_cb = cb;
-		gw->sco_start_cb_data = user_data;
+	id = connect_cb_new(gw, cb, user_data);
+
+	if (!gw->rfcomm)
 		get_records(dev);
-	} else if (!gw->sco) {
-		gw->sco_start_cb = cb;
-		gw->sco_start_cb_data = user_data;
+	else if (!gw->sco) {
 		io = bt_io_connect(BT_IO_SCO, sco_connect_cb, dev, NULL, &err,
 				BT_IO_OPT_SOURCE_BDADDR, &dev->src,
 				BT_IO_OPT_DEST_BDADDR, &dev->dst,
@@ -782,34 +825,53 @@ gboolean gateway_request_stream(struct audio_device *dev,
 		if (!io) {
 			error("%s", err->message);
 			g_error_free(err);
-			return FALSE;
+			return 0;
 		}
-	} else if (cb)
-		cb(dev, err, user_data);
+	} else
+		g_idle_add(request_stream_cb, dev);
 
-	return TRUE;
+	return id;
 }
 
-int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t sco_cb,
+int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t cb,
 				void *user_data)
 {
 	struct gateway *gw = dev->gateway;
+	unsigned int id;
 
-	if (!gw->rfcomm) {
-		gw->sco_start_cb = sco_cb;
-		gw->sco_start_cb_data = user_data;
-		return get_records(dev);
-	}
+	id = connect_cb_new(gw, cb, user_data);
 
-	if (sco_cb)
-		sco_cb(dev, NULL, user_data);
+	if (!gw->rfcomm)
+		get_records(dev);
+	else if (cb)
+		g_idle_add(request_stream_cb, dev);
 
-	return 0;
+	return id;
 }
 
 gboolean gateway_cancel_stream(struct audio_device *dev, unsigned int id)
 {
+	struct gateway *gw = dev->gateway;
+	GSList *l;
+	struct connect_cb *cb = NULL;
+
+	for (l = gw->callbacks; l != NULL; l = l->next) {
+		struct connect_cb *tmp = l->data;
+
+		if (tmp->id == id) {
+			cb = tmp;
+			break;
+		}
+	}
+
+	if (!cb)
+		return FALSE;
+
+	gw->callbacks = g_slist_remove(gw->callbacks, cb);
+	g_free(cb);
+
 	gateway_suspend_stream(dev);
+
 	return TRUE;
 }
 
@@ -825,6 +887,7 @@ int gateway_get_sco_fd(struct audio_device *dev)
 
 void gateway_suspend_stream(struct audio_device *dev)
 {
+	GError *gerr = NULL;
 	struct gateway *gw = dev->gateway;
 
 	if (!gw || !gw->sco)
@@ -833,8 +896,9 @@ void gateway_suspend_stream(struct audio_device *dev)
 	g_io_channel_shutdown(gw->sco, TRUE, NULL);
 	g_io_channel_unref(gw->sco);
 	gw->sco = NULL;
-	gw->sco_start_cb = NULL;
-	gw->sco_start_cb_data = NULL;
+	g_set_error(&gerr, GATEWAY_ERROR, GATEWAY_ERROR_SUSPENDED, "Suspended");
+	run_connect_cb(dev, gerr);
+	g_error_free(gerr);
 	change_state(dev, GATEWAY_STATE_CONNECTED);
 }
 
diff --git a/audio/gateway.h b/audio/gateway.h
index 2dca32a..a8ed2f2 100644
--- a/audio/gateway.h
+++ b/audio/gateway.h
@@ -38,6 +38,15 @@ typedef enum {
 	GATEWAY_LOCK_WRITE = 1 << 1,
 } gateway_lock_t;
 
+typedef enum {
+	GATEWAY_ERROR_DISCONNECTED,
+	GATEWAY_ERROR_SUSPENDED,
+} gateway_error_t;
+
+#define GATEWAY_ERROR gateway_error_quark()
+
+GQuark gateway_error_quark(void);
+
 typedef void (*gateway_state_cb) (struct audio_device *dev,
 					gateway_state_t old_state,
 					gateway_state_t new_state,
@@ -52,7 +61,7 @@ gboolean gateway_is_connected(struct audio_device *dev);
 int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io);
 int gateway_connect_sco(struct audio_device *dev, GIOChannel *chan);
 void gateway_start_service(struct audio_device *device);
-gboolean gateway_request_stream(struct audio_device *dev,
+unsigned int gateway_request_stream(struct audio_device *dev,
 			gateway_stream_cb_t cb, void *user_data);
 int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t cb,
 			void *user_data);
diff --git a/audio/unix.c b/audio/unix.c
index 1e0ab30..c2d6d4a 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -1045,11 +1045,8 @@ static void start_config(struct audio_device *dev, struct unix_client *client)
 		client->cancel = headset_cancel_stream;
 		break;
 	case TYPE_GATEWAY:
-		if (gateway_config_stream(dev, gateway_setup_complete, client) >= 0) {
-			client->cancel = gateway_cancel_stream;
-			id = 1;
-		} else
-			id = 0;
+		id = gateway_config_stream(dev, gateway_setup_complete, client);
+		client->cancel = gateway_cancel_stream;
 		break;
 
 	default:
@@ -1118,10 +1115,8 @@ static void start_resume(struct audio_device *dev, struct unix_client *client)
 		break;
 
 	case TYPE_GATEWAY:
-		if (gateway_request_stream(dev, gateway_resume_complete, client))
-			id = 1;
-		else
-			id = 0;
+		id = gateway_request_stream(dev, gateway_resume_complete,
+						client);
 		client->cancel = gateway_cancel_stream;
 		break;
 
-- 
1.7.1


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

* [PATCH v5 3/6] Fix state to "playing" on SCO establishment
  2011-09-06 13:55 [PATCH v5 0/6] Add support for HandsfreeGateway to Media Frédéric Dalleau
  2011-09-06 13:55 ` [PATCH v5 1/6] Fix disconnect SCO at same time than RFCOMM Frédéric Dalleau
  2011-09-06 13:55 ` [PATCH v5 2/6] Fix asynchronously run request stream cb Frédéric Dalleau
@ 2011-09-06 13:55 ` Frédéric Dalleau
  2011-09-21  8:42   ` Luiz Augusto von Dentz
  2011-09-06 13:55 ` [PATCH v5 4/6] Set state to "connecting" on connection requested Frédéric Dalleau
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Frédéric Dalleau @ 2011-09-06 13:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 audio/gateway.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/audio/gateway.c b/audio/gateway.c
index 4c28721..b788de7 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -260,6 +260,7 @@ static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 				(GIOFunc) sco_io_cb, dev);
 
+	change_state(dev, GATEWAY_STATE_PLAYING);
 	run_connect_cb(dev, NULL);
 }
 
-- 
1.7.1


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

* [PATCH v5 4/6] Set state to "connecting" on connection requested
  2011-09-06 13:55 [PATCH v5 0/6] Add support for HandsfreeGateway to Media Frédéric Dalleau
                   ` (2 preceding siblings ...)
  2011-09-06 13:55 ` [PATCH v5 3/6] Fix state to "playing" on SCO establishment Frédéric Dalleau
@ 2011-09-06 13:55 ` Frédéric Dalleau
  2011-09-21  8:46   ` Luiz Augusto von Dentz
  2011-09-06 13:55 ` [PATCH v5 5/6] Fix reference count issue in incoming connections Frédéric Dalleau
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Frédéric Dalleau @ 2011-09-06 13:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

Make sure that state changes to disconnected on
errors (authorization refused, disconnect, sdp)
This change will become necessary when
integrating the Audio interface which rely on
state change to confirm that connection
has started successfully.
---
 audio/gateway.c |   29 +++++++++++++++++++----------
 audio/manager.c |    6 ++++--
 2 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/audio/gateway.c b/audio/gateway.c
index b788de7..945477e 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -323,8 +323,6 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
 		goto fail;
 	}
 
-	change_state(dev, GATEWAY_STATE_CONNECTING);
-
 	sk = g_io_channel_unix_get_fd(chan);
 
 	gw->rfcomm = g_io_channel_ref(chan);
@@ -387,17 +385,23 @@ static void get_incoming_record_cb(sdp_list_t *recs, int err,
 	if (err < 0) {
 		error("Unable to get service record: %s (%d)", strerror(-err),
 					-err);
-		return;
+		goto fail;
 	}
 
 	if (!recs || !recs->data) {
 		error("No records found");
-		return;
+		goto fail;
 	}
 
 	gw->version = get_remote_profile_version(recs->data);
-	if (gw->version > 0)
-		rfcomm_connect_cb(gw->incoming, gerr, dev);
+	if (gw->version == 0)
+		goto fail;
+
+	rfcomm_connect_cb(gw->incoming, gerr, dev);
+	return;
+
+fail:
+	gateway_close(dev);
 }
 
 static void unregister_incoming(gpointer user_data)
@@ -423,8 +427,11 @@ static void rfcomm_incoming_cb(GIOChannel *chan, GError *err,
 	sdp_uuid16_create(&uuid, HANDSFREE_AGW_SVCLASS_ID);
 	if (bt_search_service(&dev->src, &dev->dst, &uuid,
 						get_incoming_record_cb, dev,
-						unregister_incoming) < 0)
-		unregister_incoming(dev);
+						unregister_incoming) == 0)
+		return;
+
+	unregister_incoming(dev);
+	gateway_close(dev);
 }
 
 static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
@@ -499,8 +506,6 @@ static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
 	}
 
 	g_io_channel_unref(io);
-
-	change_state(dev, GATEWAY_STATE_CONNECTING);
 	return;
 
 fail:
@@ -520,6 +525,7 @@ static int get_records(struct audio_device *device)
 {
 	uuid_t uuid;
 
+	change_state(device, GATEWAY_STATE_CONNECTING);
 	sdp_uuid16_create(&uuid, HANDSFREE_AGW_SVCLASS_ID);
 	return bt_search_service(&device->src, &device->dst, &uuid,
 				get_record_cb, device, NULL);
@@ -764,6 +770,8 @@ int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io)
 
 	dev->gateway->rfcomm = g_io_channel_ref(io);
 
+	change_state(dev, GATEWAY_STATE_CONNECTING);
+
 	return 0;
 }
 
@@ -795,6 +803,7 @@ void gateway_start_service(struct audio_device *dev)
 	if (!bt_io_accept(gw->rfcomm, rfcomm_incoming_cb, dev, NULL, &err)) {
 		error("bt_io_accept: %s", err->message);
 		g_error_free(err);
+		gateway_close(dev);
 	}
 }
 
diff --git a/audio/manager.c b/audio/manager.c
index 33b4f5f..b0a4aa1 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -544,9 +544,10 @@ static void gateway_auth_cb(DBusError *derr, void *user_data)
 {
 	struct audio_device *device = user_data;
 
-	if (derr && dbus_error_is_set(derr))
+	if (derr && dbus_error_is_set(derr)) {
 		error("Access denied: %s", derr->message);
-	else {
+		gateway_set_state(device, GATEWAY_STATE_DISCONNECTED);
+	} else {
 		char ag_address[18];
 
 		ba2str(&device->dst, ag_address);
@@ -605,6 +606,7 @@ static void hf_io_cb(GIOChannel *chan, gpointer data)
 						gateway_auth_cb, device);
 	if (perr < 0) {
 		DBG("Authorization denied!");
+		gateway_set_state(device, GATEWAY_STATE_DISCONNECTED);
 		goto drop;
 	}
 
-- 
1.7.1


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

* [PATCH v5 5/6] Fix reference count issue in incoming connections
  2011-09-06 13:55 [PATCH v5 0/6] Add support for HandsfreeGateway to Media Frédéric Dalleau
                   ` (3 preceding siblings ...)
  2011-09-06 13:55 ` [PATCH v5 4/6] Set state to "connecting" on connection requested Frédéric Dalleau
@ 2011-09-06 13:55 ` Frédéric Dalleau
  2011-09-21  8:47   ` Luiz Augusto von Dentz
  2011-09-06 13:55 ` [PATCH v5 6/6] Check all states before allowing gw connection Frédéric Dalleau
  2011-09-27  9:25 ` [PATCH v5 0/6] Add support for HandsfreeGateway to Media Johan Hedberg
  6 siblings, 1 reply; 14+ messages in thread
From: Frédéric Dalleau @ 2011-09-06 13:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

In case of incoming RFCOMM connection, manager
calls gateway_connect_rfcomm which already take
reference to GIOChannel, hence no need to take
another one.
---
 audio/gateway.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/audio/gateway.c b/audio/gateway.c
index 945477e..f3e6c6a 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -325,7 +325,8 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
 
 	sk = g_io_channel_unix_get_fd(chan);
 
-	gw->rfcomm = g_io_channel_ref(chan);
+	if (gw->rfcomm == NULL)
+		gw->rfcomm = g_io_channel_ref(chan);
 
 	ret = agent_sendfd(gw->agent, sk, newconnection_reply, dev);
 
-- 
1.7.1


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

* [PATCH v5 6/6] Check all states before allowing gw connection
  2011-09-06 13:55 [PATCH v5 0/6] Add support for HandsfreeGateway to Media Frédéric Dalleau
                   ` (4 preceding siblings ...)
  2011-09-06 13:55 ` [PATCH v5 5/6] Fix reference count issue in incoming connections Frédéric Dalleau
@ 2011-09-06 13:55 ` Frédéric Dalleau
  2011-09-21  8:54   ` Luiz Augusto von Dentz
  2011-09-27  9:25 ` [PATCH v5 0/6] Add support for HandsfreeGateway to Media Johan Hedberg
  6 siblings, 1 reply; 14+ messages in thread
From: Frédéric Dalleau @ 2011-09-06 13:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 audio/gateway.c |    6 ++++++
 audio/gateway.h |    1 +
 audio/manager.c |    2 +-
 3 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/audio/gateway.c b/audio/gateway.c
index f3e6c6a..f2b25d5 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -764,6 +764,12 @@ gboolean gateway_is_connected(struct audio_device *dev)
 			dev->gateway->state == GATEWAY_STATE_CONNECTED);
 }
 
+gboolean gateway_is_active(struct audio_device *dev)
+{
+	return (dev && dev->gateway &&
+			dev->gateway->state != GATEWAY_STATE_DISCONNECTED);
+}
+
 int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io)
 {
 	if (!io)
diff --git a/audio/gateway.h b/audio/gateway.h
index a8ed2f2..77f5787 100644
--- a/audio/gateway.h
+++ b/audio/gateway.h
@@ -57,6 +57,7 @@ typedef void (*gateway_stream_cb_t) (struct audio_device *dev, GError *err,
 void gateway_set_state(struct audio_device *dev, gateway_state_t new_state);
 void gateway_unregister(struct audio_device *dev);
 struct gateway *gateway_init(struct audio_device *device);
+gboolean gateway_is_active(struct audio_device *dev);
 gboolean gateway_is_connected(struct audio_device *dev);
 int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io);
 int gateway_connect_sco(struct audio_device *dev, GIOChannel *chan);
diff --git a/audio/manager.c b/audio/manager.c
index b0a4aa1..64a78e9 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -592,7 +592,7 @@ static void hf_io_cb(GIOChannel *chan, gpointer data)
 			goto drop;
 	}
 
-	if (gateway_is_connected(device)) {
+	if (gateway_is_active(device)) {
 		DBG("Refusing new connection since one already exists");
 		goto drop;
 	}
-- 
1.7.1


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

* Re: [PATCH v5 1/6] Fix disconnect SCO at same time than RFCOMM
  2011-09-06 13:55 ` [PATCH v5 1/6] Fix disconnect SCO at same time than RFCOMM Frédéric Dalleau
@ 2011-09-21  8:41   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2011-09-21  8:41 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth

Hi Frédéric,

2011/9/6 Frédéric Dalleau <frederic.dalleau@linux.intel.com>:
> If RFCOMM disconnects, SCO should be disconnected too.
> ---
>  audio/gateway.c |    7 +------
>  1 files changed, 1 insertions(+), 6 deletions(-)
>
> diff --git a/audio/gateway.c b/audio/gateway.c
> index 142b12e..59c91dd 100644
> --- a/audio/gateway.c
> +++ b/audio/gateway.c
> @@ -222,15 +222,10 @@ static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>  static gboolean rfcomm_disconnect_cb(GIOChannel *chan, GIOCondition cond,
>                        struct audio_device *dev)
>  {
> -       struct gateway *gw = dev->gateway;
> -
>        if (cond & G_IO_NVAL)
>                return FALSE;
>
> -       g_io_channel_shutdown(gw->rfcomm, TRUE, NULL);
> -       g_io_channel_unref(gw->rfcomm);
> -       gw->rfcomm = NULL;
> -       change_state(dev, GATEWAY_STATE_DISCONNECTED);
> +       gateway_close(dev);
>
>        return FALSE;
>  }
> --
> 1.7.1

Ack.

-- 
Luiz Augusto von Dentz

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

* Re: [PATCH v5 3/6] Fix state to "playing" on SCO establishment
  2011-09-06 13:55 ` [PATCH v5 3/6] Fix state to "playing" on SCO establishment Frédéric Dalleau
@ 2011-09-21  8:42   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2011-09-21  8:42 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth

Hi Frédéric,

2011/9/6 Frédéric Dalleau <frederic.dalleau@linux.intel.com>:
> ---
>  audio/gateway.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/audio/gateway.c b/audio/gateway.c
> index 4c28721..b788de7 100644
> --- a/audio/gateway.c
> +++ b/audio/gateway.c
> @@ -260,6 +260,7 @@ static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>        g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
>                                (GIOFunc) sco_io_cb, dev);
>
> +       change_state(dev, GATEWAY_STATE_PLAYING);
>        run_connect_cb(dev, NULL);
>  }
>
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Ack

-- 
Luiz Augusto von Dentz

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

* Re: [PATCH v5 2/6] Fix asynchronously run request stream cb
  2011-09-06 13:55 ` [PATCH v5 2/6] Fix asynchronously run request stream cb Frédéric Dalleau
@ 2011-09-21  8:45   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2011-09-21  8:45 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth

Hi Frédéric,

2011/9/6 Frédéric Dalleau <frederic.dalleau@linux.intel.com>:
> Cancel pending callback if stream is canceled
> Asynchronously run gateway_config_stream cb
> Remove occurences of sco_start_cb
> ---
>  audio/gateway.c |  148 +++++++++++++++++++++++++++++++++++++++----------------
>  audio/gateway.h |   11 ++++-
>  audio/unix.c    |   13 ++---
>  3 files changed, 120 insertions(+), 52 deletions(-)
>
> diff --git a/audio/gateway.c b/audio/gateway.c
> index 59c91dd..4c28721 100644
> --- a/audio/gateway.c
> +++ b/audio/gateway.c
> @@ -60,13 +60,18 @@ struct hf_agent {
>        guint watch;    /* Disconnect watch */
>  };
>
> +struct connect_cb {
> +       unsigned int id;
> +       gateway_stream_cb_t cb;
> +       void *cb_data;
> +};
> +
>  struct gateway {
>        gateway_state_t state;
>        GIOChannel *rfcomm;
>        GIOChannel *sco;
>        GIOChannel *incoming;
> -       gateway_stream_cb_t sco_start_cb;
> -       void *sco_start_cb_data;
> +       GSList *callbacks;
>        struct hf_agent *agent;
>        DBusMessage *msg;
>        int version;
> @@ -83,6 +88,11 @@ static GSList *gateway_callbacks = NULL;
>
>  int gateway_close(struct audio_device *device);
>
> +GQuark gateway_error_quark(void)
> +{
> +       return g_quark_from_static_string("gateway-error-quark");
> +}
> +
>  static const char *state2str(gateway_state_t state)
>  {
>        switch (state) {
> @@ -180,6 +190,41 @@ static gboolean agent_sendfd(struct hf_agent *agent, int fd,
>        return TRUE;
>  }
>
> +static unsigned int connect_cb_new(struct gateway *gw,
> +                                       gateway_stream_cb_t func,
> +                                       void *user_data)
> +{
> +       struct connect_cb *cb;
> +       static unsigned int free_cb_id = 1;
> +
> +       if (!func)
> +               return 0;
> +
> +       cb = g_new(struct connect_cb, 1);
> +
> +       cb->cb = func;
> +       cb->cb_data = user_data;
> +       cb->id = free_cb_id++;
> +
> +       gw->callbacks = g_slist_append(gw->callbacks, cb);
> +
> +       return cb->id;
> +}
> +
> +static void run_connect_cb(struct audio_device *dev, GError *err)
> +{
> +       struct gateway *gw = dev->gateway;
> +       GSList *l;
> +
> +       for (l = gw->callbacks; l != NULL; l = l->next) {
> +               struct connect_cb *cb = l->data;
> +               cb->cb(dev, err, cb->cb_data);
> +       }
> +
> +       g_slist_free_full(gw->callbacks, g_free);
> +       gw->callbacks = NULL;
> +}
> +
>  static gboolean sco_io_cb(GIOChannel *chan, GIOCondition cond,
>                        struct audio_device *dev)
>  {
> @@ -206,9 +251,6 @@ static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>
>        gw->sco = g_io_channel_ref(chan);
>
> -       if (gw->sco_start_cb)
> -               gw->sco_start_cb(dev, err, gw->sco_start_cb_data);
> -
>        if (err) {
>                error("sco_connect_cb(): %s", err->message);
>                gateway_close(dev);
> @@ -217,6 +259,8 @@ static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>
>        g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
>                                (GIOFunc) sco_io_cb, dev);
> +
> +       run_connect_cb(dev, NULL);
>  }
>
>  static gboolean rfcomm_disconnect_cb(GIOChannel *chan, GIOCondition cond,
> @@ -270,8 +314,6 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
>
>        if (err) {
>                error("connect(): %s", err->message);
> -               if (gw->sco_start_cb)
> -                       gw->sco_start_cb(dev, err, gw->sco_start_cb_data);
>                goto fail;
>        }
>
> @@ -307,7 +349,7 @@ fail:
>                g_dbus_send_message(dev->conn, reply);
>        }
>
> -       change_state(dev, GATEWAY_STATE_DISCONNECTED);
> +       gateway_close(dev);
>  }
>
>  static int get_remote_profile_version(sdp_record_t *rec)
> @@ -452,7 +494,6 @@ static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
>                                BT_IO_OPT_INVALID);
>        if (!io) {
>                error("Unable to connect: %s", gerr->message);
> -               gateway_close(dev);
>                goto fail;
>        }
>
> @@ -468,16 +509,10 @@ fail:
>                g_dbus_send_message(dev->conn, reply);
>        }
>
> -       change_state(dev, GATEWAY_STATE_DISCONNECTED);
> -
> -       if (!gerr)
> -               g_set_error(&gerr, BT_IO_ERROR, BT_IO_ERROR_FAILED,
> -                               "connect: %s (%d)", strerror(-err), -err);
> -
> -       if (gw->sco_start_cb)
> -               gw->sco_start_cb(dev, gerr, gw->sco_start_cb_data);
> +       gateway_close(dev);
>
> -       g_error_free(gerr);
> +       if (gerr)
> +               g_error_free(gerr);
>  }
>
>  static int get_records(struct audio_device *device)
> @@ -510,6 +545,7 @@ static DBusMessage *ag_connect(DBusConnection *conn, DBusMessage *msg,
>
>  int gateway_close(struct audio_device *device)
>  {
> +       GError *gerr = NULL;
>        struct gateway *gw = device->gateway;
>        int sock;
>
> @@ -526,11 +562,13 @@ int gateway_close(struct audio_device *device)
>                g_io_channel_shutdown(gw->sco, TRUE, NULL);
>                g_io_channel_unref(gw->sco);
>                gw->sco = NULL;
> -               gw->sco_start_cb = NULL;
> -               gw->sco_start_cb_data = NULL;
>        }
>
>        change_state(device, GATEWAY_STATE_DISCONNECTED);
> +       g_set_error(&gerr, GATEWAY_ERROR,
> +                       GATEWAY_ERROR_DISCONNECTED, "Disconnected");
> +       run_connect_cb(device, gerr);
> +       g_error_free(gerr);
>
>        return 0;
>  }
> @@ -759,22 +797,27 @@ void gateway_start_service(struct audio_device *dev)
>        }
>  }
>
> +static gboolean request_stream_cb(gpointer data)
> +{
> +       run_connect_cb(data, NULL);
> +       return FALSE;
> +}
> +
>  /* These are functions to be called from unix.c for audio system
>  * ifaces (alsa, gstreamer, etc.) */
> -gboolean gateway_request_stream(struct audio_device *dev,
> +unsigned int gateway_request_stream(struct audio_device *dev,
>                                gateway_stream_cb_t cb, void *user_data)
>  {
>        struct gateway *gw = dev->gateway;
> +       unsigned int id;
>        GError *err = NULL;
>        GIOChannel *io;
>
> -       if (!gw->rfcomm) {
> -               gw->sco_start_cb = cb;
> -               gw->sco_start_cb_data = user_data;
> +       id = connect_cb_new(gw, cb, user_data);
> +
> +       if (!gw->rfcomm)
>                get_records(dev);
> -       } else if (!gw->sco) {
> -               gw->sco_start_cb = cb;
> -               gw->sco_start_cb_data = user_data;
> +       else if (!gw->sco) {
>                io = bt_io_connect(BT_IO_SCO, sco_connect_cb, dev, NULL, &err,
>                                BT_IO_OPT_SOURCE_BDADDR, &dev->src,
>                                BT_IO_OPT_DEST_BDADDR, &dev->dst,
> @@ -782,34 +825,53 @@ gboolean gateway_request_stream(struct audio_device *dev,
>                if (!io) {
>                        error("%s", err->message);
>                        g_error_free(err);
> -                       return FALSE;
> +                       return 0;
>                }
> -       } else if (cb)
> -               cb(dev, err, user_data);
> +       } else
> +               g_idle_add(request_stream_cb, dev);
>
> -       return TRUE;
> +       return id;
>  }
>
> -int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t sco_cb,
> +int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t cb,
>                                void *user_data)
>  {
>        struct gateway *gw = dev->gateway;
> +       unsigned int id;
>
> -       if (!gw->rfcomm) {
> -               gw->sco_start_cb = sco_cb;
> -               gw->sco_start_cb_data = user_data;
> -               return get_records(dev);
> -       }
> +       id = connect_cb_new(gw, cb, user_data);
>
> -       if (sco_cb)
> -               sco_cb(dev, NULL, user_data);
> +       if (!gw->rfcomm)
> +               get_records(dev);
> +       else if (cb)
> +               g_idle_add(request_stream_cb, dev);
>
> -       return 0;
> +       return id;
>  }
>
>  gboolean gateway_cancel_stream(struct audio_device *dev, unsigned int id)
>  {
> +       struct gateway *gw = dev->gateway;
> +       GSList *l;
> +       struct connect_cb *cb = NULL;
> +
> +       for (l = gw->callbacks; l != NULL; l = l->next) {
> +               struct connect_cb *tmp = l->data;
> +
> +               if (tmp->id == id) {
> +                       cb = tmp;
> +                       break;
> +               }
> +       }
> +
> +       if (!cb)
> +               return FALSE;
> +
> +       gw->callbacks = g_slist_remove(gw->callbacks, cb);
> +       g_free(cb);
> +
>        gateway_suspend_stream(dev);
> +
>        return TRUE;
>  }
>
> @@ -825,6 +887,7 @@ int gateway_get_sco_fd(struct audio_device *dev)
>
>  void gateway_suspend_stream(struct audio_device *dev)
>  {
> +       GError *gerr = NULL;
>        struct gateway *gw = dev->gateway;
>
>        if (!gw || !gw->sco)
> @@ -833,8 +896,9 @@ void gateway_suspend_stream(struct audio_device *dev)
>        g_io_channel_shutdown(gw->sco, TRUE, NULL);
>        g_io_channel_unref(gw->sco);
>        gw->sco = NULL;
> -       gw->sco_start_cb = NULL;
> -       gw->sco_start_cb_data = NULL;
> +       g_set_error(&gerr, GATEWAY_ERROR, GATEWAY_ERROR_SUSPENDED, "Suspended");
> +       run_connect_cb(dev, gerr);
> +       g_error_free(gerr);
>        change_state(dev, GATEWAY_STATE_CONNECTED);
>  }
>
> diff --git a/audio/gateway.h b/audio/gateway.h
> index 2dca32a..a8ed2f2 100644
> --- a/audio/gateway.h
> +++ b/audio/gateway.h
> @@ -38,6 +38,15 @@ typedef enum {
>        GATEWAY_LOCK_WRITE = 1 << 1,
>  } gateway_lock_t;
>
> +typedef enum {
> +       GATEWAY_ERROR_DISCONNECTED,
> +       GATEWAY_ERROR_SUSPENDED,
> +} gateway_error_t;
> +
> +#define GATEWAY_ERROR gateway_error_quark()
> +
> +GQuark gateway_error_quark(void);
> +
>  typedef void (*gateway_state_cb) (struct audio_device *dev,
>                                        gateway_state_t old_state,
>                                        gateway_state_t new_state,
> @@ -52,7 +61,7 @@ gboolean gateway_is_connected(struct audio_device *dev);
>  int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io);
>  int gateway_connect_sco(struct audio_device *dev, GIOChannel *chan);
>  void gateway_start_service(struct audio_device *device);
> -gboolean gateway_request_stream(struct audio_device *dev,
> +unsigned int gateway_request_stream(struct audio_device *dev,
>                        gateway_stream_cb_t cb, void *user_data);
>  int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t cb,
>                        void *user_data);
> diff --git a/audio/unix.c b/audio/unix.c
> index 1e0ab30..c2d6d4a 100644
> --- a/audio/unix.c
> +++ b/audio/unix.c
> @@ -1045,11 +1045,8 @@ static void start_config(struct audio_device *dev, struct unix_client *client)
>                client->cancel = headset_cancel_stream;
>                break;
>        case TYPE_GATEWAY:
> -               if (gateway_config_stream(dev, gateway_setup_complete, client) >= 0) {
> -                       client->cancel = gateway_cancel_stream;
> -                       id = 1;
> -               } else
> -                       id = 0;
> +               id = gateway_config_stream(dev, gateway_setup_complete, client);
> +               client->cancel = gateway_cancel_stream;
>                break;
>
>        default:
> @@ -1118,10 +1115,8 @@ static void start_resume(struct audio_device *dev, struct unix_client *client)
>                break;
>
>        case TYPE_GATEWAY:
> -               if (gateway_request_stream(dev, gateway_resume_complete, client))
> -                       id = 1;
> -               else
> -                       id = 0;
> +               id = gateway_request_stream(dev, gateway_resume_complete,
> +                                               client);
>                client->cancel = gateway_cancel_stream;
>                break;
>
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Ack

-- 
Luiz Augusto von Dentz

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

* Re: [PATCH v5 4/6] Set state to "connecting" on connection requested
  2011-09-06 13:55 ` [PATCH v5 4/6] Set state to "connecting" on connection requested Frédéric Dalleau
@ 2011-09-21  8:46   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2011-09-21  8:46 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth

Hi Frédéric,

2011/9/6 Frédéric Dalleau <frederic.dalleau@linux.intel.com>:
> Make sure that state changes to disconnected on
> errors (authorization refused, disconnect, sdp)
> This change will become necessary when
> integrating the Audio interface which rely on
> state change to confirm that connection
> has started successfully.
> ---
>  audio/gateway.c |   29 +++++++++++++++++++----------
>  audio/manager.c |    6 ++++--
>  2 files changed, 23 insertions(+), 12 deletions(-)
>
> diff --git a/audio/gateway.c b/audio/gateway.c
> index b788de7..945477e 100644
> --- a/audio/gateway.c
> +++ b/audio/gateway.c
> @@ -323,8 +323,6 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
>                goto fail;
>        }
>
> -       change_state(dev, GATEWAY_STATE_CONNECTING);
> -
>        sk = g_io_channel_unix_get_fd(chan);
>
>        gw->rfcomm = g_io_channel_ref(chan);
> @@ -387,17 +385,23 @@ static void get_incoming_record_cb(sdp_list_t *recs, int err,
>        if (err < 0) {
>                error("Unable to get service record: %s (%d)", strerror(-err),
>                                        -err);
> -               return;
> +               goto fail;
>        }
>
>        if (!recs || !recs->data) {
>                error("No records found");
> -               return;
> +               goto fail;
>        }
>
>        gw->version = get_remote_profile_version(recs->data);
> -       if (gw->version > 0)
> -               rfcomm_connect_cb(gw->incoming, gerr, dev);
> +       if (gw->version == 0)
> +               goto fail;
> +
> +       rfcomm_connect_cb(gw->incoming, gerr, dev);
> +       return;
> +
> +fail:
> +       gateway_close(dev);
>  }
>
>  static void unregister_incoming(gpointer user_data)
> @@ -423,8 +427,11 @@ static void rfcomm_incoming_cb(GIOChannel *chan, GError *err,
>        sdp_uuid16_create(&uuid, HANDSFREE_AGW_SVCLASS_ID);
>        if (bt_search_service(&dev->src, &dev->dst, &uuid,
>                                                get_incoming_record_cb, dev,
> -                                               unregister_incoming) < 0)
> -               unregister_incoming(dev);
> +                                               unregister_incoming) == 0)
> +               return;
> +
> +       unregister_incoming(dev);
> +       gateway_close(dev);
>  }
>
>  static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
> @@ -499,8 +506,6 @@ static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
>        }
>
>        g_io_channel_unref(io);
> -
> -       change_state(dev, GATEWAY_STATE_CONNECTING);
>        return;
>
>  fail:
> @@ -520,6 +525,7 @@ static int get_records(struct audio_device *device)
>  {
>        uuid_t uuid;
>
> +       change_state(device, GATEWAY_STATE_CONNECTING);
>        sdp_uuid16_create(&uuid, HANDSFREE_AGW_SVCLASS_ID);
>        return bt_search_service(&device->src, &device->dst, &uuid,
>                                get_record_cb, device, NULL);
> @@ -764,6 +770,8 @@ int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io)
>
>        dev->gateway->rfcomm = g_io_channel_ref(io);
>
> +       change_state(dev, GATEWAY_STATE_CONNECTING);
> +
>        return 0;
>  }
>
> @@ -795,6 +803,7 @@ void gateway_start_service(struct audio_device *dev)
>        if (!bt_io_accept(gw->rfcomm, rfcomm_incoming_cb, dev, NULL, &err)) {
>                error("bt_io_accept: %s", err->message);
>                g_error_free(err);
> +               gateway_close(dev);
>        }
>  }
>
> diff --git a/audio/manager.c b/audio/manager.c
> index 33b4f5f..b0a4aa1 100644
> --- a/audio/manager.c
> +++ b/audio/manager.c
> @@ -544,9 +544,10 @@ static void gateway_auth_cb(DBusError *derr, void *user_data)
>  {
>        struct audio_device *device = user_data;
>
> -       if (derr && dbus_error_is_set(derr))
> +       if (derr && dbus_error_is_set(derr)) {
>                error("Access denied: %s", derr->message);
> -       else {
> +               gateway_set_state(device, GATEWAY_STATE_DISCONNECTED);
> +       } else {
>                char ag_address[18];
>
>                ba2str(&device->dst, ag_address);
> @@ -605,6 +606,7 @@ static void hf_io_cb(GIOChannel *chan, gpointer data)
>                                                gateway_auth_cb, device);
>        if (perr < 0) {
>                DBG("Authorization denied!");
> +               gateway_set_state(device, GATEWAY_STATE_DISCONNECTED);
>                goto drop;
>        }
>
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Ack

-- 
Luiz Augusto von Dentz

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

* Re: [PATCH v5 5/6] Fix reference count issue in incoming connections
  2011-09-06 13:55 ` [PATCH v5 5/6] Fix reference count issue in incoming connections Frédéric Dalleau
@ 2011-09-21  8:47   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2011-09-21  8:47 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth

Hi Frédéric,

2011/9/6 Frédéric Dalleau <frederic.dalleau@linux.intel.com>:
> In case of incoming RFCOMM connection, manager
> calls gateway_connect_rfcomm which already take
> reference to GIOChannel, hence no need to take
> another one.
> ---
>  audio/gateway.c |    3 ++-
>  1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/audio/gateway.c b/audio/gateway.c
> index 945477e..f3e6c6a 100644
> --- a/audio/gateway.c
> +++ b/audio/gateway.c
> @@ -325,7 +325,8 @@ static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
>
>        sk = g_io_channel_unix_get_fd(chan);
>
> -       gw->rfcomm = g_io_channel_ref(chan);
> +       if (gw->rfcomm == NULL)
> +               gw->rfcomm = g_io_channel_ref(chan);
>
>        ret = agent_sendfd(gw->agent, sk, newconnection_reply, dev);
>
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Ack

-- 
Luiz Augusto von Dentz

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

* Re: [PATCH v5 6/6] Check all states before allowing gw connection
  2011-09-06 13:55 ` [PATCH v5 6/6] Check all states before allowing gw connection Frédéric Dalleau
@ 2011-09-21  8:54   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2011-09-21  8:54 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth

Hi Frédéric,

2011/9/6 Frédéric Dalleau <frederic.dalleau@linux.intel.com>:
> ---
>  audio/gateway.c |    6 ++++++
>  audio/gateway.h |    1 +
>  audio/manager.c |    2 +-
>  3 files changed, 8 insertions(+), 1 deletions(-)
>
> diff --git a/audio/gateway.c b/audio/gateway.c
> index f3e6c6a..f2b25d5 100644
> --- a/audio/gateway.c
> +++ b/audio/gateway.c
> @@ -764,6 +764,12 @@ gboolean gateway_is_connected(struct audio_device *dev)
>                        dev->gateway->state == GATEWAY_STATE_CONNECTED);
>  }
>
> +gboolean gateway_is_active(struct audio_device *dev)
> +{
> +       return (dev && dev->gateway &&
> +                       dev->gateway->state != GATEWAY_STATE_DISCONNECTED);

How about changing this to something similar as headset_is_active, IMO
the caller should verify if the device has the gateway interface
otherwise it may generate duplicates checks and extra code.

> +}
> +
>  int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io)
>  {
>        if (!io)
> diff --git a/audio/gateway.h b/audio/gateway.h
> index a8ed2f2..77f5787 100644
> --- a/audio/gateway.h
> +++ b/audio/gateway.h
> @@ -57,6 +57,7 @@ typedef void (*gateway_stream_cb_t) (struct audio_device *dev, GError *err,
>  void gateway_set_state(struct audio_device *dev, gateway_state_t new_state);
>  void gateway_unregister(struct audio_device *dev);
>  struct gateway *gateway_init(struct audio_device *device);
> +gboolean gateway_is_active(struct audio_device *dev);
>  gboolean gateway_is_connected(struct audio_device *dev);
>  int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io);
>  int gateway_connect_sco(struct audio_device *dev, GIOChannel *chan);
> diff --git a/audio/manager.c b/audio/manager.c
> index b0a4aa1..64a78e9 100644
> --- a/audio/manager.c
> +++ b/audio/manager.c
> @@ -592,7 +592,7 @@ static void hf_io_cb(GIOChannel *chan, gpointer data)
>                        goto drop;
>        }
>
> -       if (gateway_is_connected(device)) {
> +       if (gateway_is_active(device)) {
>                DBG("Refusing new connection since one already exists");
>                goto drop;
>        }
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



-- 
Luiz Augusto von Dentz

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

* Re: [PATCH v5 0/6] Add support for HandsfreeGateway to Media
  2011-09-06 13:55 [PATCH v5 0/6] Add support for HandsfreeGateway to Media Frédéric Dalleau
                   ` (5 preceding siblings ...)
  2011-09-06 13:55 ` [PATCH v5 6/6] Check all states before allowing gw connection Frédéric Dalleau
@ 2011-09-27  9:25 ` Johan Hedberg
  6 siblings, 0 replies; 14+ messages in thread
From: Johan Hedberg @ 2011-09-27  9:25 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth

Hi Frédéric,

On Tue, Sep 06, 2011, Frédéric Dalleau wrote:
> The first patch in this series fix the issue remaining in v2.
> It also fix a crash because the request_stream callback was run synchronously.
> After that various fixes.
> 
> Changes from v4 :
> Patch 2: take Luiz comment into account and create error domain for
> gateway
> Patch 4: also make sure gateway is set back to disconnected state in case of
> authorize errors.
> 
> Best regards,
> Frédéric
> 
> Frédéric Dalleau (6):
>   Fix disconnect SCO at same time than RFCOMM
>   Fix asynchronously run request stream cb
>   Fix state to "playing" on SCO establishment
>   Set state to "connecting" on connection requested
>   Fix reference count issue in incoming connections
>   Check all states before allowing gw connection
> 
>  audio/gateway.c |  194 ++++++++++++++++++++++++++++++++++++++-----------------
>  audio/gateway.h |   12 +++-
>  audio/manager.c |    8 ++-
>  audio/unix.c    |   13 +---
>  4 files changed, 155 insertions(+), 72 deletions(-)

Patches 1-5 have been applied. Thanks.

Johan

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

end of thread, other threads:[~2011-09-27  9:25 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-06 13:55 [PATCH v5 0/6] Add support for HandsfreeGateway to Media Frédéric Dalleau
2011-09-06 13:55 ` [PATCH v5 1/6] Fix disconnect SCO at same time than RFCOMM Frédéric Dalleau
2011-09-21  8:41   ` Luiz Augusto von Dentz
2011-09-06 13:55 ` [PATCH v5 2/6] Fix asynchronously run request stream cb Frédéric Dalleau
2011-09-21  8:45   ` Luiz Augusto von Dentz
2011-09-06 13:55 ` [PATCH v5 3/6] Fix state to "playing" on SCO establishment Frédéric Dalleau
2011-09-21  8:42   ` Luiz Augusto von Dentz
2011-09-06 13:55 ` [PATCH v5 4/6] Set state to "connecting" on connection requested Frédéric Dalleau
2011-09-21  8:46   ` Luiz Augusto von Dentz
2011-09-06 13:55 ` [PATCH v5 5/6] Fix reference count issue in incoming connections Frédéric Dalleau
2011-09-21  8:47   ` Luiz Augusto von Dentz
2011-09-06 13:55 ` [PATCH v5 6/6] Check all states before allowing gw connection Frédéric Dalleau
2011-09-21  8:54   ` Luiz Augusto von Dentz
2011-09-27  9:25 ` [PATCH v5 0/6] Add support for HandsfreeGateway to Media 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).