mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-05 16:50:01 +00:00
nimble/l2cap: Add TX_UNSTALLED event to L2CAP CoC
With this patch if L2CAP CoC has been stalled due to lack of credits BLE_HS_ESTALLED code will be returned. When NimBLE gets back credits and finish sending SDU, BLE_L2CAP_EVENT_COC_TX_UNSTALLED will be sent to the application as the indication that L2CAP CoC is unstalled and ready for sending new data.
This commit is contained in:
@@ -94,6 +94,7 @@ extern "C" {
|
|||||||
#define BLE_HS_ESTORE_FAIL 28
|
#define BLE_HS_ESTORE_FAIL 28
|
||||||
#define BLE_HS_EPREEMPTED 29
|
#define BLE_HS_EPREEMPTED 29
|
||||||
#define BLE_HS_EDISABLED 30
|
#define BLE_HS_EDISABLED 30
|
||||||
|
#define BLE_HS_ESTALLED 31
|
||||||
|
|
||||||
/** Error base for ATT errors */
|
/** Error base for ATT errors */
|
||||||
#define BLE_HS_ERR_ATT_BASE 0x100
|
#define BLE_HS_ERR_ATT_BASE 0x100
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ struct ble_hs_conn;
|
|||||||
#define BLE_L2CAP_EVENT_COC_DISCONNECTED 1
|
#define BLE_L2CAP_EVENT_COC_DISCONNECTED 1
|
||||||
#define BLE_L2CAP_EVENT_COC_ACCEPT 2
|
#define BLE_L2CAP_EVENT_COC_ACCEPT 2
|
||||||
#define BLE_L2CAP_EVENT_COC_DATA_RECEIVED 3
|
#define BLE_L2CAP_EVENT_COC_DATA_RECEIVED 3
|
||||||
|
#define BLE_L2CAP_EVENT_COC_TX_UNSTALLED 4
|
||||||
|
|
||||||
typedef void ble_l2cap_sig_update_fn(uint16_t conn_handle, int status,
|
typedef void ble_l2cap_sig_update_fn(uint16_t conn_handle, int status,
|
||||||
void *arg);
|
void *arg);
|
||||||
@@ -173,6 +174,28 @@ struct ble_l2cap_event {
|
|||||||
/** The mbuf with received SDU. */
|
/** The mbuf with received SDU. */
|
||||||
struct os_mbuf *sdu_rx;
|
struct os_mbuf *sdu_rx;
|
||||||
} receive;
|
} receive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents tx_unstalled data. Valid for the following event
|
||||||
|
* types:
|
||||||
|
* o BLE_L2CAP_EVENT_COC_TX_UNSTALLED
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
/** Connection handle of the relevant connection */
|
||||||
|
uint16_t conn_handle;
|
||||||
|
|
||||||
|
/** The L2CAP channel of the relevant L2CAP connection. */
|
||||||
|
struct ble_l2cap_chan *chan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status of the send attempt which was stalled due to
|
||||||
|
* lack of credits; This can be non zero only if there
|
||||||
|
* is an issue with memory allocation for following SDU fragments.
|
||||||
|
* In such a case last SDU has been partially sent to peer device
|
||||||
|
* and it is up to application to decide how to handle it.
|
||||||
|
*/
|
||||||
|
int status;
|
||||||
|
} tx_unstalled;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -316,6 +316,23 @@ ble_l2cap_coc_cleanup_chan(struct ble_l2cap_chan *chan)
|
|||||||
os_mbuf_free_chain(chan->coc_tx.sdu);
|
os_mbuf_free_chain(chan->coc_tx.sdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ble_l2cap_event_coc_unstalled(struct ble_l2cap_chan *chan, int status)
|
||||||
|
{
|
||||||
|
struct ble_l2cap_event event = { };
|
||||||
|
|
||||||
|
if (!chan->cb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.type = BLE_L2CAP_EVENT_COC_TX_UNSTALLED;
|
||||||
|
event.tx_unstalled.conn_handle = chan->conn_handle;
|
||||||
|
event.tx_unstalled.chan = chan;
|
||||||
|
event.tx_unstalled.status = status;
|
||||||
|
|
||||||
|
chan->cb(&event, chan->cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||||
{
|
{
|
||||||
@@ -402,16 +419,30 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
|||||||
os_mbuf_free_chain(tx->sdu);
|
os_mbuf_free_chain(tx->sdu);
|
||||||
tx->sdu = 0;
|
tx->sdu = 0;
|
||||||
tx->data_offset = 0;
|
tx->data_offset = 0;
|
||||||
|
if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
|
||||||
|
ble_l2cap_event_coc_unstalled(chan, 0);
|
||||||
|
tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tx->sdu) {
|
||||||
|
/* Not complete SDU sent, wait for credits */
|
||||||
|
tx->flags |= BLE_L2CAP_COC_FLAG_STALLED;
|
||||||
|
return BLE_HS_ESTALLED;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
os_mbuf_free_chain(tx->sdu);
|
os_mbuf_free_chain(tx->sdu);
|
||||||
tx->sdu = NULL;
|
tx->sdu = NULL;
|
||||||
os_mbuf_free_chain(txom);
|
os_mbuf_free_chain(txom);
|
||||||
|
if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
|
||||||
|
ble_l2cap_event_coc_unstalled(chan, rc);
|
||||||
|
tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,11 +35,14 @@ extern "C" {
|
|||||||
|
|
||||||
struct ble_l2cap_chan;
|
struct ble_l2cap_chan;
|
||||||
|
|
||||||
|
#define BLE_L2CAP_COC_FLAG_STALLED 0x01
|
||||||
|
|
||||||
struct ble_l2cap_coc_endpoint {
|
struct ble_l2cap_coc_endpoint {
|
||||||
|
struct os_mbuf *sdu;
|
||||||
uint16_t mtu;
|
uint16_t mtu;
|
||||||
uint16_t credits;
|
uint16_t credits;
|
||||||
uint16_t data_offset;
|
uint16_t data_offset;
|
||||||
struct os_mbuf *sdu;
|
uint8_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ble_l2cap_coc_srv {
|
struct ble_l2cap_coc_srv {
|
||||||
|
|||||||
@@ -736,6 +736,9 @@ ble_l2cap_test_event(struct ble_l2cap_event *event, void *arg)
|
|||||||
OS_MBUF_PKTLEN(event->receive.sdu_rx));
|
OS_MBUF_PKTLEN(event->receive.sdu_rx));
|
||||||
TEST_ASSERT(memcmp(sdu_rx->om_data, ev->data, ev->data_len) == 0);
|
TEST_ASSERT(memcmp(sdu_rx->om_data, ev->data, ev->data_len) == 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
case BLE_L2CAP_EVENT_COC_TX_UNSTALLED:
|
||||||
|
/* TODO Add tests for this */
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user