diff options
-rw-r--r-- | attrib/gatttool.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/attrib/gatttool.c b/attrib/gatttool.c index f1e2940e..fed4aebc 100644 --- a/attrib/gatttool.c +++ b/attrib/gatttool.c @@ -43,12 +43,15 @@ #include "gatt.h" #define GATT_PSM 27 +/* Minimum MTU for L2CAP connections over BR/EDR */ +#define ATT_MIN_MTU_L2CAP 48 static gchar *opt_src = NULL; static gchar *opt_dst = NULL; static int opt_start = 0x0001; static int opt_end = 0xffff; static int opt_handle = 0x0001; +static int opt_mtu = 0; static gboolean opt_primary = FALSE; static gboolean opt_characteristics = FALSE; static gboolean opt_char_read = FALSE; @@ -75,6 +78,14 @@ static int l2cap_connect(void) return -EINVAL; } + /* This check is required because currently setsockopt() returns no + * errors for MTU values smaller than the allowed minimum. */ + if (opt_mtu != 0 && opt_mtu < ATT_MIN_MTU_L2CAP) { + g_printerr("MTU cannot be smaller than %d\n", + ATT_MIN_MTU_L2CAP); + return -EINVAL; + } + str2ba(opt_dst, &dba); /* Local adapter */ @@ -106,6 +117,31 @@ static int l2cap_connect(void) return -err; } + if (opt_mtu > 0) { + struct l2cap_options l2o; + socklen_t len; + + memset(&l2o, 0, sizeof(l2o)); + len = sizeof(l2o); + if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0) { + err = errno; + g_printerr("getsockopt(L2CAP_OPTIONS): %s(%d)\n", + strerror(err), err); + return -err; + } + + l2o.imtu = opt_mtu; + l2o.omtu = opt_mtu; + + if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, + sizeof(l2o)) < 0) { + err = errno; + g_printerr("setsockopt(L2CAP_OPTIONS): %s(%d)\n", + strerror(err), err); + return -err; + } + } + memset(&addr, 0, sizeof(addr)); addr.l2_family = AF_BLUETOOTH; bacpy(&addr.l2_bdaddr, &dba); @@ -431,6 +467,8 @@ static GOptionEntry options[] = { "Specify local adapter interface", "hciX" }, { "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst, "Specify remote Bluetooth address", "MAC" }, + { "mtu", 'm', 0, G_OPTION_ARG_INT, &opt_mtu, + "Specify the MTU size", "MTU" }, { NULL }, }; |