Make bt_l2cap_connect to take mtu as paramter.

This commit is contained in:
Luiz Augusto von Dentz 2008-05-07 18:39:36 +00:00
parent 319f3d5167
commit f85b9560ec
6 changed files with 41 additions and 102 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
nc->sk = g_io_channel_unix_get_fd(chan);
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;
}
if (bnep_connect(nc)) {
error("connect(): %s (%d)", strerror(errno), errno);
goto failed;
}
return;
return FALSE;
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;
}