Bluetooth: Move L2CAP header encoding to sending stage

Encoding the L2CAP header when allocating the buffer means that we
must know the final size up-front. This is not always possible, so
move the header encoding to bt_l2cap_send() and only have the
bt_l2cap_create_pdu() function reserve enough headroom without
actually encoding anything.

Change-Id: Ic1c3b6b72c265cd0db4e835790fa915e0acd9388
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2015-05-20 14:58:18 +03:00 committed by Anas Nashif
commit 44e67698a6
6 changed files with 30 additions and 45 deletions

View file

@ -67,7 +67,7 @@ static void send_err_rsp(struct bt_conn *conn, uint8_t req, uint16_t handle,
rsp->handle = sys_cpu_to_le16(handle); rsp->handle = sys_cpu_to_le16(handle);
rsp->error = err; rsp->error = err;
bt_conn_send(conn, buf); bt_l2cap_send(conn, BT_L2CAP_CID_ATT, buf);
} }
static void att_mtu_req(struct bt_conn *conn, struct bt_buf *data) static void att_mtu_req(struct bt_conn *conn, struct bt_buf *data)
@ -112,7 +112,7 @@ static void att_mtu_req(struct bt_conn *conn, struct bt_buf *data)
rsp = bt_buf_add(buf, sizeof(*rsp)); rsp = bt_buf_add(buf, sizeof(*rsp));
rsp->mtu = sys_cpu_to_le16(mtu); rsp->mtu = sys_cpu_to_le16(mtu);
bt_conn_send(conn, buf); bt_l2cap_send(conn, BT_L2CAP_CID_ATT, buf);
} }
static bool range_is_valid(uint16_t start, uint16_t end, uint16_t *err) static bool range_is_valid(uint16_t start, uint16_t end, uint16_t *err)
@ -573,7 +573,7 @@ struct bt_buf *bt_att_create_pdu(struct bt_conn *conn, uint8_t op, size_t len)
struct bt_att_hdr *hdr; struct bt_att_hdr *hdr;
struct bt_buf *buf; struct bt_buf *buf;
buf = bt_l2cap_create_pdu(conn, BT_L2CAP_CID_ATT, sizeof(*hdr) + len); buf = bt_l2cap_create_pdu(conn);
if (!buf) { if (!buf) {
return NULL; return NULL;
} }

View file

@ -176,7 +176,7 @@ void bt_conn_send(struct bt_conn *conn, struct bt_buf *buf)
remaining -= len; remaining -= len;
while (remaining) { while (remaining) {
buf = bt_conn_create_pdu(conn); buf = bt_l2cap_create_pdu(conn);
len = min(remaining, dev->le_mtu); len = min(remaining, dev->le_mtu);
@ -366,10 +366,3 @@ void bt_conn_put(struct bt_conn *conn)
conn->handle = 0; conn->handle = 0;
} }
struct bt_buf *bt_conn_create_pdu(struct bt_conn *conn)
{
size_t reserve = conn->dev->drv->head_reserve;
return bt_buf_get(BT_ACL_OUT, reserve + sizeof(struct bt_hci_acl_hdr));
}

View file

@ -102,9 +102,6 @@ struct bt_conn {
char rx_stack[BT_CONN_RX_STACK_SIZE]; char rx_stack[BT_CONN_RX_STACK_SIZE];
}; };
/* Prepare a new buffer to be sent over the connection */
struct bt_buf *bt_conn_create_pdu(struct bt_conn *conn);
/* Process incoming data for a connection */ /* Process incoming data for a connection */
void bt_conn_recv(struct bt_conn *conn, struct bt_buf *buf, uint8_t flags); void bt_conn_recv(struct bt_conn *conn, struct bt_buf *buf, uint8_t flags);

View file

@ -67,29 +67,24 @@ static uint8_t get_ident(struct bt_conn *conn)
return conn->l2cap.ident; return conn->l2cap.ident;
} }
struct bt_buf *bt_l2cap_create_pdu(struct bt_conn *conn, uint16_t cid, struct bt_buf *bt_l2cap_create_pdu(struct bt_conn *conn)
size_t len) {
size_t head_reserve = sizeof(struct bt_l2cap_hdr) +
sizeof(struct bt_hci_acl_hdr) +
conn->dev->drv->head_reserve;
return bt_buf_get(BT_ACL_OUT, head_reserve);
}
void bt_l2cap_send(struct bt_conn *conn, uint16_t cid, struct bt_buf *buf)
{ {
struct bt_l2cap_hdr *hdr; struct bt_l2cap_hdr *hdr;
struct bt_buf *buf;
buf = bt_conn_create_pdu(conn); hdr = bt_buf_push(buf, sizeof(*hdr));
if (!buf) { hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr));
return NULL;
}
/* Check if buf created has enough space */
if (bt_buf_tailroom(buf) - sizeof(*hdr) < len) {
BT_ERR("Buffer too short\n");
bt_buf_put(buf);
return NULL;
}
hdr = bt_buf_add(buf, sizeof(*hdr));
hdr->len = sys_cpu_to_le16(len);
hdr->cid = sys_cpu_to_le16(cid); hdr->cid = sys_cpu_to_le16(cid);
return buf; bt_conn_send(conn, buf);
} }
static void rej_not_understood(struct bt_conn *conn, uint8_t ident) static void rej_not_understood(struct bt_conn *conn, uint8_t ident)
@ -98,8 +93,7 @@ static void rej_not_understood(struct bt_conn *conn, uint8_t ident)
struct bt_l2cap_sig_hdr *hdr; struct bt_l2cap_sig_hdr *hdr;
struct bt_buf *buf; struct bt_buf *buf;
buf = bt_l2cap_create_pdu(conn, BT_L2CAP_CID_LE_SIG, buf = bt_l2cap_create_pdu(conn);
sizeof(*hdr) + sizeof(*rej));
if (!buf) { if (!buf) {
return; return;
} }
@ -112,7 +106,7 @@ static void rej_not_understood(struct bt_conn *conn, uint8_t ident)
rej = bt_buf_add(buf, sizeof(*rej)); rej = bt_buf_add(buf, sizeof(*rej));
rej->reason = sys_cpu_to_le16(BT_L2CAP_REJ_NOT_UNDERSTOOD); rej->reason = sys_cpu_to_le16(BT_L2CAP_REJ_NOT_UNDERSTOOD);
bt_conn_send(conn, buf); bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
} }
static void le_conn_param_rsp(struct bt_conn *conn, struct bt_buf *buf) static void le_conn_param_rsp(struct bt_conn *conn, struct bt_buf *buf)
@ -212,8 +206,7 @@ void bt_l2cap_update_conn_param(struct bt_conn *conn)
return; return;
} }
buf = bt_l2cap_create_pdu(conn, BT_L2CAP_CID_LE_SIG, buf = bt_l2cap_create_pdu(conn);
sizeof(*hdr) + sizeof(*req));
if (!buf) { if (!buf) {
return; return;
} }
@ -229,5 +222,5 @@ void bt_l2cap_update_conn_param(struct bt_conn *conn)
req->latency = sys_cpu_to_le16(LE_CONN_LATENCY); req->latency = sys_cpu_to_le16(LE_CONN_LATENCY);
req->timeout = sys_cpu_to_le16(LE_CONN_TIMEOUT); req->timeout = sys_cpu_to_le16(LE_CONN_TIMEOUT);
bt_conn_send(conn, buf); bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
} }

View file

@ -69,8 +69,10 @@ struct bt_l2cap_conn_param_rsp {
} PACK_STRUCT; } PACK_STRUCT;
/* Prepare an L2CAP PDU to be sent over a connection */ /* Prepare an L2CAP PDU to be sent over a connection */
struct bt_buf *bt_l2cap_create_pdu(struct bt_conn *conn, uint16_t cid, struct bt_buf *bt_l2cap_create_pdu(struct bt_conn *conn);
size_t len);
/* Send L2CAP PDU over a connection */
void bt_l2cap_send(struct bt_conn *conn, uint16_t cid, struct bt_buf *buf);
/* Receive a new L2CAP PDU from a connection */ /* Receive a new L2CAP PDU from a connection */
void bt_l2cap_recv(struct bt_conn *conn, struct bt_buf *buf); void bt_l2cap_recv(struct bt_conn *conn, struct bt_buf *buf);

View file

@ -204,7 +204,7 @@ struct bt_buf *bt_smp_create_pdu(struct bt_conn *conn, uint8_t op, size_t len)
struct bt_smp_hdr *hdr; struct bt_smp_hdr *hdr;
struct bt_buf *buf; struct bt_buf *buf;
buf = bt_l2cap_create_pdu(conn, BT_L2CAP_CID_SMP, sizeof(*hdr) + len); buf = bt_l2cap_create_pdu(conn);
if (!buf) { if (!buf) {
return NULL; return NULL;
} }
@ -228,7 +228,7 @@ static void send_err_rsp(struct bt_conn *conn, uint8_t reason)
rsp = bt_buf_add(buf, sizeof(*rsp)); rsp = bt_buf_add(buf, sizeof(*rsp));
rsp->reason = reason; rsp->reason = reason;
bt_conn_send(conn, buf); bt_l2cap_send(conn, BT_L2CAP_CID_SMP, buf);
} }
static int smp_init(struct bt_conn_smp *smp) static int smp_init(struct bt_conn_smp *smp)
@ -295,7 +295,7 @@ static int smp_pairing_req(struct bt_conn *conn, struct bt_buf *buf)
smp->prsp[0] = BT_SMP_CMD_PAIRING_RSP; smp->prsp[0] = BT_SMP_CMD_PAIRING_RSP;
memcpy(smp->prsp + 1, rsp, sizeof(*rsp)); memcpy(smp->prsp + 1, rsp, sizeof(*rsp));
bt_conn_send(conn, rsp_buf); bt_l2cap_send(conn, BT_L2CAP_CID_SMP, rsp_buf);
return 0; return 0;
} }
@ -339,7 +339,7 @@ static int smp_pairing_confirm(struct bt_conn *conn, struct bt_buf *buf)
return BT_SMP_ERR_UNSPECIFIED; return BT_SMP_ERR_UNSPECIFIED;
} }
bt_conn_send(conn, rsp_buf); bt_l2cap_send(conn, BT_L2CAP_CID_SMP, rsp_buf);
return 0; return 0;
} }
@ -390,7 +390,7 @@ static int smp_pairing_random(struct bt_conn *conn, struct bt_buf *buf)
rsp = bt_buf_add(rsp_buf, sizeof(*rsp)); rsp = bt_buf_add(rsp_buf, sizeof(*rsp));
memcpy(rsp->val, smp->prnd, sizeof(rsp->val)); memcpy(rsp->val, smp->prnd, sizeof(rsp->val));
bt_conn_send(conn, rsp_buf); bt_l2cap_send(conn, BT_L2CAP_CID_SMP, rsp_buf);
/*smp_s1(smp->tk, smp->prnd, smp->rrnd, stk);*/ /*smp_s1(smp->tk, smp->prnd, smp->rrnd, stk);*/