summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/avdtp.c2
-rw-r--r--common/glib-helper.c17
-rw-r--r--common/glib-helper.h3
-rw-r--r--input/device.c4
-rw-r--r--input/manager.c6
-rw-r--r--network/connection.c111
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;
}