From 57e21703e213e61fdfd6571a421e2f9da118444b Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 23 Feb 2007 19:04:43 +0000 Subject: Fake input: added rfcomm_connect --- input/device.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 6 deletions(-) (limited to 'input') diff --git a/input/device.c b/input/device.c index c487b4ee..3b11f491 100644 --- a/input/device.c +++ b/input/device.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -406,16 +407,88 @@ static const char *create_input_path(uint8_t major, uint8_t minor) return path; } +static gboolean rfcomm_connect_cb(GIOChannel *chan, + GIOCondition cond, struct pending_connect *pc) +{ + int err = EIO; + + err_connection_failed(pc->conn, pc->msg, strerror(err)); + pending_connect_free(pc); + g_io_channel_unref(chan); + return FALSE; +} + static int rfcomm_connect(struct pending_connect *pc, uint8_t ch) { - char addr[18]; - /* FIXME: not implemented */ + struct sockaddr_rc addr; + GIOChannel *io; + int sk, err; + + sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (sk < 0) { + err = errno; + error("socket: %s (%d)", strerror(err), err); + return -err; + } + + io = g_io_channel_unix_new(sk); + if (!io) { + err = -EIO; + error("channel_unix_new failed in rfcomm connect"); + goto failed; + } + + g_io_channel_set_close_on_unref(io, FALSE); + + memset(&addr, 0, sizeof(addr)); + addr.rc_family = AF_BLUETOOTH; + bacpy(&addr.rc_bdaddr, &pc->src); + addr.rc_channel = 0; - ba2str(&pc->dst, addr); - debug("RFCOMM connecting to %s on channel:%d", addr, ch); - errno = EIO; + if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + err = errno; + error("bind: %s (%d)", strerror(err), err); + goto failed; + } + + if (set_nonblocking(sk) < 0) { + err = errno; + error("Set non blocking: %s (%d)", strerror(err), err); + goto failed; + } + + memset(&addr, 0, sizeof(addr)); + addr.rc_family = AF_BLUETOOTH; + bacpy(&addr.rc_bdaddr, &pc->dst); + addr.rc_channel = ch; + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + char peer[18]; /* FIXME: debug purpose */ + if (!(errno == EAGAIN || errno == EINPROGRESS)) { + err = errno; + error("connect() failed: %s (%d)", + strerror(err), err); + goto failed; + } + + ba2str(&pc->dst, peer); + debug("RFCOMM connection in progress: %s channel:%d", peer, ch); + g_io_add_watch(io, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + (GIOFunc) rfcomm_connect_cb, pc); + } else { + debug("Connect succeeded with first try"); + rfcomm_connect_cb(io, G_IO_OUT, pc); + } + + return 0; + +failed: + if (io) + g_io_channel_unref(io); + + close(sk); + errno = err; - return -EIO; + return -err; } static int l2cap_connect(struct pending_connect *pc, -- cgit