All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel
@ 2014-03-07 20:23 Marcin Kraglak
  2014-03-07 20:23 ` [PATCH 2/5] android/handsfree: Add support for handling incoming SCO connections Marcin Kraglak
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Marcin Kraglak @ 2014-03-07 20:23 UTC (permalink / raw)
  To: linux-bluetooth

Return false if listen failed.
---
 android/handsfree.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index dc5c73d..fa27f10 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -1192,7 +1192,7 @@ static bool enable_hfp_ag(void)
 	if (!hfp_server) {
 		error("Failed to listen on Handsfree rfcomm: %s", err->message);
 		g_error_free(err);
-		goto failed;
+		return false;
 	}
 
 	rec = hfp_ag_record();
-- 
1.8.3.1


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

* [PATCH 2/5] android/handsfree: Add support for handling incoming SCO connections
  2014-03-07 20:23 [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel Marcin Kraglak
@ 2014-03-07 20:23 ` Marcin Kraglak
  2014-03-10 11:48   ` Szymon Janc
  2014-03-07 20:23 ` [PATCH 3/5] android/handsfree: Handle connect_audio call Marcin Kraglak
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Marcin Kraglak @ 2014-03-07 20:23 UTC (permalink / raw)
  To: linux-bluetooth

This adds support for accepting SCO connections from remote devices.
---
 android/handsfree.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 148 insertions(+)

diff --git a/android/handsfree.c b/android/handsfree.c
index fa27f10..40f3652 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -83,11 +83,14 @@ static const struct indicator inds_defaults[] = {
 static struct {
 	bdaddr_t bdaddr;
 	uint8_t state;
+	uint8_t audio_state;
 	uint32_t features;
 	bool indicators_enabled;
 	struct indicator inds[IND_COUNT];
 	bool hsp;
 	struct hfp_gw *gw;
+	GIOChannel *sco;
+	guint sco_watch;
 } device;
 
 static bdaddr_t adapter_addr;
@@ -99,6 +102,8 @@ static GIOChannel *hfp_server = NULL;
 static uint32_t hsp_record_id = 0;
 static GIOChannel *hsp_server = NULL;
 
+static GIOChannel *sco_server = NULL;
+
 static void device_set_state(uint8_t state)
 {
 	struct hal_ev_handsfree_conn_state ev;
@@ -119,6 +124,26 @@ static void device_set_state(uint8_t state)
 				HAL_EV_HANDSFREE_CONN_STATE, sizeof(ev), &ev);
 }
 
+static void device_set_audio_state(uint8_t state)
+{
+	struct hal_ev_handsfree_audio_state ev;
+	char address[18];
+
+	if (device.audio_state == state)
+		return;
+
+	device.audio_state = state;
+
+	ba2str(&device.bdaddr, address);
+	DBG("device %s audio state %u", address, state);
+
+	bdaddr2android(&device.bdaddr, ev.bdaddr);
+	ev.state = state;
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+				HAL_EV_HANDSFREE_AUDIO_STATE, sizeof(ev), &ev);
+}
+
 static void device_init(const bdaddr_t *bdaddr)
 {
 	bacpy(&device.bdaddr, bdaddr);
@@ -137,6 +162,19 @@ static void device_cleanup(void)
 
 	device_set_state(HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTED);
 
+	if (device.sco_watch) {
+		g_source_remove(device.sco_watch);
+		device.sco_watch = 0;
+	}
+
+	if (device.sco) {
+		g_io_channel_shutdown(device.sco, TRUE, NULL);
+		g_io_channel_unref(device.sco);
+		device.sco = NULL;
+	}
+
+	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED);
+
 	memset(&device, 0, sizeof(device));
 }
 
@@ -739,6 +777,42 @@ failed:
 					HAL_OP_HANDSFREE_DISCONNECT, status);
 }
 
+static gboolean sco_watch_cb(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
+{
+	g_source_remove(device.sco_watch);
+	device.sco_watch = 0;
+
+	g_io_channel_shutdown(device.sco, TRUE, NULL);
+	g_io_channel_unref(device.sco);
+	device.sco = NULL;
+
+	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED);
+
+	return FALSE;
+}
+
+static void connect_sco_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+	if (err) {
+		uint8_t status;
+
+		error("SCO: connect failed (%s)", err->message);
+		status = HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED;
+		device_set_audio_state(status);
+
+		return;
+	}
+
+	g_io_channel_set_close_on_unref(chan, TRUE);
+
+	device.sco = g_io_channel_ref(chan);
+	device.sco_watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+							sco_watch_cb, NULL);
+
+	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTED);
+}
+
 static void handle_connect_audio(const void *buf, uint16_t len)
 {
 	DBG("");
@@ -1044,6 +1118,46 @@ static sdp_record_t *headset_ag_record(void)
 	return record;
 }
 
+static void confirm_sco_cb(GIOChannel *chan, gpointer user_data)
+{
+	char address[18];
+	bdaddr_t bdaddr;
+	GError *err = NULL;
+
+	if (device.sco)
+		goto drop;
+
+	bt_io_get(chan, &err,
+			BT_IO_OPT_DEST, address,
+			BT_IO_OPT_DEST_BDADDR, &bdaddr,
+			BT_IO_OPT_INVALID);
+	if (err) {
+		error("SCO: confirm failed (%s)", err->message);
+		g_error_free(err);
+		goto drop;
+	}
+
+	DBG("incoming SCO connection from %s", address);
+
+	if (device.state != HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED ||
+			bacmp(&device.bdaddr, &bdaddr)) {
+		error("SCO: connection from %s rejected", address);
+		goto drop;
+	}
+
+	if (!bt_io_accept(chan, connect_sco_cb, NULL, NULL, NULL)) {
+		error("SCO: failed to accept connection");
+		goto drop;
+	}
+
+	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTING);
+
+	return;
+
+drop:
+	g_io_channel_shutdown(chan, TRUE, NULL);
+}
+
 static bool enable_hsp_ag(void)
 {
 	sdp_record_t *rec;
@@ -1233,6 +1347,33 @@ static void cleanup_hfp_ag(void)
 	}
 }
 
+static bool enable_sco_server(void)
+{
+	GError *err = NULL;
+
+	sco_server = bt_io_listen(NULL, confirm_sco_cb, NULL, NULL, &err,
+				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+				BT_IO_OPT_INVALID);
+	if (!sco_server) {
+		error("Failed to listen on SCO: %s", err->message);
+		g_error_free(err);
+		cleanup_hsp_ag();
+		cleanup_hfp_ag();
+		return false;
+	}
+
+	return true;
+}
+
+static void disable_sco_server(void)
+{
+	if (sco_server) {
+		g_io_channel_shutdown(sco_server, TRUE, NULL);
+		g_io_channel_unref(sco_server);
+		sco_server = NULL;
+	}
+}
+
 bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 {
 	DBG("mode 0x%x", mode);
@@ -1247,6 +1388,12 @@ bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 		return false;
 	}
 
+	if (!enable_sco_server()) {
+		cleanup_hsp_ag();
+		cleanup_hfp_ag();
+		return false;
+	}
+
 	hal_ipc = ipc;
 	ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
 						G_N_ELEMENTS(cmd_handlers));
@@ -1263,4 +1410,5 @@ void bt_handsfree_unregister(void)
 
 	cleanup_hfp_ag();
 	cleanup_hsp_ag();
+	disable_sco_server();
 }
-- 
1.8.3.1


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

* [PATCH 3/5] android/handsfree: Handle connect_audio call
  2014-03-07 20:23 [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel Marcin Kraglak
  2014-03-07 20:23 ` [PATCH 2/5] android/handsfree: Add support for handling incoming SCO connections Marcin Kraglak
@ 2014-03-07 20:23 ` Marcin Kraglak
  2014-03-07 20:23 ` [PATCH 4/5] android/handsfree: Handle disconnect_audio call Marcin Kraglak
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Marcin Kraglak @ 2014-03-07 20:23 UTC (permalink / raw)
  To: linux-bluetooth

This change handle connect_audio and start connect procedure.
---
 android/handsfree.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 40f3652..a3c684e 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -813,12 +813,53 @@ static void connect_sco_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTED);
 }
 
+static bool connect_sco(void)
+{
+	GIOChannel *io;
+	GError *gerr = NULL;
+
+	if (device.sco)
+		return false;
+
+	io = bt_io_connect(connect_sco_cb, NULL, NULL, &gerr,
+				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+				BT_IO_OPT_DEST_BDADDR, &device.bdaddr,
+				BT_IO_OPT_INVALID);
+
+	if (!io) {
+		error("SCO: unable to connect: %s", gerr->message);
+		g_error_free(gerr);
+		return false;
+	}
+
+	g_io_channel_unref(io);
+
+	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTING);
+
+	return true;
+}
+
 static void handle_connect_audio(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_connect_audio *cmd = buf;
+	bdaddr_t bdaddr;
+	uint8_t status;
+
 	DBG("");
 
+	android2bdaddr(cmd->bdaddr, &bdaddr);
+
+	if (device.audio_state != HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED ||
+			bacmp(&device.bdaddr, &bdaddr)) {
+		status = HAL_STATUS_FAILED;
+		goto done;
+	}
+
+	status = connect_sco() ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
+
+done:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
-			HAL_OP_HANDSFREE_CONNECT_AUDIO, HAL_STATUS_FAILED);
+				HAL_OP_HANDSFREE_CONNECT_AUDIO, status);
 }
 
 static void handle_disconnect_audio(const void *buf, uint16_t len)
-- 
1.8.3.1


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

* [PATCH 4/5] android/handsfree: Handle disconnect_audio call
  2014-03-07 20:23 [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel Marcin Kraglak
  2014-03-07 20:23 ` [PATCH 2/5] android/handsfree: Add support for handling incoming SCO connections Marcin Kraglak
  2014-03-07 20:23 ` [PATCH 3/5] android/handsfree: Handle connect_audio call Marcin Kraglak
@ 2014-03-07 20:23 ` Marcin Kraglak
  2014-03-07 20:23 ` [PATCH 5/5] android/handsfree: Remove empty line Marcin Kraglak
  2014-03-08 19:00 ` [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel Szymon Janc
  4 siblings, 0 replies; 8+ messages in thread
From: Marcin Kraglak @ 2014-03-07 20:23 UTC (permalink / raw)
  To: linux-bluetooth

This change adds handling of disconnect_audio call.
---
 android/handsfree.c | 38 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index a3c684e..69de670 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -839,6 +839,27 @@ static bool connect_sco(void)
 	return true;
 }
 
+static bool disconnect_sco(void)
+{
+	if (!device.sco)
+		return false;
+
+	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTING);
+
+	if (device.sco_watch) {
+		g_source_remove(device.sco_watch);
+		device.sco_watch = 0;
+	}
+
+	g_io_channel_shutdown(device.sco, TRUE, NULL);
+	g_io_channel_unref(device.sco);
+	device.sco = NULL;
+
+	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED);
+
+	return true;
+}
+
 static void handle_connect_audio(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_handsfree_connect_audio *cmd = buf;
@@ -864,10 +885,25 @@ done:
 
 static void handle_disconnect_audio(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_disconnect_audio *cmd = buf;
+	bdaddr_t bdaddr;
+	uint8_t status;
+
 	DBG("");
 
+	android2bdaddr(cmd->bdaddr, &bdaddr);
+
+	if (device.audio_state != HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTED ||
+			bacmp(&device.bdaddr, &bdaddr)) {
+		status = HAL_STATUS_FAILED;
+		goto done;
+	}
+
+	status = disconnect_sco() ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
+
+done:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
-			HAL_OP_HANDSFREE_DISCONNECT_AUDIO, HAL_STATUS_FAILED);
+				HAL_OP_HANDSFREE_DISCONNECT_AUDIO, status);
 }
 
 static void handle_start_vr(const void *buf, uint16_t len)
-- 
1.8.3.1


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

* [PATCH 5/5] android/handsfree: Remove empty line
  2014-03-07 20:23 [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel Marcin Kraglak
                   ` (2 preceding siblings ...)
  2014-03-07 20:23 ` [PATCH 4/5] android/handsfree: Handle disconnect_audio call Marcin Kraglak
@ 2014-03-07 20:23 ` Marcin Kraglak
  2014-03-08 19:01   ` Szymon Janc
  2014-03-08 19:00 ` [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel Szymon Janc
  4 siblings, 1 reply; 8+ messages in thread
From: Marcin Kraglak @ 2014-03-07 20:23 UTC (permalink / raw)
  To: linux-bluetooth

---
 android/handsfree.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 69de670..1b42142 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -475,7 +475,6 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	hfp_gw_set_command_handler(device.gw, at_command_handler, NULL, NULL);
 	hfp_gw_set_disconnect_handler(device.gw, disconnect_watch, NULL, NULL);
 
-
 	if (device.hsp) {
 		register_post_slc_at();
 		device_set_state(HAL_EV_HANDSFREE_CONN_STATE_CONNECTED);
-- 
1.8.3.1


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

* Re: [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel
  2014-03-07 20:23 [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel Marcin Kraglak
                   ` (3 preceding siblings ...)
  2014-03-07 20:23 ` [PATCH 5/5] android/handsfree: Remove empty line Marcin Kraglak
@ 2014-03-08 19:00 ` Szymon Janc
  4 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-03-08 19:00 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth

Hi Marcin,

On Friday 07 of March 2014 21:23:16 Marcin Kraglak wrote:
> Return false if listen failed.
> ---
>  android/handsfree.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/android/handsfree.c b/android/handsfree.c
> index dc5c73d..fa27f10 100644
> --- a/android/handsfree.c
> +++ b/android/handsfree.c
> @@ -1192,7 +1192,7 @@ static bool enable_hfp_ag(void)
>  	if (!hfp_server) {
>  		error("Failed to listen on Handsfree rfcomm: %s", err->message);
>  		g_error_free(err);
> -		goto failed;
> +		return false;
>  	}
> 
>  	rec = hfp_ag_record();

This patch is now pushed, thanks.

-- 
BR
Szymon Janc

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

* Re: [PATCH 5/5] android/handsfree: Remove empty line
  2014-03-07 20:23 ` [PATCH 5/5] android/handsfree: Remove empty line Marcin Kraglak
@ 2014-03-08 19:01   ` Szymon Janc
  0 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-03-08 19:01 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth

Hi Marcin,

On Friday 07 of March 2014 21:23:20 Marcin Kraglak wrote:
> ---
>  android/handsfree.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/android/handsfree.c b/android/handsfree.c
> index 69de670..1b42142 100644
> --- a/android/handsfree.c
> +++ b/android/handsfree.c
> @@ -475,7 +475,6 @@ static void connect_cb(GIOChannel *chan, GError *err,
> gpointer user_data) hfp_gw_set_command_handler(device.gw,
> at_command_handler, NULL, NULL); hfp_gw_set_disconnect_handler(device.gw,
> disconnect_watch, NULL, NULL);
> 
> -
>  	if (device.hsp) {
>  		register_post_slc_at();
>  		device_set_state(HAL_EV_HANDSFREE_CONN_STATE_CONNECTED);

This patch is now applied, thanks.

-- 
BR
Szymon Janc

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

* Re: [PATCH 2/5] android/handsfree: Add support for handling incoming SCO connections
  2014-03-07 20:23 ` [PATCH 2/5] android/handsfree: Add support for handling incoming SCO connections Marcin Kraglak
@ 2014-03-10 11:48   ` Szymon Janc
  0 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-03-10 11:48 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth

Hi Marcin,

On Friday 07 of March 2014 21:23:17 Marcin Kraglak wrote:
> This adds support for accepting SCO connections from remote devices.
> ---
>  android/handsfree.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 148 insertions(+)
> 
> diff --git a/android/handsfree.c b/android/handsfree.c
> index fa27f10..40f3652 100644
> --- a/android/handsfree.c
> +++ b/android/handsfree.c
> @@ -83,11 +83,14 @@ static const struct indicator inds_defaults[] = {
>  static struct {
>  	bdaddr_t bdaddr;
>  	uint8_t state;
> +	uint8_t audio_state;
>  	uint32_t features;
>  	bool indicators_enabled;
>  	struct indicator inds[IND_COUNT];
>  	bool hsp;
>  	struct hfp_gw *gw;
> +	GIOChannel *sco;
> +	guint sco_watch;
>  } device;
>  
>  static bdaddr_t adapter_addr;
> @@ -99,6 +102,8 @@ static GIOChannel *hfp_server = NULL;
>  static uint32_t hsp_record_id = 0;
>  static GIOChannel *hsp_server = NULL;
>  
> +static GIOChannel *sco_server = NULL;
> +
>  static void device_set_state(uint8_t state)
>  {
>  	struct hal_ev_handsfree_conn_state ev;
> @@ -119,6 +124,26 @@ static void device_set_state(uint8_t state)
>  				HAL_EV_HANDSFREE_CONN_STATE, sizeof(ev), &ev);
>  }
>  
> +static void device_set_audio_state(uint8_t state)
> +{
> +	struct hal_ev_handsfree_audio_state ev;
> +	char address[18];
> +
> +	if (device.audio_state == state)
> +		return;
> +
> +	device.audio_state = state;
> +
> +	ba2str(&device.bdaddr, address);
> +	DBG("device %s audio state %u", address, state);
> +
> +	bdaddr2android(&device.bdaddr, ev.bdaddr);
> +	ev.state = state;
> +
> +	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> +				HAL_EV_HANDSFREE_AUDIO_STATE, sizeof(ev), &ev);
> +}
> +
>  static void device_init(const bdaddr_t *bdaddr)
>  {
>  	bacpy(&device.bdaddr, bdaddr);
> @@ -137,6 +162,19 @@ static void device_cleanup(void)
>  
>  	device_set_state(HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTED);
>  
> +	if (device.sco_watch) {
> +		g_source_remove(device.sco_watch);
> +		device.sco_watch = 0;
> +	}
> +
> +	if (device.sco) {
> +		g_io_channel_shutdown(device.sco, TRUE, NULL);
> +		g_io_channel_unref(device.sco);
> +		device.sco = NULL;
> +	}
> +
> +	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED);
> +
>  	memset(&device, 0, sizeof(device));
>  }
>  
> @@ -739,6 +777,42 @@ failed:
>  					HAL_OP_HANDSFREE_DISCONNECT, status);
>  }
>  
> +static gboolean sco_watch_cb(GIOChannel *chan, GIOCondition cond,
> +							gpointer user_data)
> +{
> +	g_source_remove(device.sco_watch);
> +	device.sco_watch = 0;
> +
> +	g_io_channel_shutdown(device.sco, TRUE, NULL);
> +	g_io_channel_unref(device.sco);
> +	device.sco = NULL;
> +
> +	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED);
> +
> +	return FALSE;
> +}
> +
> +static void connect_sco_cb(GIOChannel *chan, GError *err, gpointer user_data)
> +{
> +	if (err) {
> +		uint8_t status;
> +
> +		error("SCO: connect failed (%s)", err->message);
> +		status = HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED;
> +		device_set_audio_state(status);
> +
> +		return;
> +	}
> +
> +	g_io_channel_set_close_on_unref(chan, TRUE);
> +
> +	device.sco = g_io_channel_ref(chan);
> +	device.sco_watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
> +							sco_watch_cb, NULL);
> +
> +	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTED);
> +}
> +
>  static void handle_connect_audio(const void *buf, uint16_t len)
>  {
>  	DBG("");
> @@ -1044,6 +1118,46 @@ static sdp_record_t *headset_ag_record(void)
>  	return record;
>  }
>  
> +static void confirm_sco_cb(GIOChannel *chan, gpointer user_data)
> +{
> +	char address[18];
> +	bdaddr_t bdaddr;
> +	GError *err = NULL;
> +
> +	if (device.sco)
> +		goto drop;
> +
> +	bt_io_get(chan, &err,
> +			BT_IO_OPT_DEST, address,
> +			BT_IO_OPT_DEST_BDADDR, &bdaddr,
> +			BT_IO_OPT_INVALID);
> +	if (err) {
> +		error("SCO: confirm failed (%s)", err->message);
> +		g_error_free(err);
> +		goto drop;
> +	}
> +
> +	DBG("incoming SCO connection from %s", address);
> +
> +	if (device.state != HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED ||
> +			bacmp(&device.bdaddr, &bdaddr)) {
> +		error("SCO: connection from %s rejected", address);
> +		goto drop;
> +	}
> +
> +	if (!bt_io_accept(chan, connect_sco_cb, NULL, NULL, NULL)) {
> +		error("SCO: failed to accept connection");
> +		goto drop;
> +	}
> +
> +	device_set_audio_state(HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTING);
> +
> +	return;
> +
> +drop:
> +	g_io_channel_shutdown(chan, TRUE, NULL);
> +}
> +
>  static bool enable_hsp_ag(void)
>  {
>  	sdp_record_t *rec;
> @@ -1233,6 +1347,33 @@ static void cleanup_hfp_ag(void)
>  	}
>  }
>  
> +static bool enable_sco_server(void)
> +{
> +	GError *err = NULL;
> +
> +	sco_server = bt_io_listen(NULL, confirm_sco_cb, NULL, NULL, &err,
> +				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
> +				BT_IO_OPT_INVALID);
> +	if (!sco_server) {
> +		error("Failed to listen on SCO: %s", err->message);
> +		g_error_free(err);
> +		cleanup_hsp_ag();
> +		cleanup_hfp_ag();
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +static void disable_sco_server(void)
> +{
> +	if (sco_server) {
> +		g_io_channel_shutdown(sco_server, TRUE, NULL);
> +		g_io_channel_unref(sco_server);
> +		sco_server = NULL;
> +	}
> +}
> +
>  bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
>  {
>  	DBG("mode 0x%x", mode);
> @@ -1247,6 +1388,12 @@ bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
>  		return false;
>  	}
>  
> +	if (!enable_sco_server()) {
> +		cleanup_hsp_ag();
> +		cleanup_hfp_ag();
> +		return false;
> +	}
> +
>  	hal_ipc = ipc;
>  	ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
>  						G_N_ELEMENTS(cmd_handlers));
> @@ -1263,4 +1410,5 @@ void bt_handsfree_unregister(void)
>  
>  	cleanup_hfp_ag();
>  	cleanup_hsp_ag();
> +	disable_sco_server();
>  }
> 

Patches 2, 3 and 4 are now also upstream (with minor fixed we discussed
offline), thanks.

-- 
Best regards, 
Szymon Janc

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

end of thread, other threads:[~2014-03-10 11:48 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-07 20:23 [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel Marcin Kraglak
2014-03-07 20:23 ` [PATCH 2/5] android/handsfree: Add support for handling incoming SCO connections Marcin Kraglak
2014-03-10 11:48   ` Szymon Janc
2014-03-07 20:23 ` [PATCH 3/5] android/handsfree: Handle connect_audio call Marcin Kraglak
2014-03-07 20:23 ` [PATCH 4/5] android/handsfree: Handle disconnect_audio call Marcin Kraglak
2014-03-07 20:23 ` [PATCH 5/5] android/handsfree: Remove empty line Marcin Kraglak
2014-03-08 19:01   ` Szymon Janc
2014-03-08 19:00 ` [PATCH 1/5] android/handsfree: Fix possible g_io_channel_shutdown() on NULL channel Szymon Janc

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.