diff options
-rw-r--r-- | audio/avdtp.c | 2 | ||||
-rw-r--r-- | common/glib-helper.c | 17 | ||||
-rw-r--r-- | common/glib-helper.h | 3 | ||||
-rw-r--r-- | input/device.c | 4 | ||||
-rw-r--r-- | input/manager.c | 6 | ||||
-rw-r--r-- | network/connection.c | 111 |
6 files changed, 41 insertions, 102 deletions
diff --git a/audio/avdtp.c b/audio/avdtp.c index 2e22d8a2..2f2e131e 100644 --- a/audio/avdtp.c +++ b/audio/avdtp.c @@ -1590,7 +1590,7 @@ static int l2cap_connect(struct avdtp *session) { int err; - err = bt_l2cap_connect(&session->src, &session->dst, AVDTP_PSM, + err = bt_l2cap_connect(&session->src, &session->dst, AVDTP_PSM, 0, l2cap_connect_cb, session); if (err < 0) { error("Connect failed. %s(%d)", strerror(-err), -err); diff --git a/common/glib-helper.c b/common/glib-helper.c index 7810ba7e..8fa8efcf 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -440,8 +440,11 @@ static int sco_connect(struct io_context *io_ctxt, const bdaddr_t *src, } static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, - const bdaddr_t *dst, uint16_t psm) + const bdaddr_t *dst, uint16_t psm, + uint16_t mtu) { + struct l2cap_options l2o; + socklen_t olen; struct sockaddr_l2 l2a; int sk, err; @@ -449,6 +452,14 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, if (sk < 0) return -errno; + if (mtu) { + memset(&l2o, 0, sizeof(l2o)); + olen = sizeof(l2o); + getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen); + l2o.imtu = l2o.omtu = mtu; + setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)); + } + memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, src); @@ -551,7 +562,7 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, } int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, - uint16_t psm, bt_io_callback_t cb, void *user_data) + uint16_t psm, uint16_t mtu, bt_io_callback_t cb, void *user_data) { struct io_context *io_ctxt; int err; @@ -560,7 +571,7 @@ int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, if (err < 0) return err; - err = l2cap_connect(io_ctxt, src, dst, psm); + err = l2cap_connect(io_ctxt, src, dst, psm, mtu); if (err < 0) { io_context_cleanup(io_ctxt); return err; diff --git a/common/glib-helper.h b/common/glib-helper.h index 6d191640..97f51b11 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -39,6 +39,7 @@ GSList *bt_string2list(const gchar *str); int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, bt_io_callback_t cb, void *user_data); int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, - uint16_t psm, bt_io_callback_t cb, void *user_data); + uint16_t psm, uint16_t mtu, bt_io_callback_t cb, + void *user_data); int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, bt_io_callback_t cb, void *user_data); diff --git a/input/device.c b/input/device.c index 348622e6..b27800e4 100644 --- a/input/device.c +++ b/input/device.c @@ -605,7 +605,7 @@ static void control_connect_cb(GIOChannel *chan, int err, gpointer user_data) idev->ctrl_sk = g_io_channel_unix_get_fd(chan); /* Connect to the HID interrupt channel */ - err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_INTR, + err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_INTR, 0, interrupt_connect_cb, idev); if (err < 0) { error("L2CAP connect failed:%s (%d)", strerror(-err), -err); @@ -766,7 +766,7 @@ static DBusHandlerResult device_connect(DBusConnection *conn, } /* HID devices */ - err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_CTRL, + err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_CTRL, 0, control_connect_cb, idev); if (err < 0) { error("L2CAP connect failed: %s(%d)", strerror(-err), -err); diff --git a/input/manager.c b/input/manager.c index 51085279..1c024c9c 100644 --- a/input/manager.c +++ b/input/manager.c @@ -283,7 +283,7 @@ static void control_connect_cb(GIOChannel *chan, int err, gpointer user_data) pr->ctrl_channel = chan; /* Connect to the HID interrupt channel */ - err = bt_l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_INTR, + err = bt_l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_INTR, 0, interrupt_connect_cb, pr); if (err < 0) { error("L2CAP connect failed:%s (%d)", strerror(-err), -err); @@ -317,7 +317,7 @@ static void create_bonding_reply(DBusPendingCall *call, void *data) dbus_message_unref(reply); - err = bt_l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_CTRL, + err = bt_l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_CTRL, 0, control_connect_cb, pr); if (err < 0) { error("L2CAP connect failed:%s (%d)", strerror(-err), -err); @@ -391,7 +391,7 @@ static void hid_record_cb(sdp_list_t *recs, int err, gpointer user_data) } /* No encryption or link key already exists -- connect control channel */ - err = bt_l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_CTRL, + err = bt_l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_CTRL, 0, control_connect_cb, pr); if (err < 0) { error("L2CAP connect failed:%s (%d)", strerror(-err), -err); diff --git a/network/connection.c b/network/connection.c index 18f79130..b5ef61ba 100644 --- a/network/connection.c +++ b/network/connection.c @@ -36,6 +36,7 @@ #include <bluetooth/hci_lib.h> #include <bluetooth/l2cap.h> #include <bluetooth/bnep.h> +#include <bluetooth/sdp.h> #include <glib.h> @@ -43,6 +44,7 @@ #include "dbus.h" #include "dbus-helper.h" #include "textfile.h" +#include "glib-helper.h" #include "error.h" #include "common.h" @@ -221,102 +223,30 @@ out: return err; } -static gboolean l2cap_connect_cb(GIOChannel *chan, - GIOCondition cond, gpointer data) +static void connect_cb(GIOChannel *chan, int err, gpointer data) { struct network_conn *nc = data; - socklen_t len; - int sk, ret; - if (cond & G_IO_NVAL) - return FALSE; - - if (cond & (G_IO_ERR | G_IO_HUP)) - goto failed; - - sk = g_io_channel_unix_get_fd(chan); - - len = sizeof(ret); - if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { - error("getsockopt(SO_ERROR): %s (%d)", strerror(errno), errno); + if (err < 0) { + error("l2cap connect(): %s (%d)", strerror(-err), -err); goto failed; } - if (ret != 0) { - error("connect(): %s (%d)", strerror(errno), errno); - goto failed; - } + nc->sk = g_io_channel_unix_get_fd(chan); - if (bnep_connect(nc)) { - error("connect(): %s (%d)", strerror(errno), errno); + err = bnep_connect(nc); + if (err < 0) { + error("bnep connect(): %s (%d)", strerror(-err), -err); + g_io_channel_close(chan); + g_io_channel_unref(chan); goto failed; } - return FALSE; + return; + failed: nc->state = DISCONNECTED; - error_connection_attempt_failed(connection, nc->msg, errno); - g_io_channel_close(chan); - return FALSE; -} - -static int l2cap_connect(struct network_conn *nc) -{ - struct l2cap_options l2o; - struct sockaddr_l2 l2a; - socklen_t olen; - char addr[18]; - GIOChannel *io; - - ba2str(&nc->dst, addr); - info("Connecting to %s", addr); - - /* Setup L2CAP options according to BNEP spec */ - memset(&l2o, 0, sizeof(l2o)); - olen = sizeof(l2o); - getsockopt(nc->sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen); - l2o.imtu = l2o.omtu = BNEP_MTU; - setsockopt(nc->sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)); - - memset(&l2a, 0, sizeof(l2a)); - l2a.l2_family = AF_BLUETOOTH; - bacpy(&l2a.l2_bdaddr, &nc->src); - - if (bind(nc->sk, (struct sockaddr *) &l2a, sizeof(l2a)) < 0) { - error("Bind failed. %s(%d)", strerror(errno), errno); - return -errno; - } - - memset(&l2a, 0, sizeof(l2a)); - l2a.l2_family = AF_BLUETOOTH; - bacpy(&l2a.l2_bdaddr, &nc->dst); - l2a.l2_psm = htobs(BNEP_PSM); - - if (set_nonblocking(nc->sk) < 0) { - error("Set non blocking: %s (%d)", strerror(errno), errno); - return -errno; - } - - io = g_io_channel_unix_new(nc->sk); - g_io_channel_set_close_on_unref(io, FALSE); - - if (connect(nc->sk, (struct sockaddr *) &l2a, sizeof(l2a))) { - if (!(errno == EAGAIN || errno == EINPROGRESS)) { - error("Connect failed. %s(%d)", strerror(errno), - errno); - g_io_channel_close(io); - g_io_channel_unref(io); - return -errno; - } - g_io_add_watch(io, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - (GIOFunc) l2cap_connect_cb, nc); - - } else { - l2cap_connect_cb(io, G_IO_OUT, nc); - } - - g_io_channel_unref(io); - return 0; + error_connection_attempt_failed(connection, nc->msg, -err); } static DBusHandlerResult get_adapter(DBusConnection *conn, DBusMessage *msg, @@ -448,6 +378,7 @@ static DBusHandlerResult connection_connect(DBusConnection *conn, { struct network_conn *nc = data; DBusError derr; + int err; if (nc->state != DISCONNECTED) { error_failed(conn, msg, "Device already connected"); @@ -462,16 +393,12 @@ static DBusHandlerResult connection_connect(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - nc->sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); nc->state = CONNECTING; - if (nc->sk < 0) { - error("Cannot create L2CAP socket. %s(%d)", strerror(errno), - errno); - goto fail; - } - nc->msg = dbus_message_ref(msg); - if (l2cap_connect(nc) < 0) { + + err = bt_l2cap_connect(&nc->src, &nc->dst, BNEP_PSM, BNEP_MTU, + connect_cb, nc); + if (err < 0) { error("Connect failed. %s(%d)", strerror(errno), errno); goto fail; } |