Bluetooth: L2CAP: Add callback to notify status
This adds a new callback for L2CAP channels which notities whenever status has changed so the channel user can can for example resume or suspend sending depending on the status. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
270e8342f5
commit
c904a45d8f
2 changed files with 42 additions and 0 deletions
|
@ -68,6 +68,15 @@ typedef enum bt_l2cap_chan_state {
|
|||
BT_L2CAP_DISCONNECT,
|
||||
} __packed bt_l2cap_chan_state_t;
|
||||
|
||||
/** @brief Status of L2CAP channel. */
|
||||
typedef enum bt_l2cap_chan_status {
|
||||
/** Channel output status */
|
||||
BT_L2CAP_STATUS_OUT,
|
||||
|
||||
/* Total number of status - must be at the end of the enum */
|
||||
BT_L2CAP_NUM_STATUS,
|
||||
} __packed bt_l2cap_chan_status_t;
|
||||
|
||||
/** @brief L2CAP Channel structure. */
|
||||
struct bt_l2cap_chan {
|
||||
/** Channel connection reference */
|
||||
|
@ -78,6 +87,7 @@ struct bt_l2cap_chan {
|
|||
bt_l2cap_chan_destroy_t destroy;
|
||||
/* Response Timeout eXpired (RTX) timer */
|
||||
struct k_delayed_work rtx_work;
|
||||
ATOMIC_DEFINE(status, BT_L2CAP_NUM_STATUS);
|
||||
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
||||
bt_l2cap_chan_state_t state;
|
||||
/** Remote PSM to be connected */
|
||||
|
@ -220,6 +230,16 @@ struct bt_l2cap_chan_ops {
|
|||
* @param chan The channel which has sent data.
|
||||
*/
|
||||
void (*sent)(struct bt_l2cap_chan *chan);
|
||||
|
||||
/* Channel status callback
|
||||
*
|
||||
* If this callback is provided it will be called whenever the
|
||||
* channel status changes.
|
||||
*
|
||||
* @param chan The channel which status changed
|
||||
* @param status The channel status
|
||||
*/
|
||||
void (*status)(struct bt_l2cap_chan *chan, atomic_t *status);
|
||||
};
|
||||
|
||||
/** @def BT_L2CAP_CHAN_SEND_RESERVE
|
||||
|
|
|
@ -330,6 +330,13 @@ void bt_l2cap_connected(struct bt_conn *conn)
|
|||
if (chan->ops->connected) {
|
||||
chan->ops->connected(chan);
|
||||
}
|
||||
|
||||
/* Always set output status to fixed channels */
|
||||
atomic_set_bit(chan->status, BT_L2CAP_STATUS_OUT);
|
||||
|
||||
if (chan->ops->status) {
|
||||
chan->ops->status(chan, chan->status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -683,6 +690,11 @@ static void l2cap_chan_tx_give_credits(struct bt_l2cap_le_chan *chan,
|
|||
while (credits--) {
|
||||
k_sem_give(&chan->tx.credits);
|
||||
}
|
||||
|
||||
if (atomic_test_and_set_bit(chan->chan.status, BT_L2CAP_STATUS_OUT) &&
|
||||
chan->chan.ops->status) {
|
||||
chan->chan.ops->status(&chan->chan, chan->chan.status);
|
||||
}
|
||||
}
|
||||
|
||||
static void l2cap_chan_rx_give_credits(struct bt_l2cap_le_chan *chan,
|
||||
|
@ -1143,6 +1155,16 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, struct net_buf *buf,
|
|||
bt_l2cap_send(ch->chan.conn, ch->tx.cid, seg);
|
||||
}
|
||||
|
||||
/* Check if there is no credits left clear output status and notify its
|
||||
* change.
|
||||
*/
|
||||
if (!k_sem_count_get(&ch->tx.credits)) {
|
||||
atomic_clear_bit(ch->chan.status, BT_L2CAP_STATUS_OUT);
|
||||
if (ch->chan.ops->status) {
|
||||
ch->chan.ops->status(&ch->chan, ch->chan.status);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue