Linux-Bluetooth Archive on lore.kernel.org
 help / Atom feed
* [PATCH BlueZ] shared/io-libevent2: Add support for libevent2 based IO handing
@ 2019-02-06 15:30 Shawn Nock
  2019-02-06 15:45 ` Marcel Holtmann
  0 siblings, 1 reply; 3+ messages in thread
From: Shawn Nock @ 2019-02-06 15:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Shawn Nock

---
 src/shared/io-libevent2.c | 247 ++++++++++++++++++++++++++++++++++++++
 src/shared/io.h           |   1 +
 2 files changed, 248 insertions(+)
 create mode 100644 src/shared/io-libevent2.c

diff --git a/src/shared/io-libevent2.c b/src/shared/io-libevent2.c
new file mode 100644
index 000000000..584e1a021
--- /dev/null
+++ b/src/shared/io-libevent2.c
@@ -0,0 +1,247 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2019       Shawn Nock <shawn@monadnock.ca>
+ *  Copyright (C) 2012-2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+
+#include <event2/event.h>
+
+#include "src/shared/io.h"
+#include "src/shared/util.h"
+
+struct io {
+  struct event *event;
+  io_callback_func_t read_callback;
+  io_destroy_func_t read_destroy;
+  void *read_data;
+  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 event_base *g_event_base = NULL;
+
+void io_set_context(void *v) {
+	g_event_base = v;
+}
+
+void io_callback(int fd, short which, void* arg)
+{
+    struct io *io = arg;
+    if (which & EV_READ && io->read_callback) {
+        io->read_callback(io, io->read_data);
+    }
+
+    if (which & EV_WRITE && io->write_callback){
+        io->write_callback(io, io->write_data);
+    }
+
+    if (which & EV_CLOSED && io->disconnect_callback) {
+        io->disconnect_callback(io, io->disconnect_data);
+    }
+}
+
+struct io *io_new(int fd)
+{
+	if (fd < 0) {
+        return NULL;
+    }
+
+	struct io *io = new0(struct io, 1);
+
+	io->event = event_new(g_event_base, fd, EV_READ | EV_WRITE | EV_PERSIST, io_callback, io);
+	if (!io->event) {
+		free(io);
+		return NULL;
+	}
+	event_add(io->event, NULL);
+	return io;
+}
+
+void io_destroy(struct io *io)
+{
+	if (!io)
+		return;
+
+	if (io->event)
+	    event_del(io->event);
+		event_free(io->event);
+
+	free(io);
+}
+
+int io_get_fd(struct io *io)
+{
+	if (!io || !io->event)
+		return -ENOTCONN;
+
+	return event_get_fd(io->event);
+}
+
+bool io_set_close_on_destroy(struct io *io, bool do_close)
+{
+    if (!io || !io->event)
+        return false;
+
+    return true;
+}
+
+static short io_get_events(struct io* io)
+{
+    short which;
+    event_get_assignment(io->event, NULL, NULL, &which, NULL, NULL);
+    return which;
+}
+
+static void io_set_events(struct io* io, short events)
+{
+    struct event_base *base;
+    int fd;
+    event_callback_fn cb;
+    void *arg;
+
+    event_get_assignment(io->event, &base, &fd, NULL, &cb, &arg);
+    int pending = event_pending(io->event, EV_READ | EV_WRITE | EV_CLOSED, NULL);
+
+    if (pending) {
+        event_del(io->event);
+    }
+    event_assign(io->event, base, fd, events, cb, arg);
+    event_add(io->event, NULL);
+}
+
+static void io_update_events(struct io* io, short events, bool enable)
+{
+    short new_ev;
+    short cur = io_get_events(io);
+    if (enable) {
+        new_ev = cur | events;
+    } else {
+        new_ev = cur & ~events;
+    }
+    if (events != new_ev) {
+        io_set_events(io, new_ev);
+    }
+}
+
+bool io_set_read_handler(struct io *io, io_callback_func_t callback,
+                         void *user_data, io_destroy_func_t destroy)
+{
+    if (!io || !io->event)
+        return false;
+
+    if (io->read_destroy) {
+        io->read_destroy(io->read_data);
+    }
+
+    io->read_callback = callback;
+    io->read_destroy = destroy;
+    io->read_data = user_data;
+
+    io_update_events(io, EV_READ, (bool)callback);
+
+	return true;
+}
+
+bool io_set_write_handler(struct io *io, io_callback_func_t callback,
+                          void *user_data, io_destroy_func_t destroy)
+{
+	if (!io || !io->event)
+		return false;
+
+	if (io->write_destroy) {
+	    io->write_destroy(io->write_data);
+	}
+
+    io->write_callback = callback;
+    io->write_destroy = destroy;
+    io->write_data = user_data;
+
+    io_update_events(io, EV_WRITE, (bool)callback);
+
+    return true;
+}
+
+bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
+                               void *user_data, io_destroy_func_t destroy)
+{
+	if (!io || !io->event)
+		return false;
+
+	if (io->disconnect_destroy) {
+	    io->disconnect_destroy(io->disconnect_data);
+	}
+
+    io->disconnect_callback = callback;
+    io->disconnect_destroy = destroy;
+    io->disconnect_data = user_data;
+
+    io_update_events(io, EV_CLOSED, (bool)callback);
+
+	return true;
+}
+
+ssize_t io_send(struct io *io, const struct iovec *iov, int iovcnt)
+{
+	ssize_t ret;
+	int fd;
+
+	if (!io || !io->event)
+		return -ENOTCONN;
+
+	fd = io_get_fd(io);
+	if (fd < 0)
+		return -ENOTCONN;
+
+	do {
+		ret = writev(fd, iov, iovcnt);
+	} while (ret < 0 && errno == EINTR);
+
+	if (ret < 0)
+		return -errno;
+
+	return ret;
+}
+
+bool io_shutdown(struct io *io)
+{
+	int fd;
+
+	if (!io || !io->event)
+		return false;
+
+	fd = io_get_fd(io);
+	if (fd < 0)
+		return false;
+
+	return shutdown(fd, SHUT_RDWR) == 0;
+}
diff --git a/src/shared/io.h b/src/shared/io.h
index 8bc1111d0..9a8d54062 100644
--- a/src/shared/io.h
+++ b/src/shared/io.h
@@ -45,3 +45,4 @@ bool io_set_write_handler(struct io *io, io_callback_func_t callback,
 				void *user_data, io_destroy_func_t destroy);
 bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
 				void *user_data, io_destroy_func_t destroy);
+void io_set_context(void *);
\ No newline at end of file
--
2.20.1

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

end of thread, back to index

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-06 15:30 [PATCH BlueZ] shared/io-libevent2: Add support for libevent2 based IO handing Shawn Nock
2019-02-06 15:45 ` Marcel Holtmann
2019-02-06 16:00   ` Shawn Nock

Linux-Bluetooth Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-bluetooth/0 linux-bluetooth/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-bluetooth linux-bluetooth/ https://lore.kernel.org/linux-bluetooth \
		linux-bluetooth@vger.kernel.org linux-bluetooth@archiver.kernel.org
	public-inbox-index linux-bluetooth


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-bluetooth


AGPL code for this site: git clone https://public-inbox.org/ public-inbox