summaryrefslogtreecommitdiff
path: root/src/shared/att.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/att.c')
-rw-r--r--src/shared/att.c51
1 files changed, 47 insertions, 4 deletions
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)