* [PATCH v2 2/7] shared: Minor code style fixes in GLib based IO
2014-02-22 21:09 [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling Szymon Janc
@ 2014-02-22 21:09 ` Szymon Janc
2014-02-22 21:09 ` [PATCH v2 3/7] shared: Add support for disconnect handler to mainloop " Szymon Janc
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-02-22 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
src/shared/io-glib.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/shared/io-glib.c b/src/shared/io-glib.c
index 5490fc0..76f5a44 100644
--- a/src/shared/io-glib.c
+++ b/src/shared/io-glib.c
@@ -195,6 +195,7 @@ bool io_set_read_handler(struct io *io, io_callback_func_t callback,
io->read_destroy = destroy;
io->read_data = user_data;
+
done:
io->read_callback = callback;
@@ -256,6 +257,7 @@ bool io_set_write_handler(struct io *io, io_callback_func_t callback,
io->write_destroy = destroy;
io->write_data = user_data;
+
done:
io->write_callback = callback;
--
1.9.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 3/7] shared: Add support for disconnect handler to mainloop based IO
2014-02-22 21:09 [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling Szymon Janc
2014-02-22 21:09 ` [PATCH v2 2/7] shared: Minor code style fixes in GLib based IO Szymon Janc
@ 2014-02-22 21:09 ` Szymon Janc
2014-02-22 21:09 ` [PATCH v2 4/7] shared: Add support for disconnect handler in HFP Szymon Janc
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-02-22 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
---
src/shared/io-mainloop.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/src/shared/io-mainloop.c b/src/shared/io-mainloop.c
index d84d8d2..3fe1a88 100644
--- a/src/shared/io-mainloop.c
+++ b/src/shared/io-mainloop.c
@@ -42,6 +42,9 @@ struct io {
io_callback_func_t write_callback;
io_destroy_func_t write_destroy;
void *write_data;
+ io_callback_func_t disconnect_callback;
+ io_destroy_func_t disconnect_destroy;
+ void *disconnect_data;
};
static struct io *io_ref(struct io *io)
@@ -75,6 +78,9 @@ static void io_cleanup(void *user_data)
if (io->read_destroy)
io->read_destroy(io->read_data);
+ if (io->disconnect_destroy)
+ io->disconnect_destroy(io->disconnect_data);
+
if (io->close_on_destroy)
close(io->fd);
@@ -122,6 +128,21 @@ static void io_callback(int fd, uint32_t events, void *user_data)
mainloop_modify_fd(io->fd, io->events);
}
}
+
+ if ((events & EPOLLRDHUP) && io->disconnect_callback) {
+ if (!io->disconnect_callback(io, io->disconnect_data)) {
+ if (io->disconnect_destroy)
+ io->disconnect_destroy(io->disconnect_data);
+
+ io->disconnect_callback = NULL;
+ io->disconnect_destroy = NULL;
+ io->disconnect_data = NULL;
+
+ io->events &= ~EPOLLRDHUP;
+
+ mainloop_modify_fd(io->fd, io->events);
+ }
+ }
}
struct io *io_new(int fd)
@@ -246,5 +267,30 @@ bool io_set_write_handler(struct io *io, io_callback_func_t callback,
bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
void *user_data, io_destroy_func_t destroy)
{
- return false;
+ uint32_t events;
+
+ if (!io || io->fd < 0)
+ return false;
+
+ if (io->disconnect_destroy)
+ io->disconnect_destroy(io->disconnect_data);
+
+ if (callback)
+ events = io->events | EPOLLRDHUP;
+ else
+ events = io->events & ~EPOLLRDHUP;
+
+ io->disconnect_callback = callback;
+ io->disconnect_destroy = destroy;
+ io->disconnect_data = user_data;
+
+ if (events == io->events)
+ return true;
+
+ if (mainloop_modify_fd(io->fd, events) < 0)
+ return false;
+
+ io->events = events;
+
+ return true;
}
--
1.9.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 4/7] shared: Add support for disconnect handler in HFP
2014-02-22 21:09 [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling Szymon Janc
2014-02-22 21:09 ` [PATCH v2 2/7] shared: Minor code style fixes in GLib based IO Szymon Janc
2014-02-22 21:09 ` [PATCH v2 3/7] shared: Add support for disconnect handler to mainloop " Szymon Janc
@ 2014-02-22 21:09 ` Szymon Janc
2014-02-22 21:09 ` [PATCH v2 5/7] shared: Add support for shutdown to IO Szymon Janc
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-02-22 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
---
src/shared/hfp.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/shared/hfp.h | 6 ++++++
2 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index 09fbe3e..98408ca 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -51,6 +51,13 @@ struct hfp_gw {
hfp_debug_func_t debug_callback;
hfp_destroy_func_t debug_destroy;
void *debug_data;
+
+ hfp_disconnect_func_t disconnect_callback;
+ hfp_destroy_func_t disconnect_destroy;
+ void *disconnect_data;
+
+ bool in_disconnect;
+ bool destroyed;
};
static void write_watch_destroy(void *user_data)
@@ -227,6 +234,7 @@ void hfp_gw_unref(struct hfp_gw *hfp)
io_set_write_handler(hfp->io, NULL, NULL, NULL);
io_set_read_handler(hfp->io, NULL, NULL, NULL);
+ io_set_disconnect_handler(hfp->io, NULL, NULL, NULL);
io_destroy(hfp->io);
hfp->io = NULL;
@@ -242,7 +250,12 @@ void hfp_gw_unref(struct hfp_gw *hfp)
ringbuf_free(hfp->write_buf);
hfp->write_buf = NULL;
- free(hfp);
+ if (!hfp->in_disconnect) {
+ free(hfp);
+ return;
+ }
+
+ hfp->destroyed = true;
}
static void read_tracing(const void *buf, size_t count, void *user_data)
@@ -391,3 +404,54 @@ bool hfp_gw_set_command_handler(struct hfp_gw *hfp,
return true;
}
+
+static void disconnect_watch_destroy(void *user_data)
+{
+ struct hfp_gw *hfp = user_data;
+
+ if (hfp->disconnect_destroy)
+ hfp->disconnect_destroy(hfp->disconnect_data);
+
+ if (hfp->destroyed)
+ free(hfp);
+}
+
+static bool io_disconnected(struct io *io, void *user_data)
+{
+ struct hfp_gw *hfp = user_data;
+
+ hfp->in_disconnect = true;
+
+ if (hfp->disconnect_callback)
+ hfp->disconnect_callback(hfp->disconnect_data);
+
+ hfp->in_disconnect = false;
+
+ return false;
+}
+
+bool hfp_gw_set_disconnect_handler(struct hfp_gw *hfp,
+ hfp_disconnect_func_t callback,
+ void *user_data,
+ hfp_destroy_func_t destroy)
+{
+ if (!hfp)
+ return false;
+
+ if (hfp->disconnect_destroy)
+ hfp->disconnect_destroy(hfp->disconnect_data);
+
+ if (!io_set_disconnect_handler(hfp->io, io_disconnected, hfp,
+ disconnect_watch_destroy)) {
+ hfp->disconnect_callback = NULL;
+ hfp->disconnect_destroy = NULL;
+ hfp->disconnect_data = NULL;
+ return false;
+ }
+
+ hfp->disconnect_callback = callback;
+ hfp->disconnect_destroy = destroy;
+ hfp->disconnect_data = user_data;
+
+ return true;
+}
diff --git a/src/shared/hfp.h b/src/shared/hfp.h
index 836b166..6bb51bc 100644
--- a/src/shared/hfp.h
+++ b/src/shared/hfp.h
@@ -64,6 +64,7 @@ typedef void (*hfp_destroy_func_t)(void *user_data);
typedef void (*hfp_debug_func_t)(const char *str, void *user_data);
typedef void (*hfp_command_func_t)(const char *command, void *user_data);
+typedef void (*hfp_disconnect_func_t)(void *user_data);
struct hfp_gw;
@@ -86,3 +87,8 @@ bool hfp_gw_send_info(struct hfp_gw *hfp, const char *format, ...)
bool hfp_gw_set_command_handler(struct hfp_gw *hfp,
hfp_command_func_t callback,
void *user_data, hfp_destroy_func_t destroy);
+
+bool hfp_gw_set_disconnect_handler(struct hfp_gw *hfp,
+ hfp_disconnect_func_t callback,
+ void *user_data,
+ hfp_destroy_func_t destroy);
--
1.9.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 5/7] shared: Add support for shutdown to IO
2014-02-22 21:09 [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling Szymon Janc
` (2 preceding siblings ...)
2014-02-22 21:09 ` [PATCH v2 4/7] shared: Add support for disconnect handler in HFP Szymon Janc
@ 2014-02-22 21:09 ` Szymon Janc
2014-02-22 21:09 ` [PATCH v2 6/7] shared: Add support for local disconnect to HFP Szymon Janc
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-02-22 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
This allows to locally shutdown IO.
---
src/shared/io-glib.c | 9 +++++++++
src/shared/io-mainloop.c | 9 +++++++++
src/shared/io.h | 2 ++
3 files changed, 20 insertions(+)
diff --git a/src/shared/io-glib.c b/src/shared/io-glib.c
index 76f5a44..6316037 100644
--- a/src/shared/io-glib.c
+++ b/src/shared/io-glib.c
@@ -323,3 +323,12 @@ done:
return true;
}
+
+bool io_shutdown(struct io *io)
+{
+ if (!io || !io->channel)
+ return false;
+
+ return g_io_channel_shutdown(io->channel, TRUE, NULL)
+ == G_IO_STATUS_NORMAL;
+}
diff --git a/src/shared/io-mainloop.c b/src/shared/io-mainloop.c
index 3fe1a88..2ea5eed 100644
--- a/src/shared/io-mainloop.c
+++ b/src/shared/io-mainloop.c
@@ -26,6 +26,7 @@
#endif
#include <unistd.h>
+#include <sys/socket.h>
#include "monitor/mainloop.h"
#include "src/shared/util.h"
@@ -294,3 +295,11 @@ bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
return true;
}
+
+bool io_shutdown(struct io *io)
+{
+ if (!io || io->fd < 0)
+ return false;
+
+ return shutdown(io->fd, SHUT_RDWR) == 0;
+}
diff --git a/src/shared/io.h b/src/shared/io.h
index 2e78c03..8897964 100644
--- a/src/shared/io.h
+++ b/src/shared/io.h
@@ -33,6 +33,8 @@ void io_destroy(struct io *io);
int io_get_fd(struct io *io);
bool io_set_close_on_destroy(struct io *io, bool do_close);
+bool io_shutdown(struct io *io);
+
typedef bool (*io_callback_func_t)(struct io *io, void *user_data);
bool io_set_read_handler(struct io *io, io_callback_func_t callback,
--
1.9.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 6/7] shared: Add support for local disconnect to HFP
2014-02-22 21:09 [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling Szymon Janc
` (3 preceding siblings ...)
2014-02-22 21:09 ` [PATCH v2 5/7] shared: Add support for shutdown to IO Szymon Janc
@ 2014-02-22 21:09 ` Szymon Janc
2014-02-22 21:09 ` [PATCH v2 7/7] android/handsfree: Use HFP code for connection handling Szymon Janc
2014-02-24 9:57 ` [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling Szymon Janc
6 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-02-22 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
This allows to locally trigger disconnection.
---
src/shared/hfp.c | 8 ++++++++
src/shared/hfp.h | 2 ++
2 files changed, 10 insertions(+)
diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index 98408ca..854cf46 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -455,3 +455,11 @@ bool hfp_gw_set_disconnect_handler(struct hfp_gw *hfp,
return true;
}
+
+bool hfp_gw_disconnect(struct hfp_gw *hfp)
+{
+ if (!hfp)
+ return false;
+
+ return io_shutdown(hfp->io);
+}
diff --git a/src/shared/hfp.h b/src/shared/hfp.h
index 6bb51bc..b0bd934 100644
--- a/src/shared/hfp.h
+++ b/src/shared/hfp.h
@@ -92,3 +92,5 @@ bool hfp_gw_set_disconnect_handler(struct hfp_gw *hfp,
hfp_disconnect_func_t callback,
void *user_data,
hfp_destroy_func_t destroy);
+
+bool hfp_gw_disconnect(struct hfp_gw *hfp);
--
1.9.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 7/7] android/handsfree: Use HFP code for connection handling
2014-02-22 21:09 [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling Szymon Janc
` (4 preceding siblings ...)
2014-02-22 21:09 ` [PATCH v2 6/7] shared: Add support for local disconnect to HFP Szymon Janc
@ 2014-02-22 21:09 ` Szymon Janc
2014-02-24 9:57 ` [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling Szymon Janc
6 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-02-22 21:09 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
HFP code is now able to handle disconnection on its own so just use
this instead of using own watches.
---
android/handsfree.c | 50 +++++++++++++-------------------------------------
1 file changed, 13 insertions(+), 37 deletions(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index 680345b..60bff91 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -51,8 +51,6 @@
static struct {
bdaddr_t bdaddr;
uint8_t state;
- GIOChannel *io;
- guint watch;
struct hfp_gw *gw;
} device;
@@ -95,38 +93,23 @@ static void device_cleanup(void)
device.gw = NULL;
}
- if (device.watch) {
- g_source_remove(device.watch);
- device.watch = 0;
- }
-
- if (device.io) {
- g_io_channel_unref(device.io);
- device.io = NULL;
- }
-
device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED);
memset(&device, 0, sizeof(device));
}
-static gboolean watch_cb(GIOChannel *chan, GIOCondition cond,
- gpointer user_data)
+static void at_command_handler(const char *command, void *user_data)
{
- DBG("");
-
- device.watch = 0;
-
- device_cleanup();
+ hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
- return FALSE;
+ hfp_gw_disconnect(device.gw);
}
-static void at_command_handler(const char *command, void *user_data)
+static void disconnect_watch(void *user_data)
{
- hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+ DBG("");
- g_io_channel_shutdown(device.io, TRUE, NULL);
+ device_cleanup();
}
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
@@ -138,22 +121,15 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
goto failed;
}
- g_io_channel_set_close_on_unref(chan, TRUE);
-
device.gw = hfp_gw_new(g_io_channel_unix_get_fd(chan));
if (!device.gw)
goto failed;
+ g_io_channel_set_close_on_unref(chan, FALSE);
+
hfp_gw_set_close_on_unref(device.gw, true);
hfp_gw_set_command_handler(device.gw, at_command_handler, NULL, NULL);
-
- device.watch = g_io_add_watch(chan,
- G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- watch_cb, NULL);
- if (device.watch == 0)
- goto failed;
-
- device.io = g_io_channel_ref(chan);
+ hfp_gw_set_disconnect_handler(device.gw, disconnect_watch, NULL, NULL);
device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTED);
@@ -331,11 +307,11 @@ static void handle_disconnect(const void *buf, uint16_t len)
goto failed;
}
- if (device.io) {
- device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING);
- g_io_channel_shutdown(device.io, TRUE, NULL);
- } else {
+ if (device.state == HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTING) {
device_cleanup();
+ } else {
+ device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING);
+ hfp_gw_disconnect(device.gw);
}
status = HAL_STATUS_SUCCESS;
--
1.9.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling
2014-02-22 21:09 [PATCH v2 1/7] shared: Add support for disconnect handler to GLib based IO handling Szymon Janc
` (5 preceding siblings ...)
2014-02-22 21:09 ` [PATCH v2 7/7] android/handsfree: Use HFP code for connection handling Szymon Janc
@ 2014-02-24 9:57 ` Szymon Janc
6 siblings, 0 replies; 8+ messages in thread
From: Szymon Janc @ 2014-02-24 9:57 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
On Saturday 22 of February 2014 22:09:19 Szymon Janc wrote:
> From: Szymon Janc <szymon.janc@tieto.com>
>
> ---
> src/shared/io-glib.c | 76 +++++++++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 67 insertions(+), 9 deletions(-)
>
> diff --git a/src/shared/io-glib.c b/src/shared/io-glib.c
> index 5bd9ac0..5490fc0 100644
> --- a/src/shared/io-glib.c
> +++ b/src/shared/io-glib.c
> @@ -40,6 +40,10 @@ struct io {
> io_callback_func_t write_callback;
> io_destroy_func_t write_destroy;
> void *write_data;
> + guint disconnect_watch;
> + io_callback_func_t disconnect_callback;
> + io_destroy_func_t disconnect_destroy;
> + void *disconnect_data;
> };
>
> static struct io *io_ref(struct io *io)
> @@ -157,7 +161,7 @@ static gboolean read_callback(GIOChannel *channel, GIOCondition cond,
> struct io *io = user_data;
> bool result;
>
> - if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL))
> + if (cond & (G_IO_ERR | G_IO_NVAL))
> return FALSE;
>
> if (io->read_callback)
> @@ -183,9 +187,9 @@ bool io_set_read_handler(struct io *io, io_callback_func_t callback,
> goto done;
>
> io->read_watch = g_io_add_watch_full(io->channel, G_PRIORITY_DEFAULT,
> - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
> - read_callback, io_ref(io),
> - read_watch_destroy);
> + G_IO_IN | G_IO_ERR | G_IO_NVAL,
> + read_callback, io_ref(io),
> + read_watch_destroy);
> if (io->read_watch == 0)
> return false;
>
> @@ -218,7 +222,7 @@ static gboolean write_callback(GIOChannel *channel, GIOCondition cond,
> struct io *io = user_data;
> bool result;
>
> - if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL))
> + if (cond & (G_IO_ERR | G_IO_NVAL))
> return FALSE;
>
> if (io->write_callback)
> @@ -244,9 +248,9 @@ bool io_set_write_handler(struct io *io, io_callback_func_t callback,
> goto done;
>
> io->write_watch = g_io_add_watch_full(io->channel, G_PRIORITY_DEFAULT,
> - G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
> - write_callback, io_ref(io),
> - write_watch_destroy);
> + G_IO_OUT | G_IO_ERR | G_IO_NVAL,
> + write_callback, io_ref(io),
> + write_watch_destroy);
> if (io->write_watch == 0)
> return false;
>
> @@ -258,8 +262,62 @@ done:
> return true;
> }
>
> +static void disconnect_watch_destroy(gpointer user_data)
> +{
> + struct io *io = user_data;
> +
> + if (io->disconnect_destroy)
> + io->disconnect_destroy(io->disconnect_data);
> +
> + io->disconnect_watch = 0;
> + io->disconnect_callback = NULL;
> + io->disconnect_destroy = NULL;
> + io->disconnect_data = NULL;
> +
> + io_unref(io);
> +}
> +
> +static gboolean disconnect_callback(GIOChannel *channel, GIOCondition cond,
> + gpointer user_data)
> +{
> + struct io *io = user_data;
> + bool result;
> +
> + if (io->disconnect_callback)
> + result = io->disconnect_callback(io, io->disconnect_data);
> + else
> + result = false;
> +
> + return result ? TRUE : FALSE;
> +}
> +
> bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
> void *user_data, io_destroy_func_t destroy)
> {
> - return false;
> + if (!io)
> + return false;
> +
> + if (io->disconnect_watch > 0) {
> + g_source_remove(io->disconnect_watch);
> + io->disconnect_watch = 0;
> + }
> +
> + if (!callback)
> + goto done;
> +
> + io->disconnect_watch = g_io_add_watch_full(io->channel,
> + G_PRIORITY_DEFAULT,
> + G_IO_HUP | G_IO_ERR | G_IO_NVAL,
> + disconnect_callback, io_ref(io),
> + disconnect_watch_destroy);
> + if (io->disconnect_watch == 0)
> + return false;
> +
> + io->disconnect_destroy = destroy;
> + io->disconnect_data = user_data;
> +
> +done:
> + io->disconnect_callback = callback;
> +
> + return true;
> }
>
This is now applied.
--
Best regards,
Szymon Janc
^ permalink raw reply [flat|nested] 8+ messages in thread