Bluetooth: L2CAP: Refactor channel context by ident

Moves 'ident' member so far included in bt_l2cap_le_chan context only
to common bt_l2cap_chan context. The change is driven by sharing ability
to store/restore 'ident' on both transports and makes use of it only if
CoC is configured. For default configuration there's channel addition
helper to be used internally by dedicated macros managing channel
objects enlisted in connection tracker list.
The common member is used in matching outstanding connection responses
on LE and to prepare a ground for BR/EDR transport context when
there'll be a need to match response to original incoming connection
request after in-between security changes that can happen.

Change-Id: I1a4cad7cd53c74774604a0e9794607081a8b6e80
Signed-off-by: Arkadiusz Lichwa <arkadiusz.lichwa@tieto.com>
This commit is contained in:
Arkadiusz Lichwa 2016-07-19 15:07:26 +02:00 committed by Johan Hedberg
commit d5a07edde0
2 changed files with 56 additions and 15 deletions

View file

@ -84,6 +84,8 @@ struct bt_l2cap_chan {
bt_l2cap_chan_destroy_t destroy;
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
bt_l2cap_chan_state_t state;
/** Helps match request context during CoC */
uint8_t ident;
#endif /* CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL */
};
@ -107,8 +109,6 @@ struct bt_l2cap_le_chan {
struct bt_l2cap_le_endpoint rx;
/** Channel Transmission Endpoint */
struct bt_l2cap_le_endpoint tx;
/** Helps match request context for oustanding requests during CoC */
uint8_t ident;
/* Response Timeout eXpired (RTX) timer */
struct nano_delayed_work rtx_work;
/** Segment SDU packet from upper layer */

View file

@ -63,8 +63,21 @@
/* For now use MPS - SDU length to disable segmentation */
#define BT_L2CAP_MAX_LE_MTU (BT_L2CAP_MAX_LE_MPS - 2)
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
#define l2cap_lookup_ident(conn, ident) __l2cap_lookup_ident(conn, ident, false)
#define l2cap_remove_ident(conn, ident) __l2cap_lookup_ident(conn, ident, true)
#endif /* CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL */
enum l2cap_conn_list_action {
L2CAP_LOOKUP_CHAN,
L2CAP_DETACH_CHAN,
};
/* Wrapper macros making action on channel's list assigned to connection */
#define l2cap_lookup_chan(conn, chan) \
__l2cap_chan(conn, chan, L2CAP_LOOKUP_CHAN)
#define l2cap_detach_chan(conn, chan) \
__l2cap_chan(conn, chan, L2CAP_DETACH_CHAN)
static struct bt_l2cap_fixed_chan *le_channels;
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
@ -138,6 +151,7 @@ static struct bt_l2cap_le_chan *l2cap_chan_alloc_cid(struct bt_conn *conn,
return NULL;
}
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
static struct bt_l2cap_le_chan *
__l2cap_lookup_ident(struct bt_conn *conn, uint16_t ident, bool remove)
{
@ -145,15 +159,12 @@ __l2cap_lookup_ident(struct bt_conn *conn, uint16_t ident, bool remove)
for (chan = conn->channels, prev = NULL; chan;
prev = chan, chan = chan->_next) {
/* get the app's l2cap object where this chan is member */
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
if (ch->ident != ident) {
if (chan->ident != ident) {
continue;
}
if (!remove) {
return ch;
return BT_L2CAP_LE_CHAN(chan);
}
if (!prev) {
@ -162,7 +173,38 @@ __l2cap_lookup_ident(struct bt_conn *conn, uint16_t ident, bool remove)
prev->_next = chan->_next;
}
return ch;
return BT_L2CAP_LE_CHAN(chan);
}
return NULL;
}
#endif /* CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL */
static struct bt_l2cap_le_chan *__l2cap_chan(struct bt_conn *conn,
struct bt_l2cap_chan *ch,
enum l2cap_conn_list_action action)
{
struct bt_l2cap_chan *chan, *prev;
for (chan = conn->channels, prev = NULL; chan;
prev = chan, chan = chan->_next) {
if (chan != ch) {
continue;
}
switch (action) {
case L2CAP_DETACH_CHAN:
if (!prev) {
conn->channels = chan->_next;
} else {
prev->_next = chan->_next;
}
return BT_L2CAP_LE_CHAN(chan);
case L2CAP_LOOKUP_CHAN:
default:
return BT_L2CAP_LE_CHAN(chan);
}
}
return NULL;
@ -194,8 +236,7 @@ static void l2cap_rtx_timeout(struct nano_work *work)
BT_ERR("chan %p timeout", chan);
l2cap_remove_ident(chan->chan.conn, chan->ident);
l2cap_detach_chan(chan->chan.conn, &chan->chan);
bt_l2cap_chan_del(&chan->chan);
}
@ -727,7 +768,7 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
switch (result) {
case BT_L2CAP_SUCCESS:
/* Reset ident since it is no longer pending */
chan->ident = 0;
chan->chan.ident = 0;
chan->tx.cid = dcid;
chan->tx.mtu = mtu;
chan->tx.mps = mps;
@ -1238,11 +1279,11 @@ static int l2cap_le_connect(struct bt_conn *conn, struct bt_l2cap_le_chan *ch,
return -ENOMEM;
}
ch->ident = get_ident();
ch->chan.ident = get_ident();
hdr = net_buf_add(buf, sizeof(*hdr));
hdr->code = BT_L2CAP_LE_CONN_REQ;
hdr->ident = ch->ident;
hdr->ident = ch->chan.ident;
hdr->len = sys_cpu_to_le16(sizeof(*req));
req = net_buf_add(buf, sizeof(*req));
@ -1308,11 +1349,11 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
return -ENOMEM;
}
ch->ident = get_ident();
ch->chan.ident = get_ident();
hdr = net_buf_add(buf, sizeof(*hdr));
hdr->code = BT_L2CAP_DISCONN_REQ;
hdr->ident = ch->ident;
hdr->ident = ch->chan.ident;
hdr->len = sys_cpu_to_le16(sizeof(*req));
req = net_buf_add(buf, sizeof(*req));