From fbd60c20356e145a30e7fe7f6e91c9e8cf3c73da Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 12 Mar 2008 21:22:06 +0000 Subject: Add RFCOMM listener to echo plugin --- plugins/echo.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'plugins/echo.c') diff --git a/plugins/echo.c b/plugins/echo.c index 81999a64..ca8c25d4 100644 --- a/plugins/echo.c +++ b/plugins/echo.c @@ -26,21 +26,117 @@ #endif #include +#include +#include + +#include +#include +#include +#include + +#include #include "plugin.h" #include "server.h" #include "logging.h" +static gboolean session_event(GIOChannel *chan, + GIOCondition cond, gpointer data) +{ + unsigned char buf[672]; + gsize len, written; + GIOError err; + + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) + return FALSE; + + err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); + if (err == G_IO_ERROR_AGAIN) + return TRUE; + + g_io_channel_write(chan, (const gchar *) buf, len, &written); + + return TRUE; +} + +static gboolean connect_event(GIOChannel *chan, + GIOCondition cond, gpointer data) +{ + GIOChannel *io; + struct sockaddr_rc addr; + socklen_t optlen; + char address[18]; + int sk, nsk; + + sk = g_io_channel_unix_get_fd(chan); + + memset(&addr, 0, sizeof(addr)); + optlen = sizeof(addr); + + nsk = accept(sk, (struct sockaddr *) &addr, &optlen); + if (nsk < 0) + return TRUE; + + io = g_io_channel_unix_new(nsk); + g_io_channel_set_close_on_unref(io, TRUE); + + ba2str(&addr.rc_bdaddr, address); + + g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + session_event, NULL); + + return TRUE; +} + +static GIOChannel *setup_rfcomm(uint8_t channel) +{ + GIOChannel *io; + struct sockaddr_rc addr; + int sk; + + sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (sk < 0) + return NULL; + + memset(&addr, 0, sizeof(addr)); + addr.rc_family = AF_BLUETOOTH; + bacpy(&addr.rc_bdaddr, BDADDR_ANY); + addr.rc_channel = channel; + + if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + close(sk); + return NULL; + } + + if (listen(sk, 10) < 0) { + close(sk); + return NULL; + } + + io = g_io_channel_unix_new(sk); + g_io_channel_set_close_on_unref(io, TRUE); + + g_io_add_watch(io, G_IO_IN, connect_event, NULL); + + return io; +} + +static GIOChannel *chan = NULL; + static int echo_probe(const char *adapter) { debug("echo probe adapter %s", adapter); + chan = setup_rfcomm(23); + return 0; } static void echo_remove(const char *adapter) { debug("echo remove adapter %s", adapter); + + g_io_channel_unref(chan); } static struct bt_server echo_server = { -- cgit