Bluetooth: L2CAP: Introduce BT_L2CAP_STATUS_SHUTDOWN flag
This introduces BT_L2CAP_STATUS_SHUTDOWN which is used to indicate when a channel has been shutdown. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
cbcbfee41d
commit
bdc1eff35b
2 changed files with 61 additions and 1 deletions
|
@ -74,6 +74,13 @@ typedef enum bt_l2cap_chan_status {
|
||||||
/** Channel output status */
|
/** Channel output status */
|
||||||
BT_L2CAP_STATUS_OUT,
|
BT_L2CAP_STATUS_OUT,
|
||||||
|
|
||||||
|
/** Channel shutdown status
|
||||||
|
*
|
||||||
|
* Once this status is notified it means the channel will no longer be
|
||||||
|
* able to transmit or receive data.
|
||||||
|
*/
|
||||||
|
BT_L2CAP_STATUS_SHUTDOWN,
|
||||||
|
|
||||||
/* Total number of status - must be at the end of the enum */
|
/* Total number of status - must be at the end of the enum */
|
||||||
BT_L2CAP_NUM_STATUS,
|
BT_L2CAP_NUM_STATUS,
|
||||||
} __packed bt_l2cap_chan_status_t;
|
} __packed bt_l2cap_chan_status_t;
|
||||||
|
|
|
@ -255,6 +255,8 @@ destroy:
|
||||||
if (chan->destroy) {
|
if (chan->destroy) {
|
||||||
chan->destroy(chan);
|
chan->destroy(chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_clear(chan->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void l2cap_rtx_timeout(struct k_work *work)
|
static void l2cap_rtx_timeout(struct k_work *work)
|
||||||
|
@ -1503,6 +1505,44 @@ static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
||||||
|
static void l2cap_chan_shutdown(struct bt_l2cap_chan *chan)
|
||||||
|
{
|
||||||
|
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
|
||||||
|
struct net_buf *buf;
|
||||||
|
|
||||||
|
BT_DBG("chan %p", chan);
|
||||||
|
|
||||||
|
atomic_set_bit(chan->status, BT_L2CAP_STATUS_SHUTDOWN);
|
||||||
|
|
||||||
|
/* Destroy segmented SDU if it exists */
|
||||||
|
if (ch->_sdu) {
|
||||||
|
net_buf_unref(ch->_sdu);
|
||||||
|
ch->_sdu = NULL;
|
||||||
|
ch->_sdu_len = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup outstanding request */
|
||||||
|
if (ch->tx_buf) {
|
||||||
|
net_buf_unref(ch->tx_buf);
|
||||||
|
ch->tx_buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove buffers on the TX queue */
|
||||||
|
while ((buf = net_buf_get(&ch->tx_queue, K_NO_WAIT))) {
|
||||||
|
net_buf_unref(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove buffers on the RX queue */
|
||||||
|
while ((buf = net_buf_get(&ch->rx_queue, K_NO_WAIT))) {
|
||||||
|
net_buf_unref(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update status */
|
||||||
|
if (chan->ops->status) {
|
||||||
|
chan->ops->status(chan, chan->status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan,
|
static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan,
|
||||||
struct net_buf *buf, u16_t credits)
|
struct net_buf *buf, u16_t credits)
|
||||||
{
|
{
|
||||||
|
@ -1517,7 +1557,10 @@ static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan,
|
||||||
sizeof(*ev));
|
sizeof(*ev));
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
BT_ERR("Unable to send credits update");
|
BT_ERR("Unable to send credits update");
|
||||||
bt_l2cap_chan_disconnect(&chan->chan);
|
/* Disconnect would probably not work either so the only
|
||||||
|
* option left is to shutdown the channel.
|
||||||
|
*/
|
||||||
|
l2cap_chan_shutdown(&chan->chan);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1727,6 +1770,12 @@ static void l2cap_chan_recv_queue(struct bt_l2cap_le_chan *chan,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (atomic_test_bit(chan->chan.status, BT_L2CAP_STATUS_SHUTDOWN)) {
|
||||||
|
BT_WARN("Ignoring data received while channel has shutdown");
|
||||||
|
net_buf_unref(buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
net_buf_put(&chan->rx_queue, buf);
|
net_buf_put(&chan->rx_queue, buf);
|
||||||
k_work_submit(&chan->rx_work);
|
k_work_submit(&chan->rx_work);
|
||||||
}
|
}
|
||||||
|
@ -1956,6 +2005,10 @@ int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (atomic_test_bit(chan->status, BT_L2CAP_STATUS_SHUTDOWN)) {
|
||||||
|
return -ESHUTDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_BREDR) &&
|
if (IS_ENABLED(CONFIG_BT_BREDR) &&
|
||||||
chan->conn->type == BT_CONN_TYPE_BR) {
|
chan->conn->type == BT_CONN_TYPE_BR) {
|
||||||
return bt_l2cap_br_chan_send(chan, buf);
|
return bt_l2cap_br_chan_send(chan, buf);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue