Skip to content

Commit 209f2f4

Browse files
mickeylh2zero
authored andcommitted
feat(L2CAP): add disconnect API and harden CoC send/error handling
- Add NimBLEL2CAPChannel::disconnect() and getConnHandle(). - Fix CoC TX mbuf ownership handling in writeFragment(): treat BLE_HS_ENOMEM / BLE_HS_EAGAIN as consumed buffer, only free local tx mbuf on BLE_HS_EBUSY.
1 parent bc2b46e commit 209f2f4

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

src/NimBLEL2CAPChannel.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,14 @@ int NimBLEL2CAPChannel::writeFragment(std::vector<uint8_t>::const_iterator begin
134134

135135
case BLE_HS_ENOMEM:
136136
case BLE_HS_EAGAIN:
137+
/* ble_l2cap_send already consumed and freed txd on these errors */
138+
NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d (consumed buffer). Retrying shortly...", res);
139+
ble_npl_time_delay(ble_npl_time_ms_to_ticks32(RetryTimeout));
140+
continue;
141+
137142
case BLE_HS_EBUSY:
138-
NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d. Retrying shortly...", res);
143+
/* Channel busy; txd not consumed */
144+
NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d (busy). Retrying shortly...", res);
139145
os_mbuf_free_chain(txd);
140146
ble_npl_time_delay(ble_npl_time_ms_to_ticks32(RetryTimeout));
141147
continue;
@@ -197,6 +203,28 @@ bool NimBLEL2CAPChannel::write(const std::vector<uint8_t>& bytes) {
197203
return true;
198204
}
199205

206+
bool NimBLEL2CAPChannel::disconnect() {
207+
if (!this->channel) {
208+
NIMBLE_LOGW(LOG_TAG, "L2CAP Channel not open");
209+
return false;
210+
}
211+
212+
int rc = ble_l2cap_disconnect(this->channel);
213+
if (rc != 0 && rc != BLE_HS_ENOTCONN && rc != BLE_HS_EALREADY) {
214+
NIMBLE_LOGE(LOG_TAG, "ble_l2cap_disconnect failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
215+
return false;
216+
}
217+
218+
return true;
219+
}
220+
221+
uint16_t NimBLEL2CAPChannel::getConnHandle() const {
222+
if (!this->channel) {
223+
return BLE_HS_CONN_HANDLE_NONE;
224+
}
225+
return ble_l2cap_get_conn_handle(this->channel);
226+
}
227+
200228
// private
201229
int NimBLEL2CAPChannel::handleConnectionEvent(struct ble_l2cap_event* event) {
202230
channel = event->connect.chan;

src/NimBLEL2CAPChannel.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ class NimBLEL2CAPChannel {
5656
/// NOTE: This function will block until the data has been sent or an error occurred.
5757
bool write(const std::vector<uint8_t>& bytes);
5858

59+
/// @brief Disconnect this L2CAP channel.
60+
/// @return true on success, false on failure.
61+
bool disconnect();
62+
63+
/// @brief Get the connection handle associated with this channel.
64+
/// @return Connection handle, or BLE_HS_CONN_HANDLE_NONE if not connected.
65+
uint16_t getConnHandle() const;
66+
5967
/// @return True, if the channel is connected. False, otherwise.
6068
bool isConnected() const { return !!channel; }
6169

0 commit comments

Comments
 (0)