Bluetooth: Add code to handle BT_ATT_OP_MTU_REQ

Add code to respond to BT_ATT_OP_MTU_REQ with BT_ATT_OP_MTU_RSP
selecting the MTU based on the amount of room bt_buf has:

< ACL Data RX: Handle 39 flags 0x02 dlen 7
      ATT: Exchange MTU Response (0x03) len 2
        Server RX MTU: 65

Change-Id: I47b8179fcee0d6adff5761abc37cfcb1ed636d65
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz 2015-05-04 17:22:10 +03:00 committed by Anas Nashif
commit 028edd59ba
2 changed files with 52 additions and 0 deletions

View file

@ -35,6 +35,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <misc/byteorder.h> #include <misc/byteorder.h>
#include <misc/util.h>
#include <bluetooth/hci.h> #include <bluetooth/hci.h>
#include <bluetooth/bluetooth.h> #include <bluetooth/bluetooth.h>
@ -63,6 +64,51 @@ static void send_err_rsp(struct bt_conn *conn, uint8_t req, uint16_t handle,
bt_conn_send(conn, buf); bt_conn_send(conn, buf);
} }
static void att_mtu_req(struct bt_conn *conn, struct bt_buf *data)
{
struct bt_att_exchange_mtu_req *req;
struct bt_att_exchange_mtu_rsp *rsp;
struct bt_buf *buf;
uint16_t mtu;
if (data->len != sizeof(*req)) {
send_err_rsp(conn, BT_ATT_OP_MTU_REQ, 0,
BT_ATT_ERR_INVALID_PDU);
return;
}
req = (void *)data->data;
mtu = sys_le16_to_cpu(req->mtu);
BT_DBG("Client MTU %u\n", mtu);
if (mtu > BT_ATT_MAX_LE_MTU || mtu < BT_ATT_DEFAULT_LE_MTU) {
send_err_rsp(conn, BT_ATT_OP_MTU_REQ, 0,
BT_ATT_ERR_INVALID_PDU);
return;
}
buf = bt_att_create_pdu(conn, BT_ATT_OP_MTU_RSP, sizeof(*rsp));
if (!buf) {
return;
}
/* Select MTU based on the amount of room we have in bt_buf including
* one extra byte for ATT header.
*/
mtu = min(mtu, bt_buf_tailroom(buf) + 1);
BT_DBG("Server MTU %u\n", mtu);
/* TODO: Store the MTU negotiated */
rsp = (void *)bt_buf_add(buf, sizeof(*rsp));
rsp->mtu = sys_cpu_to_le16(mtu);
bt_conn_send(conn, buf);
}
void bt_att_recv(struct bt_conn *conn, struct bt_buf *buf) void bt_att_recv(struct bt_conn *conn, struct bt_buf *buf)
{ {
struct bt_att_hdr *hdr = (void *)buf->data; struct bt_att_hdr *hdr = (void *)buf->data;
@ -77,6 +123,9 @@ void bt_att_recv(struct bt_conn *conn, struct bt_buf *buf)
bt_buf_pull(buf, sizeof(*hdr)); bt_buf_pull(buf, sizeof(*hdr));
switch (hdr->code) { switch (hdr->code) {
case BT_ATT_OP_MTU_REQ:
att_mtu_req(conn, buf);
break;
default: default:
BT_DBG("Unhandled ATT code %u\n", hdr->code); BT_DBG("Unhandled ATT code %u\n", hdr->code);
send_err_rsp(conn, hdr->code, 0, BT_ATT_ERR_NOT_SUPPORTED); send_err_rsp(conn, hdr->code, 0, BT_ATT_ERR_NOT_SUPPORTED);

View file

@ -30,6 +30,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#define BT_ATT_DEFAULT_LE_MTU 23
#define BT_ATT_MAX_LE_MTU 517
struct bt_att_hdr { struct bt_att_hdr {
uint8_t code; uint8_t code;
} PACK_STRUCT; } PACK_STRUCT;