summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2016-07-08 11:43:32 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2016-07-13 14:03:45 +0300
commit05bdde05b2176b42f6334c4f478395cfc6943abf (patch)
treeb6ef4158acd0f567341c0ecb7244f04a4e9a9f6b
parentfc9ccf6154a0c090e641569a9567a40eb1c721f5 (diff)
downloadbluez-05bdde05b2176b42f6334c4f478395cfc6943abf.tar.gz
shared/att: Fix MTU size for when using BR/EDR links
BR/EDR links uses L2CAP commands to setup the MTU.
-rw-r--r--src/shared/att-types.h4
-rw-r--r--src/shared/att.c51
-rw-r--r--src/shared/att.h1
3 files changed, 52 insertions, 4 deletions
diff --git a/src/shared/att-types.h b/src/shared/att-types.h
index 4a9b67f36..51922d174 100644
--- a/src/shared/att-types.h
+++ b/src/shared/att-types.h
@@ -37,6 +37,10 @@
#define BT_ATT_MAX_LE_MTU 517
#define BT_ATT_MAX_VALUE_LEN 512
+#define BT_ATT_LINK_BREDR 0x00
+#define BT_ATT_LINK_LE 0x01
+#define BT_ATT_LINK_LOCAL 0xff
+
/* ATT protocol opcodes */
#define BT_ATT_OP_ERROR_RSP 0x01
#define BT_ATT_OP_MTU_REQ 0x02
diff --git a/src/shared/att.c b/src/shared/att.c
index 74a915001..f1e0f5922 100644
--- a/src/shared/att.c
+++ b/src/shared/att.c
@@ -34,6 +34,7 @@
#include "src/shared/util.h"
#include "src/shared/timeout.h"
#include "lib/bluetooth.h"
+#include "lib/l2cap.h"
#include "lib/uuid.h"
#include "src/shared/att.h"
#include "src/shared/crypto.h"
@@ -967,6 +968,18 @@ static void bt_att_free(struct bt_att *att)
free(att);
}
+static uint16_t get_l2cap_mtu(int fd)
+{
+ socklen_t len;
+ struct l2cap_options l2o;
+
+ len = sizeof(l2o);
+ if (getsockopt(fd, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0)
+ return 0;
+
+ return l2o.omtu;
+}
+
struct bt_att *bt_att_new(int fd, bool ext_signed)
{
struct bt_att *att;
@@ -976,10 +989,6 @@ struct bt_att *bt_att_new(int fd, bool ext_signed)
att = new0(struct bt_att, 1);
att->fd = fd;
- att->mtu = BT_ATT_DEFAULT_LE_MTU;
- att->buf = malloc(att->mtu);
- if (!att->buf)
- goto fail;
att->io = io_new(fd);
if (!att->io)
@@ -1005,6 +1014,18 @@ struct bt_att *bt_att_new(int fd, bool ext_signed)
if (!att->io_on_l2cap)
att->io_sec_level = BT_ATT_SECURITY_LOW;
+ if (bt_att_get_link_type(att) == BT_ATT_LINK_BREDR)
+ att->mtu = get_l2cap_mtu(att->fd);
+ else
+ att->mtu = BT_ATT_DEFAULT_LE_MTU;
+
+ if (att->mtu < BT_ATT_DEFAULT_LE_MTU)
+ goto fail;
+
+ att->buf = malloc(att->mtu);
+ if (!att->buf)
+ goto fail;
+
return bt_att_ref(att);
fail:
@@ -1099,6 +1120,28 @@ bool bt_att_set_mtu(struct bt_att *att, uint16_t mtu)
return true;
}
+uint8_t bt_att_get_link_type(struct bt_att *att)
+{
+ struct sockaddr_l2 src;
+ socklen_t len;
+
+ if (!att)
+ return -EINVAL;
+
+ if (!att->io_on_l2cap)
+ return BT_ATT_LINK_LOCAL;
+
+ len = sizeof(src);
+ memset(&src, 0, len);
+ if (getsockname(att->fd, (void *)&src, &len) < 0)
+ return -errno;
+
+ if (src.l2_bdaddr_type == BDADDR_BREDR)
+ return BT_ATT_LINK_BREDR;
+
+ return BT_ATT_LINK_LE;
+}
+
bool bt_att_set_timeout_cb(struct bt_att *att, bt_att_timeout_func_t callback,
void *user_data,
bt_att_destroy_func_t destroy)
diff --git a/src/shared/att.h b/src/shared/att.h
index 2a7f87e57..7bffee7d6 100644
--- a/src/shared/att.h
+++ b/src/shared/att.h
@@ -53,6 +53,7 @@ bool bt_att_set_debug(struct bt_att *att, bt_att_debug_func_t callback,
uint16_t bt_att_get_mtu(struct bt_att *att);
bool bt_att_set_mtu(struct bt_att *att, uint16_t mtu);
+uint8_t bt_att_get_link_type(struct bt_att *att);
bool bt_att_set_timeout_cb(struct bt_att *att, bt_att_timeout_func_t callback,
void *user_data,