diff --git a/src/NimBLEL2CAPChannel.cpp b/src/NimBLEL2CAPChannel.cpp index 4a155860..3a8030b3 100644 --- a/src/NimBLEL2CAPChannel.cpp +++ b/src/NimBLEL2CAPChannel.cpp @@ -134,8 +134,14 @@ int NimBLEL2CAPChannel::writeFragment(std::vector::const_iterator begin case BLE_HS_ENOMEM: case BLE_HS_EAGAIN: + /* ble_l2cap_send already consumed and freed txd on these errors */ + NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d (consumed buffer). Retrying shortly...", res); + ble_npl_time_delay(ble_npl_time_ms_to_ticks32(RetryTimeout)); + continue; + case BLE_HS_EBUSY: - NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d. Retrying shortly...", res); + /* Channel busy; txd not consumed */ + NIMBLE_LOGD(LOG_TAG, "ble_l2cap_send returned %d (busy). Retrying shortly...", res); os_mbuf_free_chain(txd); ble_npl_time_delay(ble_npl_time_ms_to_ticks32(RetryTimeout)); continue; @@ -197,6 +203,28 @@ bool NimBLEL2CAPChannel::write(const std::vector& bytes) { return true; } +bool NimBLEL2CAPChannel::disconnect() { + if (!this->channel) { + NIMBLE_LOGW(LOG_TAG, "L2CAP Channel not open"); + return false; + } + + int rc = ble_l2cap_disconnect(this->channel); + if (rc != 0 && rc != BLE_HS_ENOTCONN && rc != BLE_HS_EALREADY) { + NIMBLE_LOGE(LOG_TAG, "ble_l2cap_disconnect failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + return false; + } + + return true; +} + +uint16_t NimBLEL2CAPChannel::getConnHandle() const { + if (!this->channel) { + return BLE_HS_CONN_HANDLE_NONE; + } + return ble_l2cap_get_conn_handle(this->channel); +} + // private int NimBLEL2CAPChannel::handleConnectionEvent(struct ble_l2cap_event* event) { channel = event->connect.chan; diff --git a/src/NimBLEL2CAPChannel.h b/src/NimBLEL2CAPChannel.h index b7fafa4a..b0a8be3e 100644 --- a/src/NimBLEL2CAPChannel.h +++ b/src/NimBLEL2CAPChannel.h @@ -56,6 +56,14 @@ class NimBLEL2CAPChannel { /// NOTE: This function will block until the data has been sent or an error occurred. bool write(const std::vector& bytes); + /// @brief Disconnect this L2CAP channel. + /// @return true on success, false on failure. + bool disconnect(); + + /// @brief Get the connection handle associated with this channel. + /// @return Connection handle, or BLE_HS_CONN_HANDLE_NONE if not connected. + uint16_t getConnHandle() const; + /// @return True, if the channel is connected. False, otherwise. bool isConnected() const { return !!channel; }