diff options
author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-04-23 18:12:25 +0000 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-04-23 18:12:25 +0000 |
commit | 0a46bec1995f0b707080214bde9132cb6b69e162 (patch) | |
tree | 4a303cbab74018e500e1b980593fee5e8b58b9a3 /common | |
parent | b47a2a08851a5bacc0e2498846db25d8837ba069 (diff) |
Introduce bt_sco_connect and some other fixes.
Diffstat (limited to 'common')
-rw-r--r-- | common/glib-helper.c | 139 |
1 files changed, 99 insertions, 40 deletions
diff --git a/common/glib-helper.c b/common/glib-helper.c index e314d9e9..23271fa2 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -26,6 +26,7 @@ #endif #include <errno.h> +#include <fcntl.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/ioctl.h> @@ -34,6 +35,7 @@ #include <bluetooth/bluetooth.h> #include <bluetooth/rfcomm.h> #include <bluetooth/l2cap.h> +#include <bluetooth/sco.h> #include <bluetooth/sdp.h> #include <bluetooth/sdp_lib.h> @@ -379,6 +381,61 @@ done: return FALSE; } +static int transport_connect(struct io_context *io_ctxt, int fd, + struct sockaddr *addr, socklen_t addrlen) +{ + int err; + + io_ctxt->io = g_io_channel_unix_new(fd); + if (!io_ctxt->io) + return -ENOMEM; + + err = g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL); + if (err != G_IO_STATUS_NORMAL) + return -EPERM; + + err = connect(fd, addr, addrlen); + if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) + return -errno; + + g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + (GIOFunc) connect_cb, io_ctxt); + + return 0; +} + +static int sco_connect(struct io_context *io_ctxt, const bdaddr_t *src, + const bdaddr_t *dst) +{ + struct sockaddr_sco addr; + int sk, err; + + sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); + if (sk < 0) + return -errno; + + memset(&addr, 0, sizeof(addr)); + addr.sco_family = AF_BLUETOOTH; + bacpy(&addr.sco_bdaddr, src); + + err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); + if (err < 0) + return -errno; + + memset(&addr, 0, sizeof(addr)); + addr.sco_family = AF_BLUETOOTH; + bacpy(&addr.sco_bdaddr, dst); + + err = transport_connect(io_ctxt, sk, (struct sockaddr *) &addr, + sizeof(addr)); + if (err < 0) { + close(sk); + return err; + } + + return 0; +} + static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, const bdaddr_t *dst, uint16_t psm) { @@ -389,34 +446,25 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, if (sk < 0) return -errno; - io_ctxt->io = g_io_channel_unix_new(sk); - if (!io_ctxt->io) - return -ENOMEM; - memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, src); err = bind(sk, (struct sockaddr *) &l2a, sizeof(l2a)); if (err < 0) - return err; - - if (g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL) != - G_IO_STATUS_NORMAL) - return -EPERM; + return -errno; memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, dst); l2a.l2_psm = htobs(psm); - err = connect(sk, (struct sockaddr *) &l2a, sizeof(l2a)); - - if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) + err = transport_connect(io_ctxt, sk, (struct sockaddr *) &l2a, + sizeof(l2a)); + if (err < 0) { + close(sk); return err; - - g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - (GIOFunc) connect_cb, io_ctxt); + } return 0; } @@ -431,34 +479,25 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, if (sk < 0) return -errno; - io_ctxt->io = g_io_channel_unix_new(sk); - if (!io_ctxt->io) - return -ENOMEM; - memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; bacpy(&addr.rc_bdaddr, src); err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) - return err; - - if (g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL) != - G_IO_STATUS_NORMAL) - return -EPERM; + return -errno; memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; bacpy(&addr.rc_bdaddr, dst); addr.rc_channel = channel; - err = connect(sk, (struct sockaddr *) &addr, sizeof(addr)); - - if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) + err = transport_connect(io_ctxt, sk, (struct sockaddr *) &addr, + sizeof(addr)); + if (err < 0) { + close(sk); return err; - - g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - (GIOFunc) connect_cb, io_ctxt); + } return 0; } @@ -476,6 +515,15 @@ static int create_io_context(struct io_context **io_ctxt, bt_io_callback_t cb, return 0; } +static void io_context_cleanup(struct io_context *io_ctxt) +{ + if (io_ctxt->io) { + g_io_channel_close(io_ctxt->io); + g_io_channel_unref(io_ctxt->io); + } + g_free(io_ctxt); +} + int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, sdp_record_t *record, bt_io_callback_t cb, void *user_data) @@ -503,11 +551,7 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, err = rfcomm_connect(io_ctxt, src, dst, channel); if (err < 0) { - if (io_ctxt->io) { - g_io_channel_close(io_ctxt->io); - g_io_channel_unref(io_ctxt->io); - } - g_free(io_ctxt); + io_context_cleanup(io_ctxt); return err; } @@ -526,11 +570,26 @@ int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, err = l2cap_connect(io_ctxt, src, dst, psm); if (err < 0) { - if (io_ctxt->io) { - g_io_channel_close(io_ctxt->io); - g_io_channel_unref(io_ctxt->io); - } - g_free(io_ctxt); + io_context_cleanup(io_ctxt); + return err; + } + + return 0; +} + +int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, + bt_io_callback_t cb, void *user_data) +{ + struct io_context *io_ctxt; + int err; + + err = create_io_context(&io_ctxt, cb, user_data); + if (err < 0) + return err; + + err = sco_connect(io_ctxt, src, dst); + if (err < 0) { + io_context_cleanup(io_ctxt); return err; } |