diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2008-03-12 21:22:06 +0000 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2008-03-12 21:22:06 +0000 |
commit | fbd60c20356e145a30e7fe7f6e91c9e8cf3c73da (patch) | |
tree | 04670a20e3871693d138049a9de1c3784614db11 /plugins/echo.c | |
parent | 88f13920c39806113d88ca13d2542a2380ffa63c (diff) |
Add RFCOMM listener to echo plugin
Diffstat (limited to 'plugins/echo.c')
-rw-r--r-- | plugins/echo.c | 96 |
1 files changed, 96 insertions, 0 deletions
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 <errno.h> +#include <unistd.h> +#include <sys/socket.h> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/rfcomm.h> +#include <bluetooth/sdp.h> +#include <bluetooth/sdp_lib.h> + +#include <glib.h> #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 = { |