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;
|
struct bt_conn *conn;
|
||||||
/** Channel operations reference */
|
/** Channel operations reference */
|
||||||
struct bt_l2cap_chan_ops *ops;
|
struct bt_l2cap_chan_ops *ops;
|
||||||
struct bt_l2cap_chan *_next;
|
sys_snode_t node;
|
||||||
bt_l2cap_chan_destroy_t destroy;
|
bt_l2cap_chan_destroy_t destroy;
|
||||||
/* Response Timeout eXpired (RTX) timer */
|
/* Response Timeout eXpired (RTX) timer */
|
||||||
struct k_delayed_work rtx_work;
|
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_fifo_init(&conn->tx_queue);
|
||||||
k_poll_signal(&conn_change, 0);
|
k_poll_signal(&conn_change, 0);
|
||||||
|
|
||||||
|
sys_slist_init(&conn->channels);
|
||||||
|
|
||||||
bt_l2cap_connected(conn);
|
bt_l2cap_connected(conn);
|
||||||
notify_connected(conn);
|
notify_connected(conn);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -94,7 +94,7 @@ struct bt_conn {
|
||||||
struct k_fifo tx_queue;
|
struct k_fifo tx_queue;
|
||||||
|
|
||||||
/* Active L2CAP channels */
|
/* Active L2CAP channels */
|
||||||
struct bt_l2cap_chan *channels;
|
sys_slist_t channels;
|
||||||
|
|
||||||
atomic_t ref;
|
atomic_t ref;
|
||||||
|
|
||||||
|
|
|
@ -53,12 +53,6 @@
|
||||||
#define l2cap_remove_ident(conn, ident) __l2cap_lookup_ident(conn, ident, true)
|
#define l2cap_remove_ident(conn, ident) __l2cap_lookup_ident(conn, ident, true)
|
||||||
#endif /* CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL */
|
#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;
|
static struct bt_l2cap_fixed_chan *le_channels;
|
||||||
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||||
static struct bt_l2cap_server *servers;
|
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;
|
le_channels = chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||||
static struct bt_l2cap_le_chan *l2cap_chan_alloc_cid(struct bt_conn *conn,
|
static struct bt_l2cap_le_chan *l2cap_chan_alloc_cid(struct bt_conn *conn,
|
||||||
struct bt_l2cap_chan *chan)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
|
||||||
static struct bt_l2cap_le_chan *
|
static struct bt_l2cap_le_chan *
|
||||||
__l2cap_lookup_ident(struct bt_conn *conn, uint16_t ident, bool remove)
|
__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;
|
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||||
prev = chan, chan = chan->_next) {
|
if (chan->ident == ident) {
|
||||||
if (chan->ident != ident) {
|
if (remove) {
|
||||||
continue;
|
sys_slist_remove(&conn->channels, prev,
|
||||||
}
|
&chan->node);
|
||||||
|
}
|
||||||
if (!remove) {
|
|
||||||
return BT_L2CAP_LE_CHAN(chan);
|
return BT_L2CAP_LE_CHAN(chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prev) {
|
prev = &chan->node;
|
||||||
conn->channels = chan->_next;
|
|
||||||
} else {
|
|
||||||
prev->_next = chan->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BT_L2CAP_LE_CHAN(chan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL */
|
#endif /* CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL */
|
||||||
|
|
||||||
static struct bt_l2cap_le_chan *__l2cap_chan(struct bt_conn *conn,
|
void bt_l2cap_chan_remove(struct bt_conn *conn, struct bt_l2cap_chan *ch)
|
||||||
struct bt_l2cap_chan *ch,
|
|
||||||
enum l2cap_conn_list_action action)
|
|
||||||
{
|
{
|
||||||
struct bt_l2cap_chan *chan, *prev;
|
struct bt_l2cap_chan *chan;
|
||||||
|
sys_snode_t *prev = NULL;
|
||||||
|
|
||||||
for (chan = conn->channels, prev = NULL; chan;
|
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||||
prev = chan, chan = chan->_next) {
|
if (chan == ch) {
|
||||||
if (chan != ch) {
|
sys_slist_remove(&conn->channels, prev, &chan->node);
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (action) {
|
prev = &chan->node;
|
||||||
case BT_L2CAP_CHAN_DETACH:
|
|
||||||
if (!prev) {
|
|
||||||
conn->channels = chan->_next;
|
|
||||||
} else {
|
|
||||||
prev->_next = chan->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
#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);
|
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);
|
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)
|
bt_l2cap_chan_destroy_t destroy)
|
||||||
{
|
{
|
||||||
/* Attach channel to the connection */
|
/* Attach channel to the connection */
|
||||||
chan->_next = conn->channels;
|
sys_slist_append(&conn->channels, &chan->node);
|
||||||
conn->channels = chan;
|
|
||||||
chan->conn = conn;
|
chan->conn = conn;
|
||||||
chan->destroy = destroy;
|
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,
|
static bool l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
|
||||||
bt_l2cap_chan_destroy_t destroy)
|
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) {
|
if (!ch) {
|
||||||
BT_ERR("Unable to allocate L2CAP CID");
|
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)
|
void bt_l2cap_disconnected(struct bt_conn *conn)
|
||||||
{
|
{
|
||||||
struct bt_l2cap_chan *chan;
|
struct bt_l2cap_chan *chan, *next;
|
||||||
|
|
||||||
for (chan = conn->channels; chan;) {
|
|
||||||
struct bt_l2cap_chan *next;
|
|
||||||
|
|
||||||
/* prefetch since disconnected callback may cleanup */
|
|
||||||
next = chan->_next;
|
|
||||||
|
|
||||||
|
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn->channels, chan, next, node) {
|
||||||
bt_l2cap_chan_del(chan);
|
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,
|
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) {
|
if (status) {
|
||||||
l2cap_detach_chan(chan->conn, chan);
|
bt_l2cap_chan_remove(chan->conn, chan);
|
||||||
bt_l2cap_chan_del(chan);
|
bt_l2cap_chan_del(chan);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -468,7 +437,7 @@ void bt_l2cap_encrypt_change(struct bt_conn *conn, uint8_t hci_status)
|
||||||
return;
|
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)
|
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||||
l2cap_le_encrypt_change(chan, hci_status);
|
l2cap_le_encrypt_change(chan, hci_status);
|
||||||
#endif
|
#endif
|
||||||
|
@ -576,6 +545,34 @@ static void le_conn_param_update_req(struct bt_l2cap *l2cap, uint8_t ident,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BLUETOOTH_CENTRAL */
|
#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)
|
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||||
static struct bt_l2cap_server *l2cap_server_lookup_psm(uint16_t psm)
|
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,
|
static struct bt_l2cap_le_chan *l2cap_remove_tx_cid(struct bt_conn *conn,
|
||||||
uint16_t cid)
|
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 */
|
/* Protect fixed channels against accidental removal */
|
||||||
if (!L2CAP_LE_CID_IS_DYN(cid)) {
|
if (!L2CAP_LE_CID_IS_DYN(cid)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (chan = conn->channels, prev = NULL; chan;
|
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||||
prev = chan, chan = chan->_next) {
|
if (BT_L2CAP_LE_CHAN(chan)->rx.cid == cid) {
|
||||||
/* get the app's l2cap object wherein this chan is contained */
|
sys_slist_remove(&conn->channels, prev, &chan->node);
|
||||||
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
|
return BT_L2CAP_LE_CHAN(chan);
|
||||||
|
|
||||||
if (ch->tx.cid != cid) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prev) {
|
prev = &chan->node;
|
||||||
conn->channels = chan->_next;
|
|
||||||
} else {
|
|
||||||
prev->_next = chan->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
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) {
|
if (l2cap_change_security(chan, result) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
l2cap_detach_chan(conn, &chan->chan);
|
bt_l2cap_chan_remove(conn, &chan->chan);
|
||||||
default:
|
default:
|
||||||
bt_l2cap_chan_del(&chan->chan);
|
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)
|
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
|
||||||
static int l2cap_le_connect(struct bt_conn *conn, struct bt_l2cap_le_chan *ch,
|
static int l2cap_le_connect(struct bt_conn *conn, struct bt_l2cap_le_chan *ch,
|
||||||
uint16_t psm)
|
uint16_t psm)
|
||||||
|
|
|
@ -60,12 +60,6 @@
|
||||||
*/
|
*/
|
||||||
#define L2CAP_FEAT_FIXED_CHAN_MASK 0x00000080
|
#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 {
|
enum {
|
||||||
/* Connection oriented channels flags */
|
/* Connection oriented channels flags */
|
||||||
L2CAP_FLAG_CONN_LCONF_DONE, /* local config accepted by remote */
|
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;
|
struct bt_l2cap_chan *chan;
|
||||||
|
|
||||||
for (chan = conn->channels; chan; chan = chan->_next) {
|
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||||
struct bt_l2cap_br_chan *ch = BR_CHAN(chan);
|
if (BR_CHAN(chan)->rx.cid == cid) {
|
||||||
|
|
||||||
if (ch->rx.cid == cid) {
|
|
||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,15 +108,13 @@ struct bt_l2cap_chan *bt_l2cap_br_lookup_rx_cid(struct bt_conn *conn,
|
||||||
return NULL;
|
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)
|
uint16_t cid)
|
||||||
{
|
{
|
||||||
struct bt_l2cap_chan *chan;
|
struct bt_l2cap_chan *chan;
|
||||||
|
|
||||||
for (chan = conn->channels; chan; chan = chan->_next) {
|
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||||
struct bt_l2cap_br_chan *ch = BR_CHAN(chan);
|
if (BR_CHAN(chan)->tx.cid == cid) {
|
||||||
|
|
||||||
if (ch->tx.cid == cid) {
|
|
||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,40 +150,9 @@ l2cap_br_chan_alloc_cid(struct bt_conn *conn, struct bt_l2cap_chan *chan)
|
||||||
return NULL;
|
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)
|
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);
|
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,
|
static struct bt_l2cap_br_chan *l2cap_br_remove_tx_cid(struct bt_conn *conn,
|
||||||
uint16_t cid)
|
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 */
|
/* Protect fixed channels against accidental removal */
|
||||||
if (!L2CAP_BR_CID_IS_DYN(cid)) {
|
if (!L2CAP_BR_CID_IS_DYN(cid)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (chan = conn->channels, prev = NULL; chan;
|
SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
|
||||||
prev = chan, chan = chan->_next) {
|
if (BR_CHAN(chan)->rx.cid == cid) {
|
||||||
/* get the app's l2cap object wherein this chan is contained */
|
sys_slist_remove(&conn->channels, prev, &chan->node);
|
||||||
struct bt_l2cap_br_chan *ch = BR_CHAN(chan);
|
return BR_CHAN(chan);
|
||||||
|
|
||||||
if (ch->tx.cid != cid) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prev) {
|
prev = &chan->node;
|
||||||
conn->channels = chan->_next;
|
|
||||||
} else {
|
|
||||||
prev->_next = chan->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1518,7 +1469,7 @@ void l2cap_br_encrypt_change(struct bt_conn *conn, uint8_t hci_status)
|
||||||
{
|
{
|
||||||
struct bt_l2cap_chan *chan;
|
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);
|
l2cap_br_conn_pend(chan, hci_status);
|
||||||
|
|
||||||
if (chan->ops && chan->ops->encrypt_change) {
|
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,
|
void bt_l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
|
||||||
bt_l2cap_chan_destroy_t destroy);
|
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 */
|
/* Delete channel */
|
||||||
void bt_l2cap_chan_del(struct bt_l2cap_chan *chan);
|
void bt_l2cap_chan_del(struct bt_l2cap_chan *chan);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue