Bluetooth: L2CAP: Use sys_slist_t for connection channels
This avoid having duplicated code for list manipulation in both LE and BR channels. Change-Id: I734635e8e51d4b826a3d45cda8551e1e509bd913 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
aa435c951f
commit
41a55893f7
6 changed files with 89 additions and 175 deletions
|
@ -74,7 +74,7 @@ struct bt_l2cap_chan {
|
|||
struct bt_conn *conn;
|
||||
/** Channel operations reference */
|
||||
struct bt_l2cap_chan_ops *ops;
|
||||
struct bt_l2cap_chan *_next;
|
||||
sys_snode_t node;
|
||||
bt_l2cap_chan_destroy_t destroy;
|
||||
/* Response Timeout eXpired (RTX) timer */
|
||||
struct k_delayed_work rtx_work;
|
||||
|
|
|
@ -1304,6 +1304,8 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
|
|||
k_fifo_init(&conn->tx_queue);
|
||||
k_poll_signal(&conn_change, 0);
|
||||
|
||||
sys_slist_init(&conn->channels);
|
||||
|
||||
bt_l2cap_connected(conn);
|
||||
notify_connected(conn);
|
||||
break;
|
||||
|
|
|
@ -94,7 +94,7 @@ struct bt_conn {
|
|||
struct k_fifo tx_queue;
|
||||
|
||||
/* Active L2CAP channels */
|
||||
struct bt_l2cap_chan *channels;
|
||||
sys_slist_t channels;
|
||||
|
||||
atomic_t ref;
|
||||
|
||||
|
|
|
@ -53,12 +53,6 @@
|
|||
#define l2cap_remove_ident(conn, ident) __l2cap_lookup_ident(conn, ident, true)
|
||||
#endif /* CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL */
|
||||
|
||||
/* Wrapper macros making action on channel's list assigned to connection */
|
||||
#define l2cap_lookup_chan(conn, chan) \
|
||||
__l2cap_chan(conn, chan, BT_L2CAP_CHAN_LOOKUP)
|
||||
#define l2cap_detach_chan(conn, chan) \
|
||||
__l2cap_chan(conn, chan, BT_L2CAP_CHAN_DETACH)
|
||||
|
||||
static struct bt_l2cap_fixed_chan *le_channels;
|
||||
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||
static struct bt_l2cap_server *servers;
|
||||
|
@ -100,6 +94,7 @@ void bt_l2cap_le_fixed_chan_register(struct bt_l2cap_fixed_chan *chan)
|
|||
le_channels = chan;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||
static struct bt_l2cap_le_chan *l2cap_chan_alloc_cid(struct bt_conn *conn,
|
||||
struct bt_l2cap_chan *chan)
|
||||
{
|
||||
|
@ -124,63 +119,41 @@ 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)
|
||||
{
|
||||
struct bt_l2cap_chan *chan, *prev;
|
||||
struct bt_l2cap_chan *chan;
|
||||
sys_snode_t *prev = NULL;
|
||||
|
||||
for (chan = conn->channels, prev = NULL; chan;
|
||||
prev = chan, chan = chan->_next) {
|
||||
if (chan->ident != ident) {
|
||||
continue;
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
if (chan->ident == ident) {
|
||||
if (remove) {
|
||||
sys_slist_remove(&conn->channels, prev,
|
||||
&chan->node);
|
||||
}
|
||||
|
||||
if (!remove) {
|
||||
return BT_L2CAP_LE_CHAN(chan);
|
||||
}
|
||||
|
||||
if (!prev) {
|
||||
conn->channels = chan->_next;
|
||||
} else {
|
||||
prev->_next = chan->_next;
|
||||
}
|
||||
|
||||
return BT_L2CAP_LE_CHAN(chan);
|
||||
prev = &chan->node;
|
||||
}
|
||||
|
||||
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)
|
||||
void bt_l2cap_chan_remove(struct bt_conn *conn, struct bt_l2cap_chan *ch)
|
||||
{
|
||||
struct bt_l2cap_chan *chan, *prev;
|
||||
struct bt_l2cap_chan *chan;
|
||||
sys_snode_t *prev = NULL;
|
||||
|
||||
for (chan = conn->channels, prev = NULL; chan;
|
||||
prev = chan, chan = chan->_next) {
|
||||
if (chan != ch) {
|
||||
continue;
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
if (chan == ch) {
|
||||
sys_slist_remove(&conn->channels, prev, &chan->node);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case BT_L2CAP_CHAN_DETACH:
|
||||
if (!prev) {
|
||||
conn->channels = chan->_next;
|
||||
} else {
|
||||
prev->_next = chan->_next;
|
||||
prev = &chan->node;
|
||||
}
|
||||
|
||||
return BT_L2CAP_LE_CHAN(chan);
|
||||
case BT_L2CAP_CHAN_LOOKUP:
|
||||
default:
|
||||
return BT_L2CAP_LE_CHAN(chan);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||
|
@ -286,7 +259,7 @@ static void l2cap_rtx_timeout(struct k_work *work)
|
|||
|
||||
BT_ERR("chan %p timeout", chan);
|
||||
|
||||
l2cap_detach_chan(chan->chan.conn, &chan->chan);
|
||||
bt_l2cap_chan_remove(chan->chan.conn, &chan->chan);
|
||||
bt_l2cap_chan_del(&chan->chan);
|
||||
}
|
||||
|
||||
|
@ -294,8 +267,7 @@ void bt_l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
|
|||
bt_l2cap_chan_destroy_t destroy)
|
||||
{
|
||||
/* Attach channel to the connection */
|
||||
chan->_next = conn->channels;
|
||||
conn->channels = chan;
|
||||
sys_slist_append(&conn->channels, &chan->node);
|
||||
chan->conn = conn;
|
||||
chan->destroy = destroy;
|
||||
|
||||
|
@ -305,7 +277,13 @@ void bt_l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
|
|||
static bool l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
|
||||
bt_l2cap_chan_destroy_t destroy)
|
||||
{
|
||||
struct bt_l2cap_le_chan *ch = l2cap_chan_alloc_cid(conn, chan);
|
||||
struct bt_l2cap_le_chan *ch;
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||
ch = l2cap_chan_alloc_cid(conn, chan);
|
||||
#else
|
||||
ch = BT_L2CAP_LE_CHAN(chan);
|
||||
#endif
|
||||
|
||||
if (!ch) {
|
||||
BT_ERR("Unable to allocate L2CAP CID");
|
||||
|
@ -364,20 +342,11 @@ void bt_l2cap_connected(struct bt_conn *conn)
|
|||
|
||||
void bt_l2cap_disconnected(struct bt_conn *conn)
|
||||
{
|
||||
struct bt_l2cap_chan *chan;
|
||||
|
||||
for (chan = conn->channels; chan;) {
|
||||
struct bt_l2cap_chan *next;
|
||||
|
||||
/* prefetch since disconnected callback may cleanup */
|
||||
next = chan->_next;
|
||||
struct bt_l2cap_chan *chan, *next;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn->channels, chan, next, node) {
|
||||
bt_l2cap_chan_del(chan);
|
||||
|
||||
chan = next;
|
||||
}
|
||||
|
||||
conn->channels = NULL;
|
||||
}
|
||||
|
||||
static struct net_buf *l2cap_create_le_sig_pdu(uint8_t code, uint8_t ident,
|
||||
|
@ -448,7 +417,7 @@ static void l2cap_le_encrypt_change(struct bt_l2cap_chan *chan, uint8_t status)
|
|||
}
|
||||
|
||||
if (status) {
|
||||
l2cap_detach_chan(chan->conn, chan);
|
||||
bt_l2cap_chan_remove(chan->conn, chan);
|
||||
bt_l2cap_chan_del(chan);
|
||||
return;
|
||||
}
|
||||
|
@ -468,7 +437,7 @@ void bt_l2cap_encrypt_change(struct bt_conn *conn, uint8_t hci_status)
|
|||
return;
|
||||
}
|
||||
|
||||
for (chan = conn->channels; chan; chan = chan->_next) {
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||
l2cap_le_encrypt_change(chan, hci_status);
|
||||
#endif
|
||||
|
@ -576,6 +545,34 @@ static void le_conn_param_update_req(struct bt_l2cap *l2cap, uint8_t ident,
|
|||
}
|
||||
#endif /* CONFIG_BLUETOOTH_CENTRAL */
|
||||
|
||||
struct bt_l2cap_chan *bt_l2cap_le_lookup_tx_cid(struct bt_conn *conn,
|
||||
uint16_t cid)
|
||||
{
|
||||
struct bt_l2cap_chan *chan;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
if (BT_L2CAP_LE_CHAN(chan)->tx.cid == cid) {
|
||||
return chan;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_l2cap_chan *bt_l2cap_le_lookup_rx_cid(struct bt_conn *conn,
|
||||
uint16_t cid)
|
||||
{
|
||||
struct bt_l2cap_chan *chan;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
if (BT_L2CAP_LE_CHAN(chan)->rx.cid == cid) {
|
||||
return chan;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||
static struct bt_l2cap_server *l2cap_server_lookup_psm(uint16_t psm)
|
||||
{
|
||||
|
@ -806,29 +803,21 @@ rsp:
|
|||
static struct bt_l2cap_le_chan *l2cap_remove_tx_cid(struct bt_conn *conn,
|
||||
uint16_t cid)
|
||||
{
|
||||
struct bt_l2cap_chan *chan, *prev;
|
||||
struct bt_l2cap_chan *chan;
|
||||
sys_snode_t *prev = NULL;
|
||||
|
||||
/* Protect fixed channels against accidental removal */
|
||||
if (!L2CAP_LE_CID_IS_DYN(cid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (chan = conn->channels, prev = NULL; chan;
|
||||
prev = chan, chan = chan->_next) {
|
||||
/* get the app's l2cap object wherein this chan is contained */
|
||||
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
|
||||
|
||||
if (ch->tx.cid != cid) {
|
||||
continue;
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
if (BT_L2CAP_LE_CHAN(chan)->rx.cid == cid) {
|
||||
sys_slist_remove(&conn->channels, prev, &chan->node);
|
||||
return BT_L2CAP_LE_CHAN(chan);
|
||||
}
|
||||
|
||||
if (!prev) {
|
||||
conn->channels = chan->_next;
|
||||
} else {
|
||||
prev->_next = chan->_next;
|
||||
}
|
||||
|
||||
return ch;
|
||||
prev = &chan->node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -969,7 +958,7 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
|
|||
if (l2cap_change_security(chan, result) == 0) {
|
||||
return;
|
||||
}
|
||||
l2cap_detach_chan(conn, &chan->chan);
|
||||
bt_l2cap_chan_remove(conn, &chan->chan);
|
||||
default:
|
||||
bt_l2cap_chan_del(&chan->chan);
|
||||
}
|
||||
|
@ -1564,37 +1553,6 @@ void bt_l2cap_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
struct bt_l2cap_chan *bt_l2cap_le_lookup_tx_cid(struct bt_conn *conn,
|
||||
uint16_t cid)
|
||||
{
|
||||
struct bt_l2cap_chan *chan;
|
||||
|
||||
for (chan = conn->channels; chan; chan = chan->_next) {
|
||||
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
|
||||
|
||||
if (ch->tx.cid == cid)
|
||||
return chan;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_l2cap_chan *bt_l2cap_le_lookup_rx_cid(struct bt_conn *conn,
|
||||
uint16_t cid)
|
||||
{
|
||||
struct bt_l2cap_chan *chan;
|
||||
|
||||
for (chan = conn->channels; chan; chan = chan->_next) {
|
||||
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
|
||||
|
||||
if (ch->rx.cid == cid) {
|
||||
return chan;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||
static int l2cap_le_connect(struct bt_conn *conn, struct bt_l2cap_le_chan *ch,
|
||||
uint16_t psm)
|
||||
|
|
|
@ -60,12 +60,6 @@
|
|||
*/
|
||||
#define L2CAP_FEAT_FIXED_CHAN_MASK 0x00000080
|
||||
|
||||
/* Wrapper macros making action on channel's list assigned to connection */
|
||||
#define l2cap_br_lookup_chan(conn, chan) \
|
||||
__l2cap_chan(conn, chan, BT_L2CAP_CHAN_LOOKUP)
|
||||
#define l2cap_br_detach_chan(conn, chan) \
|
||||
__l2cap_chan(conn, chan, BT_L2CAP_CHAN_DETACH)
|
||||
|
||||
enum {
|
||||
/* Connection oriented channels flags */
|
||||
L2CAP_FLAG_CONN_LCONF_DONE, /* local config accepted by remote */
|
||||
|
@ -105,10 +99,8 @@ struct bt_l2cap_chan *bt_l2cap_br_lookup_rx_cid(struct bt_conn *conn,
|
|||
{
|
||||
struct bt_l2cap_chan *chan;
|
||||
|
||||
for (chan = conn->channels; chan; chan = chan->_next) {
|
||||
struct bt_l2cap_br_chan *ch = BR_CHAN(chan);
|
||||
|
||||
if (ch->rx.cid == cid) {
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
if (BR_CHAN(chan)->rx.cid == cid) {
|
||||
return chan;
|
||||
}
|
||||
}
|
||||
|
@ -116,15 +108,13 @@ struct bt_l2cap_chan *bt_l2cap_br_lookup_rx_cid(struct bt_conn *conn,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct bt_l2cap_chan *bt_l2cap_br_lookup_tx_cid(struct bt_conn *conn,
|
||||
struct bt_l2cap_chan *bt_l2cap_br_lookup_tx_cid(struct bt_conn *conn,
|
||||
uint16_t cid)
|
||||
{
|
||||
struct bt_l2cap_chan *chan;
|
||||
|
||||
for (chan = conn->channels; chan; chan = chan->_next) {
|
||||
struct bt_l2cap_br_chan *ch = BR_CHAN(chan);
|
||||
|
||||
if (ch->tx.cid == cid) {
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
if (BR_CHAN(chan)->tx.cid == cid) {
|
||||
return chan;
|
||||
}
|
||||
}
|
||||
|
@ -160,40 +150,9 @@ l2cap_br_chan_alloc_cid(struct bt_conn *conn, struct bt_l2cap_chan *chan)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct bt_l2cap_br_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 BT_L2CAP_CHAN_DETACH:
|
||||
if (!prev) {
|
||||
conn->channels = chan->_next;
|
||||
} else {
|
||||
prev->_next = chan->_next;
|
||||
}
|
||||
|
||||
return BR_CHAN(chan);
|
||||
case BT_L2CAP_CHAN_LOOKUP:
|
||||
default:
|
||||
return BR_CHAN(chan);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void l2cap_br_chan_cleanup(struct bt_l2cap_chan *chan)
|
||||
{
|
||||
l2cap_br_detach_chan(chan->conn, chan);
|
||||
bt_l2cap_chan_remove(chan->conn, chan);
|
||||
bt_l2cap_chan_del(chan);
|
||||
}
|
||||
|
||||
|
@ -1090,29 +1049,21 @@ send_rsp:
|
|||
static struct bt_l2cap_br_chan *l2cap_br_remove_tx_cid(struct bt_conn *conn,
|
||||
uint16_t cid)
|
||||
{
|
||||
struct bt_l2cap_chan *chan, *prev;
|
||||
struct bt_l2cap_chan *chan;
|
||||
sys_snode_t *prev = NULL;
|
||||
|
||||
/* Protect fixed channels against accidental removal */
|
||||
if (!L2CAP_BR_CID_IS_DYN(cid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (chan = conn->channels, prev = NULL; chan;
|
||||
prev = chan, chan = chan->_next) {
|
||||
/* get the app's l2cap object wherein this chan is contained */
|
||||
struct bt_l2cap_br_chan *ch = BR_CHAN(chan);
|
||||
|
||||
if (ch->tx.cid != cid) {
|
||||
continue;
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
if (BR_CHAN(chan)->rx.cid == cid) {
|
||||
sys_slist_remove(&conn->channels, prev, &chan->node);
|
||||
return BR_CHAN(chan);
|
||||
}
|
||||
|
||||
if (!prev) {
|
||||
conn->channels = chan->_next;
|
||||
} else {
|
||||
prev->_next = chan->_next;
|
||||
}
|
||||
|
||||
return ch;
|
||||
prev = &chan->node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -1518,7 +1469,7 @@ void l2cap_br_encrypt_change(struct bt_conn *conn, uint8_t hci_status)
|
|||
{
|
||||
struct bt_l2cap_chan *chan;
|
||||
|
||||
for (chan = conn->channels; chan; chan = chan->_next) {
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||
l2cap_br_conn_pend(chan, hci_status);
|
||||
|
||||
if (chan->ops && chan->ops->encrypt_change) {
|
||||
|
|
|
@ -215,6 +215,9 @@ void bt_l2cap_disconnected(struct bt_conn *conn);
|
|||
void bt_l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
|
||||
bt_l2cap_chan_destroy_t destroy);
|
||||
|
||||
/* Remove channel from the connection */
|
||||
void bt_l2cap_chan_remove(struct bt_conn *conn, struct bt_l2cap_chan *chan);
|
||||
|
||||
/* Delete channel */
|
||||
void bt_l2cap_chan_del(struct bt_l2cap_chan *chan);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue