Skip to content
Permalink
Browse files

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>
  • Loading branch information...
Vudentz authored and jhedberg committed May 22, 2019
1 parent 270e834 commit c904a45d8fa544536917c543264d88086cabbdb8
Showing with 42 additions and 0 deletions.
  1. +20 −0 include/bluetooth/l2cap.h
  2. +22 −0 subsys/bluetooth/host/l2cap.c
@@ -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;
}

0 comments on commit c904a45

Please sign in to comment.
You can’t perform that action at this time.