diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2016-07-08 11:43:32 +0300 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2016-07-13 14:03:45 +0300 |
commit | 05bdde05b2176b42f6334c4f478395cfc6943abf (patch) | |
tree | b6ef4158acd0f567341c0ecb7244f04a4e9a9f6b | |
parent | fc9ccf6154a0c090e641569a9567a40eb1c721f5 (diff) | |
download | bluez-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.h | 4 | ||||
-rw-r--r-- | src/shared/att.c | 51 | ||||
-rw-r--r-- | src/shared/att.h | 1 |
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, |