LCOV - code coverage report
Current view: top level - ble - BLEEndPoint.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 0 543 0.0 %
Date: 2024-02-15 08:20:41 Functions: 0 53 0.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4             :  *    Copyright (c) 2014-2017 Nest Labs, Inc.
       5             :  *
       6             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7             :  *    you may not use this file except in compliance with the License.
       8             :  *    You may obtain a copy of the License at
       9             :  *
      10             :  *        http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  *    Unless required by applicable law or agreed to in writing, software
      13             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  *    See the License for the specific language governing permissions and
      16             :  *    limitations under the License.
      17             :  */
      18             : 
      19             : /**
      20             :  *    @file
      21             :  *      This file implements a Bluetooth Low Energy (BLE) connection
      22             :  *      endpoint abstraction for the byte-streaming,
      23             :  *      connection-oriented CHIP over Bluetooth Low Energy (CHIPoBLE)
      24             :  *      Bluetooth Transport Protocol (BTP).
      25             :  *
      26             :  */
      27             : 
      28             : #ifndef __STDC_LIMIT_MACROS
      29             : #define __STDC_LIMIT_MACROS
      30             : #endif
      31             : #include <stdint.h>
      32             : #include <string.h>
      33             : 
      34             : #include <ble/BleConfig.h>
      35             : 
      36             : #if CONFIG_NETWORK_LAYER_BLE
      37             : #include <lib/core/CHIPConfig.h>
      38             : 
      39             : #include <lib/support/BitFlags.h>
      40             : #include <lib/support/CHIPFaultInjection.h>
      41             : #include <lib/support/CodeUtils.h>
      42             : #include <lib/support/logging/CHIPLogging.h>
      43             : 
      44             : #include <ble/BLEEndPoint.h>
      45             : #include <ble/BleLayer.h>
      46             : #include <ble/BtpEngine.h>
      47             : #if CHIP_ENABLE_CHIPOBLE_TEST
      48             : #include "BtpEngineTest.h"
      49             : #endif
      50             : 
      51             : // clang-format off
      52             : 
      53             : // Define below to enable extremely verbose, BLE end point-specific debug logging.
      54             : #undef CHIP_BLE_END_POINT_DEBUG_LOGGING_ENABLED
      55             : 
      56             : #ifdef CHIP_BLE_END_POINT_DEBUG_LOGGING_ENABLED
      57             : #define ChipLogDebugBleEndPoint(MOD, MSG, ...) ChipLogDetail(MOD, MSG, ## __VA_ARGS__)
      58             : #else
      59             : #define ChipLogDebugBleEndPoint(MOD, MSG, ...)
      60             : #endif
      61             : 
      62             : /**
      63             :  *  @def BLE_CONFIG_IMMEDIATE_ACK_WINDOW_THRESHOLD
      64             :  *
      65             :  *  @brief
      66             :  *    If an end point's receive window drops equal to or below this value, it will send an immediate acknowledgement
      67             :  *    packet to re-open its window instead of waiting for the send-ack timer to expire.
      68             :  *
      69             :  */
      70             : #define BLE_CONFIG_IMMEDIATE_ACK_WINDOW_THRESHOLD                   1
      71             : 
      72             : /**
      73             :  *  @def BLE_UNSUBSCRIBE_TIMEOUT_MS
      74             :  *
      75             :  *  @brief
      76             :  *    This is amount of time, in milliseconds, which a BLE end point will wait for an unsubscribe operation to complete
      77             :  *    before it automatically releases its BLE connection and frees itself. The default value of 5 seconds is arbitrary.
      78             :  *
      79             :  */
      80             : #define BLE_UNSUBSCRIBE_TIMEOUT_MS                            5000 // 5 seconds
      81             : 
      82             : #define BTP_ACK_SEND_TIMEOUT_MS                               2500 // 2.5 seconds
      83             : 
      84             : #define BTP_WINDOW_NO_ACK_SEND_THRESHOLD                         1 // Data fragments may only be sent without piggybacked
      85             :                                                                    // acks if receiver's window size is above this threshold.
      86             : 
      87             : // clang-format on
      88             : 
      89             : namespace chip {
      90             : namespace Ble {
      91             : 
      92           0 : CHIP_ERROR BLEEndPoint::StartConnect()
      93             : {
      94           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
      95             :     BleTransportCapabilitiesRequestMessage req;
      96           0 :     PacketBufferHandle buf;
      97           0 :     constexpr uint8_t numVersions =
      98             :         CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION - CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION + 1;
      99             :     static_assert(numVersions <= NUM_SUPPORTED_PROTOCOL_VERSIONS, "Incompatibly protocol versions");
     100             : 
     101             :     // Ensure we're in the correct state.
     102           0 :     VerifyOrExit(mState == kState_Ready, err = CHIP_ERROR_INCORRECT_STATE);
     103           0 :     mState = kState_Connecting;
     104             : 
     105             :     // Build BLE transport protocol capabilities request.
     106           0 :     buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);
     107           0 :     VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
     108             : 
     109             :     // Zero-initialize BLE transport capabilities request.
     110           0 :     memset(&req, 0, sizeof(req));
     111             : 
     112           0 :     req.mMtu = mBle->mPlatformDelegate->GetMTU(mConnObj);
     113             : 
     114           0 :     req.mWindowSize = BLE_MAX_RECEIVE_WINDOW_SIZE;
     115             : 
     116             :     // Populate request with highest supported protocol versions
     117           0 :     for (uint8_t i = 0; i < numVersions; i++)
     118             :     {
     119           0 :         req.SetSupportedProtocolVersion(i, static_cast<uint8_t>(CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION - i));
     120             :     }
     121             : 
     122           0 :     err = req.Encode(buf);
     123           0 :     SuccessOrExit(err);
     124             : 
     125             :     // Start connect timer. Canceled when end point freed or connection established.
     126           0 :     err = StartConnectTimer();
     127           0 :     SuccessOrExit(err);
     128             : 
     129             :     // Send BLE transport capabilities request to peripheral via GATT write.
     130             :     // Add reference to message fragment for duration of platform's GATT write attempt. CHIP retains partial
     131             :     // ownership of message fragment's packet buffer, since this is the same buffer as that of the whole message, just
     132             :     // with a fragmenter-modified payload offset and data length, by a Retain() on the handle when calling this function.
     133           0 :     if (!SendWrite(buf.Retain()))
     134             :     {
     135           0 :         err = BLE_ERROR_GATT_WRITE_FAILED;
     136           0 :         ExitNow();
     137             :     }
     138             : 
     139             :     // Free request buffer on write confirmation. Stash a reference to it in mSendQueue, which we don't use anyway
     140             :     // until the connection has been set up.
     141           0 :     QueueTx(std::move(buf), kType_Data);
     142             : 
     143           0 : exit:
     144             :     // If we failed to initiate the connection, close the end point.
     145           0 :     if (err != CHIP_NO_ERROR)
     146             :     {
     147           0 :         StopConnectTimer();
     148           0 :         DoClose(kBleCloseFlag_AbortTransmission, err);
     149             :     }
     150             : 
     151           0 :     return err;
     152           0 : }
     153             : 
     154           0 : CHIP_ERROR BLEEndPoint::HandleConnectComplete()
     155             : {
     156           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     157             : 
     158           0 :     mState = kState_Connected;
     159             : 
     160             :     // Cancel the connect timer.
     161           0 :     StopConnectTimer();
     162             : 
     163             :     // We've successfully completed the BLE transport protocol handshake, so let the application know we're open for business.
     164           0 :     if (mBleTransport != nullptr)
     165             :     {
     166             :         // Indicate connect complete to next-higher layer.
     167           0 :         mBleTransport->OnEndPointConnectComplete(this, CHIP_NO_ERROR);
     168             :     }
     169             :     else
     170             :     {
     171             :         // If no connect complete callback has been set up, close the end point.
     172           0 :         err = BLE_ERROR_NO_CONNECT_COMPLETE_CALLBACK;
     173             :     }
     174             : 
     175           0 :     return err;
     176             : }
     177             : 
     178           0 : CHIP_ERROR BLEEndPoint::HandleReceiveConnectionComplete()
     179             : {
     180           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     181             : 
     182             :     ChipLogDebugBleEndPoint(Ble, "entered HandleReceiveConnectionComplete");
     183           0 :     mState = kState_Connected;
     184             : 
     185             :     // Cancel receive connection timer.
     186           0 :     StopReceiveConnectionTimer();
     187             : 
     188             :     // We've successfully completed the BLE transport protocol handshake, so let the transport know we're open for business.
     189           0 :     if (mBleTransport != nullptr)
     190             :     {
     191             :         // Indicate BLE transport protocol connection received to next-higher layer.
     192           0 :         err = mBleTransport->SetEndPoint(this);
     193             :     }
     194             :     else
     195             :     {
     196           0 :         err = BLE_ERROR_NO_CONNECTION_RECEIVED_CALLBACK;
     197             :     }
     198             : 
     199           0 :     return err;
     200             : }
     201             : 
     202           0 : void BLEEndPoint::HandleSubscribeReceived()
     203             : {
     204           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     205             : 
     206           0 :     VerifyOrExit(mState == kState_Connecting || mState == kState_Aborting, err = CHIP_ERROR_INCORRECT_STATE);
     207           0 :     VerifyOrExit(!mSendQueue.IsNull(), err = CHIP_ERROR_INCORRECT_STATE);
     208             : 
     209             :     // Send BTP capabilities response to peripheral via GATT indication.
     210             : #if CHIP_ENABLE_CHIPOBLE_TEST
     211             :     VerifyOrExit(mBtpEngine.PopPacketTag(mSendQueue) == kType_Data, err = BLE_ERROR_INVALID_BTP_HEADER_FLAGS);
     212             : #endif
     213             :     // Add reference to message fragment for duration of platform's GATT indication attempt. CHIP retains partial
     214             :     // ownership of message fragment's packet buffer, since this is the same buffer as that of the whole message, just
     215             :     // with a fragmenter-modified payload offset and data length.
     216           0 :     if (!SendIndication(mSendQueue.Retain()))
     217             :     {
     218             :         // Ensure transmit queue is empty and set to NULL.
     219           0 :         QueueTxLock();
     220           0 :         mSendQueue = nullptr;
     221           0 :         QueueTxUnlock();
     222             : 
     223           0 :         ChipLogError(Ble, "cap resp ind failed");
     224           0 :         err = BLE_ERROR_GATT_INDICATE_FAILED;
     225           0 :         ExitNow();
     226             :     }
     227             : 
     228             :     // Shrink remote receive window counter by 1, since we've sent an indication which requires acknowledgement.
     229           0 :     mRemoteReceiveWindowSize = static_cast<SequenceNumber_t>(mRemoteReceiveWindowSize - 1);
     230             :     ChipLogDebugBleEndPoint(Ble, "decremented remote rx window, new size = %u", mRemoteReceiveWindowSize);
     231             : 
     232             :     // Start ack recvd timer for handshake indication.
     233           0 :     err = StartAckReceivedTimer();
     234           0 :     SuccessOrExit(err);
     235             : 
     236             :     ChipLogDebugBleEndPoint(Ble, "got subscribe, sent indication w/ capabilities response");
     237             : 
     238             :     // If SendIndication returns true, mSendQueue is freed on indication confirmation, or on close in case of
     239             :     // connection error.
     240             : 
     241           0 :     if (mState != kState_Aborting)
     242             :     {
     243             :         // If peripheral accepted the BTP connection, its end point must enter the connected state here, i.e. before it
     244             :         // receives a GATT confirmation for the capabilities response indication. This behavior is required to handle the
     245             :         // case where a peripheral's BLE controller passes up the central's first message fragment write before the
     246             :         // capabilities response indication confirmation. If the end point waited for this indication confirmation before
     247             :         // it entered the connected state, it'd be in the wrong state to receive the central's first data write, and drop
     248             :         // the corresponding message fragment.
     249           0 :         err = HandleReceiveConnectionComplete();
     250           0 :         SuccessOrExit(err);
     251             :     } // Else State == kState_Aborting, so we'll close end point when indication confirmation received.
     252             : 
     253           0 : exit:
     254           0 :     if (err != CHIP_NO_ERROR)
     255             :     {
     256           0 :         DoClose(kBleCloseFlag_SuppressCallback | kBleCloseFlag_AbortTransmission, err);
     257             :     }
     258           0 : }
     259             : 
     260           0 : void BLEEndPoint::HandleSubscribeComplete()
     261             : {
     262           0 :     ChipLogProgress(Ble, "subscribe complete, ep = %p", this);
     263           0 :     mConnStateFlags.Clear(ConnectionStateFlag::kGattOperationInFlight);
     264             : 
     265           0 :     CHIP_ERROR err = DriveSending();
     266             : 
     267           0 :     if (err != CHIP_NO_ERROR)
     268             :     {
     269           0 :         DoClose(kBleCloseFlag_AbortTransmission, CHIP_NO_ERROR);
     270             :     }
     271           0 : }
     272             : 
     273           0 : void BLEEndPoint::HandleUnsubscribeComplete()
     274             : {
     275             :     // Don't bother to clear GattOperationInFlight, we're about to free the end point anyway.
     276           0 :     Free();
     277           0 : }
     278             : 
     279           0 : bool BLEEndPoint::IsConnected(uint8_t state) const
     280             : {
     281           0 :     return (state == kState_Connected || state == kState_Closing);
     282             : }
     283             : 
     284           0 : bool BLEEndPoint::IsUnsubscribePending() const
     285             : {
     286           0 :     return mTimerStateFlags.Has(TimerStateFlag::kUnsubscribeTimerRunning);
     287             : }
     288             : 
     289           0 : void BLEEndPoint::Abort()
     290             : {
     291             :     // No more callbacks after this point, since application explicitly called Abort().
     292           0 :     OnConnectComplete  = nullptr;
     293           0 :     OnConnectionClosed = nullptr;
     294           0 :     OnMessageReceived  = nullptr;
     295             : #if CHIP_ENABLE_CHIPOBLE_TEST
     296             :     OnCommandReceived = NULL;
     297             : #endif
     298             : 
     299           0 :     DoClose(kBleCloseFlag_SuppressCallback | kBleCloseFlag_AbortTransmission, CHIP_NO_ERROR);
     300           0 : }
     301             : 
     302           0 : void BLEEndPoint::Close()
     303             : {
     304             :     // No more callbacks after this point, since application explicitly called Close().
     305           0 :     OnConnectComplete  = nullptr;
     306           0 :     OnConnectionClosed = nullptr;
     307           0 :     OnMessageReceived  = nullptr;
     308             : #if CHIP_ENABLE_CHIPOBLE_TEST
     309             :     OnCommandReceived = NULL;
     310             : #endif
     311             : 
     312           0 :     DoClose(kBleCloseFlag_SuppressCallback, CHIP_NO_ERROR);
     313           0 : }
     314             : 
     315           0 : void BLEEndPoint::DoClose(uint8_t flags, CHIP_ERROR err)
     316             : {
     317           0 :     uint8_t oldState = mState;
     318             : 
     319             :     // If end point is not closed or closing, OR end point was closing gracefully, but tx abort has been specified...
     320           0 :     if ((mState != kState_Closed && mState != kState_Closing) ||
     321           0 :         (mState == kState_Closing && (flags & kBleCloseFlag_AbortTransmission)))
     322             :     {
     323             :         // Cancel Connect and ReceiveConnect timers if they are running.
     324             :         // Check role first to avoid needless iteration over timer pool.
     325           0 :         if (mRole == kBleRole_Central)
     326             :         {
     327           0 :             StopConnectTimer();
     328             :         }
     329             :         else // (mRole == kBleRole_Peripheral), verified on Init
     330             :         {
     331           0 :             StopReceiveConnectionTimer();
     332             :         }
     333             : 
     334             :         // If transmit buffer is empty or a transmission abort was specified...
     335           0 :         if (mBtpEngine.TxState() == BtpEngine::kState_Idle || (flags & kBleCloseFlag_AbortTransmission))
     336             :         {
     337           0 :             FinalizeClose(oldState, flags, err);
     338             :         }
     339             :         else
     340             :         {
     341             :             // Wait for send queue and fragmenter's tx buffer to become empty, to ensure all pending messages have been
     342             :             // sent. Only free end point and tell platform it can throw away the underlying BLE connection once all
     343             :             // pending messages have been sent and acknowledged by the remote CHIPoBLE stack, or once the remote stack
     344             :             // closes the CHIPoBLE connection.
     345             :             //
     346             :             // In so doing, BLEEndPoint attempts to emulate the level of reliability afforded by TCPEndPoint and TCP
     347             :             // sockets in general with a typical default SO_LINGER option. That said, there is no hard guarantee that
     348             :             // pending messages will be sent once (Do)Close() is called, so developers should use application-level
     349             :             // messages to confirm the receipt of all data sent prior to a Close() call.
     350           0 :             mState = kState_Closing;
     351             : 
     352           0 :             if ((flags & kBleCloseFlag_SuppressCallback) == 0)
     353             :             {
     354           0 :                 DoCloseCallback(oldState, flags, err);
     355             :             }
     356             : 
     357           0 :             if ((flags & kBleCloseFlag_SuppressCallback) != 0)
     358             :             {
     359           0 :                 mBleTransport->OnEndPointConnectionClosed(this, err);
     360             :             }
     361             :         }
     362             :     }
     363           0 : }
     364             : 
     365           0 : void BLEEndPoint::FinalizeClose(uint8_t oldState, uint8_t flags, CHIP_ERROR err)
     366             : {
     367           0 :     mState = kState_Closed;
     368             : 
     369             :     // Ensure transmit queue is empty and set to NULL.
     370           0 :     QueueTxLock();
     371           0 :     mSendQueue = nullptr;
     372           0 :     QueueTxUnlock();
     373             : 
     374             :     // Fire application's close callback if we haven't already, and it's not suppressed.
     375           0 :     if (oldState != kState_Closing && (flags & kBleCloseFlag_SuppressCallback) == 0)
     376             :     {
     377           0 :         DoCloseCallback(oldState, flags, err);
     378             :     }
     379             : 
     380           0 :     if ((flags & kBleCloseFlag_SuppressCallback) != 0)
     381             :     {
     382           0 :         mBleTransport->OnEndPointConnectionClosed(this, err);
     383             :     }
     384             : 
     385             :     // If underlying BLE connection has closed, connection object is invalid, so just free the end point and return.
     386           0 :     if (err == BLE_ERROR_REMOTE_DEVICE_DISCONNECTED || err == BLE_ERROR_APP_CLOSED_CONNECTION)
     387             :     {
     388           0 :         mConnObj = BLE_CONNECTION_UNINITIALIZED; // Clear handle to BLE connection, so we don't double-close it.
     389           0 :         Free();
     390             :     }
     391             :     else // Otherwise, try to signal close to remote device before end point releases BLE connection and frees itself.
     392             :     {
     393           0 :         if (mRole == kBleRole_Central && mConnStateFlags.Has(ConnectionStateFlag::kDidBeginSubscribe))
     394             :         {
     395             :             // Cancel send and receive-ack timers, if running.
     396           0 :             StopAckReceivedTimer();
     397           0 :             StopSendAckTimer();
     398             : 
     399             :             // Indicate close of chipConnection to peripheral via GATT unsubscribe. Keep end point allocated until
     400             :             // unsubscribe completes or times out, so platform doesn't close underlying BLE connection before
     401             :             // we're really sure the unsubscribe request has been sent.
     402           0 :             if (!mBle->mPlatformDelegate->UnsubscribeCharacteristic(mConnObj, &CHIP_BLE_SVC_ID, &mBle->CHIP_BLE_CHAR_2_ID))
     403             :             {
     404           0 :                 ChipLogError(Ble, "BtpEngine unsub failed");
     405             : 
     406             :                 // If unsubscribe fails, release BLE connection and free end point immediately.
     407           0 :                 Free();
     408             :             }
     409           0 :             else if (mConnObj != BLE_CONNECTION_UNINITIALIZED)
     410             :             {
     411             :                 // Unsubscribe request was sent successfully, and a confirmation wasn't spontaneously generated or
     412             :                 // received in the downcall to UnsubscribeCharacteristic, so set timer for the unsubscribe to complete.
     413           0 :                 err = StartUnsubscribeTimer();
     414             : 
     415           0 :                 if (err != CHIP_NO_ERROR)
     416             :                 {
     417           0 :                     Free();
     418             :                 }
     419             : 
     420             :                 // Mark unsubscribe GATT operation in progress.
     421           0 :                 mConnStateFlags.Set(ConnectionStateFlag::kGattOperationInFlight);
     422             :             }
     423             :         }
     424             :         else // mRole == kBleRole_Peripheral, OR mTimerStateFlags.Has(ConnectionStateFlag::kDidBeginSubscribe) == false...
     425             :         {
     426           0 :             Free();
     427             :         }
     428             :     }
     429           0 : }
     430             : 
     431           0 : void BLEEndPoint::DoCloseCallback(uint8_t state, uint8_t flags, CHIP_ERROR err)
     432             : {
     433           0 :     if (state == kState_Connecting)
     434             :     {
     435           0 :         if (mBleTransport != nullptr)
     436             :         {
     437           0 :             mBleTransport->OnEndPointConnectComplete(this, err);
     438             :         }
     439             :     }
     440             :     else
     441             :     {
     442           0 :         if (mBleTransport != nullptr)
     443             :         {
     444           0 :             mBleTransport->OnEndPointConnectionClosed(this, err);
     445             :         }
     446             :     }
     447             : 
     448             :     // Callback fires once per end point lifetime.
     449           0 :     OnConnectComplete  = nullptr;
     450           0 :     OnConnectionClosed = nullptr;
     451           0 : }
     452             : 
     453           0 : void BLEEndPoint::ReleaseBleConnection()
     454             : {
     455           0 :     if (mConnObj != BLE_CONNECTION_UNINITIALIZED)
     456             :     {
     457           0 :         if (mConnStateFlags.Has(ConnectionStateFlag::kAutoClose))
     458             :         {
     459           0 :             ChipLogProgress(Ble, "Auto-closing end point's BLE connection.");
     460           0 :             mBle->mPlatformDelegate->CloseConnection(mConnObj);
     461             :         }
     462             :         else
     463             :         {
     464           0 :             ChipLogProgress(Ble, "Releasing end point's BLE connection back to application.");
     465           0 :             mBle->mApplicationDelegate->NotifyChipConnectionClosed(mConnObj);
     466             :         }
     467             : 
     468             :         // Never release the same BLE connection twice.
     469           0 :         mConnObj = BLE_CONNECTION_UNINITIALIZED;
     470             :     }
     471           0 : }
     472             : 
     473           0 : void BLEEndPoint::Free()
     474             : {
     475             :     // Release BLE connection. Will close connection if AutoClose enabled for this end point. Otherwise, informs
     476             :     // application that CHIP is done with this BLE connection, and application makes decision about whether to close
     477             :     // and clean up or retain connection.
     478           0 :     ReleaseBleConnection();
     479             : 
     480             :     // Clear fragmentation and reassembly engine's Tx and Rx buffers. Counters will be reset by next engine init.
     481           0 :     FreeBtpEngine();
     482             : 
     483             :     // Clear pending ack buffer, if any.
     484           0 :     mAckToSend = nullptr;
     485             : 
     486             :     // Cancel all timers.
     487           0 :     StopConnectTimer();
     488           0 :     StopReceiveConnectionTimer();
     489           0 :     StopAckReceivedTimer();
     490           0 :     StopSendAckTimer();
     491           0 :     StopUnsubscribeTimer();
     492             : #if CHIP_ENABLE_CHIPOBLE_TEST
     493             :     mBtpEngineTest.StopTestTimer();
     494             :     // Clear callback
     495             :     OnCommandReceived = NULL;
     496             : #endif
     497             : 
     498             :     // Clear callbacks.
     499           0 :     OnConnectComplete  = nullptr;
     500           0 :     OnMessageReceived  = nullptr;
     501           0 :     OnConnectionClosed = nullptr;
     502             : 
     503             :     // Clear handle to underlying BLE connection.
     504           0 :     mConnObj = BLE_CONNECTION_UNINITIALIZED;
     505             : 
     506             :     // Release the AddRef() that happened when the end point was allocated.
     507           0 :     Release();
     508           0 : }
     509             : 
     510           0 : void BLEEndPoint::FreeBtpEngine()
     511             : {
     512             :     // Free transmit disassembly buffer
     513           0 :     mBtpEngine.ClearTxPacket();
     514             : 
     515             :     // Free receive reassembly buffer
     516           0 :     mBtpEngine.ClearRxPacket();
     517           0 : }
     518             : 
     519           0 : CHIP_ERROR BLEEndPoint::Init(BleLayer * bleLayer, BLE_CONNECTION_OBJECT connObj, BleRole role, bool autoClose)
     520             : {
     521             :     // Fail if already initialized.
     522           0 :     VerifyOrReturnError(mBle == nullptr, CHIP_ERROR_INCORRECT_STATE);
     523             : 
     524             :     // Validate args.
     525           0 :     VerifyOrReturnError(bleLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     526           0 :     VerifyOrReturnError(connObj != BLE_CONNECTION_UNINITIALIZED, CHIP_ERROR_INVALID_ARGUMENT);
     527           0 :     VerifyOrReturnError((role == kBleRole_Central || role == kBleRole_Peripheral), CHIP_ERROR_INVALID_ARGUMENT);
     528             : 
     529             :     // If end point plays peripheral role, expect ack for indication sent as last step of BTP handshake.
     530             :     // If central, periperal's handshake indication 'ack's write sent by central to kick off the BTP handshake.
     531           0 :     bool expectInitialAck = (role == kBleRole_Peripheral);
     532             : 
     533           0 :     CHIP_ERROR err = mBtpEngine.Init(this, expectInitialAck);
     534           0 :     if (err != CHIP_NO_ERROR)
     535             :     {
     536           0 :         ChipLogError(Ble, "BtpEngine init failed");
     537           0 :         return err;
     538             :     }
     539             : 
     540             : #if CHIP_ENABLE_CHIPOBLE_TEST
     541             :     err = static_cast<CHIP_ERROR>(mTxQueueMutex.Init(mTxQueueMutex));
     542             :     if (err != CHIP_NO_ERROR)
     543             :     {
     544             :         ChipLogError(Ble, "%s: Mutex init failed", __FUNCTION__);
     545             :         return err;
     546             :     }
     547             :     err = mBtpEngineTest.Init(this);
     548             :     if (err != CHIP_NO_ERROR)
     549             :     {
     550             :         ChipLogError(Ble, "BTP test init failed");
     551             :         return err;
     552             :     }
     553             : #endif
     554             : 
     555           0 :     mBle      = bleLayer;
     556           0 :     mRefCount = 1;
     557             : 
     558             :     // BLEEndPoint data members:
     559           0 :     mConnObj = connObj;
     560           0 :     mRole    = role;
     561           0 :     mTimerStateFlags.ClearAll();
     562           0 :     mConnStateFlags.ClearAll().Set(ConnectionStateFlag::kAutoClose, autoClose);
     563           0 :     mLocalReceiveWindowSize  = 0;
     564           0 :     mRemoteReceiveWindowSize = 0;
     565           0 :     mReceiveWindowMaxSize    = 0;
     566           0 :     mSendQueue               = nullptr;
     567           0 :     mAckToSend               = nullptr;
     568             : 
     569             :     ChipLogDebugBleEndPoint(Ble, "initialized local rx window, size = %u", mLocalReceiveWindowSize);
     570             : 
     571             :     // End point is ready to connect or receive a connection.
     572           0 :     mState = kState_Ready;
     573             : 
     574           0 :     return CHIP_NO_ERROR;
     575             : }
     576             : 
     577           0 : void BLEEndPoint::AddRef()
     578             : {
     579           0 :     VerifyOrDie(mRefCount < UINT32_MAX);
     580           0 :     mRefCount++;
     581           0 : }
     582             : 
     583           0 : void BLEEndPoint::Release()
     584             : {
     585           0 :     VerifyOrDie(mRefCount > 0u);
     586             :     // Decrement the ref count.  When it reaches zero, NULL out the pointer to the chip::System::Layer
     587             :     // object. This effectively declared the object free and ready for re-allocation.
     588           0 :     mRefCount--;
     589           0 :     if (mRefCount == 0)
     590             :     {
     591           0 :         mBle = nullptr;
     592             :     }
     593           0 : }
     594             : 
     595           0 : CHIP_ERROR BLEEndPoint::SendCharacteristic(PacketBufferHandle && buf)
     596             : {
     597           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     598             : 
     599           0 :     if (mRole == kBleRole_Central)
     600             :     {
     601           0 :         if (!SendWrite(std::move(buf)))
     602             :         {
     603           0 :             err = BLE_ERROR_GATT_WRITE_FAILED;
     604             :         }
     605             :         else
     606             :         {
     607             :             // Write succeeded, so shrink remote receive window counter by 1.
     608           0 :             mRemoteReceiveWindowSize = static_cast<SequenceNumber_t>(mRemoteReceiveWindowSize - 1);
     609             :             ChipLogDebugBleEndPoint(Ble, "decremented remote rx window, new size = %u", mRemoteReceiveWindowSize);
     610             :         }
     611             :     }
     612             :     else // (mRole == kBleRole_Peripheral), verified on Init
     613             :     {
     614           0 :         if (!SendIndication(std::move(buf)))
     615             :         {
     616           0 :             err = BLE_ERROR_GATT_INDICATE_FAILED;
     617             :         }
     618             :         else
     619             :         {
     620             :             // Indication succeeded, so shrink remote receive window counter by 1.
     621           0 :             mRemoteReceiveWindowSize = static_cast<SequenceNumber_t>(mRemoteReceiveWindowSize - 1);
     622             :             ChipLogDebugBleEndPoint(Ble, "decremented remote rx window, new size = %u", mRemoteReceiveWindowSize);
     623             :         }
     624             :     }
     625             : 
     626           0 :     return err;
     627             : }
     628             : 
     629             : /*
     630             :  *  Routine to queue the Tx packet with a packet type
     631             :  *  kType_Data(0)       - data packet
     632             :  *  kType_Control(1)    - control packet
     633             :  */
     634           0 : void BLEEndPoint::QueueTx(PacketBufferHandle && data, PacketType_t type)
     635             : {
     636             : #if CHIP_ENABLE_CHIPOBLE_TEST
     637             :     ChipLogDebugBleEndPoint(Ble, "%s: data->%p, type %d, len %d", __FUNCTION__, data, type, data->DataLength());
     638             :     mBtpEngine.PushPacketTag(data, type);
     639             : #endif
     640             : 
     641           0 :     QueueTxLock();
     642             : 
     643           0 :     if (mSendQueue.IsNull())
     644             :     {
     645           0 :         mSendQueue = std::move(data);
     646             :         ChipLogDebugBleEndPoint(Ble, "%s: Set data as new mSendQueue %p, type %d", __FUNCTION__, mSendQueue->Start(), type);
     647             :     }
     648             :     else
     649             :     {
     650           0 :         mSendQueue->AddToEnd(std::move(data));
     651             :         ChipLogDebugBleEndPoint(Ble, "%s: Append data to mSendQueue %p, type %d", __FUNCTION__, mSendQueue->Start(), type);
     652             :     }
     653             : 
     654           0 :     QueueTxUnlock();
     655           0 : }
     656             : 
     657           0 : CHIP_ERROR BLEEndPoint::Send(PacketBufferHandle && data)
     658             : {
     659             :     ChipLogDebugBleEndPoint(Ble, "entered Send");
     660             : 
     661           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     662             : 
     663           0 :     VerifyOrExit(!data.IsNull(), err = CHIP_ERROR_INVALID_ARGUMENT);
     664           0 :     VerifyOrExit(IsConnected(mState), err = CHIP_ERROR_INCORRECT_STATE);
     665             : 
     666             :     // Ensure outgoing message fits in a single contiguous packet buffer, as currently required by the
     667             :     // message fragmentation and reassembly engine.
     668           0 :     if (data->HasChainedBuffer())
     669             :     {
     670           0 :         data->CompactHead();
     671             : 
     672           0 :         if (data->HasChainedBuffer())
     673             :         {
     674           0 :             err = CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG;
     675           0 :             ExitNow();
     676             :         }
     677             :     }
     678             : 
     679             :     // Add new message to send queue.
     680           0 :     QueueTx(std::move(data), kType_Data);
     681             : 
     682             :     // Send first fragment of new message, if we can.
     683           0 :     err = DriveSending();
     684           0 :     SuccessOrExit(err);
     685             : 
     686           0 : exit:
     687             :     ChipLogDebugBleEndPoint(Ble, "exiting Send");
     688           0 :     if (err != CHIP_NO_ERROR)
     689             :     {
     690           0 :         DoClose(kBleCloseFlag_AbortTransmission, err);
     691             :     }
     692             : 
     693           0 :     return err;
     694             : }
     695             : 
     696           0 : bool BLEEndPoint::PrepareNextFragment(PacketBufferHandle && data, bool & sentAck)
     697             : {
     698             :     // If we have a pending fragment acknowledgement to send, piggyback it on the fragment we're about to transmit.
     699           0 :     if (mTimerStateFlags.Has(TimerStateFlag::kSendAckTimerRunning))
     700             :     {
     701             :         // Reset local receive window counter.
     702           0 :         mLocalReceiveWindowSize = mReceiveWindowMaxSize;
     703             :         ChipLogDebugBleEndPoint(Ble, "reset local rx window on piggyback ack tx, size = %u", mLocalReceiveWindowSize);
     704             : 
     705             :         // Tell caller AND fragmenter we have an ack to piggyback.
     706           0 :         sentAck = true;
     707             :     }
     708             :     else
     709             :     {
     710             :         // No ack to piggyback.
     711           0 :         sentAck = false;
     712             :     }
     713             : 
     714           0 :     return mBtpEngine.HandleCharacteristicSend(std::move(data), sentAck);
     715             : }
     716             : 
     717           0 : CHIP_ERROR BLEEndPoint::SendNextMessage()
     718             : {
     719             :     // Get the first queued packet to send
     720           0 :     QueueTxLock();
     721             : #if CHIP_ENABLE_CHIPOBLE_TEST
     722             :     // Return if tx queue is empty
     723             :     // Note: PopHead() does not check an empty queue
     724             :     if (mSendQueue.IsNull())
     725             :     {
     726             :         QueueTxUnlock();
     727             :         return CHIP_NO_ERROR;
     728             :     }
     729             : #endif
     730             : 
     731           0 :     PacketBufferHandle data = mSendQueue.PopHead();
     732           0 :     QueueTxUnlock();
     733             : 
     734             : #if CHIP_ENABLE_CHIPOBLE_TEST
     735             :     // Get and consume the packet tag in message buffer
     736             :     PacketType_t type = mBtpEngine.PopPacketTag(data);
     737             :     mBtpEngine.SetTxPacketType(type);
     738             :     mBtpEngineTest.DoTxTiming(data, BTP_TX_START);
     739             : #endif
     740             : 
     741             :     // Hand whole message payload to the fragmenter.
     742             :     bool sentAck;
     743           0 :     VerifyOrReturnError(PrepareNextFragment(std::move(data), sentAck), BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT);
     744             : 
     745             :     /*
     746             :      // Todo: reenabled it after integrating fault injection
     747             :     // Send first message fragment over the air.
     748             :     CHIP_FAULT_INJECT(chip::FaultInjection::kFault_CHIPOBLESend, {
     749             :         if (mRole == kBleRole_Central)
     750             :         {
     751             :             err = BLE_ERROR_GATT_WRITE_FAILED;
     752             :         }
     753             :         else
     754             :         {
     755             :             err = BLE_ERROR_GATT_INDICATE_FAILED;
     756             :         }
     757             :         ExitNow();
     758             :     });
     759             :      */
     760           0 :     ReturnErrorOnFailure(SendCharacteristic(mBtpEngine.BorrowTxPacket()));
     761             : 
     762           0 :     if (sentAck)
     763             :     {
     764             :         // If sent piggybacked ack, stop send-ack timer.
     765           0 :         StopSendAckTimer();
     766             :     }
     767             : 
     768             :     // Start ack received timer, if it's not already running.
     769           0 :     return StartAckReceivedTimer();
     770           0 : }
     771             : 
     772           0 : CHIP_ERROR BLEEndPoint::ContinueMessageSend()
     773             : {
     774             :     bool sentAck;
     775             : 
     776           0 :     if (!PrepareNextFragment(nullptr, sentAck))
     777             :     {
     778             :         // Log BTP error
     779           0 :         ChipLogError(Ble, "btp fragmenter error on send!");
     780           0 :         mBtpEngine.LogState();
     781             : 
     782           0 :         return BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
     783             :     }
     784             : 
     785           0 :     ReturnErrorOnFailure(SendCharacteristic(mBtpEngine.BorrowTxPacket()));
     786             : 
     787           0 :     if (sentAck)
     788             :     {
     789             :         // If sent piggybacked ack, stop send-ack timer.
     790           0 :         StopSendAckTimer();
     791             :     }
     792             : 
     793             :     // Start ack received timer, if it's not already running.
     794           0 :     return StartAckReceivedTimer();
     795             : }
     796             : 
     797           0 : CHIP_ERROR BLEEndPoint::HandleHandshakeConfirmationReceived()
     798             : {
     799             :     ChipLogDebugBleEndPoint(Ble, "entered HandleHandshakeConfirmationReceived");
     800             : 
     801           0 :     CHIP_ERROR err     = CHIP_NO_ERROR;
     802           0 :     uint8_t closeFlags = kBleCloseFlag_AbortTransmission;
     803             : 
     804             :     // Free capabilities request/response payload.
     805           0 :     QueueTxLock();
     806           0 :     mSendQueue.FreeHead();
     807           0 :     QueueTxUnlock();
     808             : 
     809           0 :     if (mRole == kBleRole_Central)
     810             :     {
     811             :         // Subscribe to characteristic which peripheral will use to send indications. Prompts peripheral to send
     812             :         // BLE transport capabilities indication.
     813           0 :         VerifyOrExit(mBle->mPlatformDelegate->SubscribeCharacteristic(mConnObj, &CHIP_BLE_SVC_ID, &mBle->CHIP_BLE_CHAR_2_ID),
     814             :                      err = BLE_ERROR_GATT_SUBSCRIBE_FAILED);
     815             : 
     816             :         // We just sent a GATT subscribe request, so make sure to attempt unsubscribe on close.
     817           0 :         mConnStateFlags.Set(ConnectionStateFlag::kDidBeginSubscribe);
     818             : 
     819             :         // Mark GATT operation in progress for subscribe request.
     820           0 :         mConnStateFlags.Set(ConnectionStateFlag::kGattOperationInFlight);
     821             :     }
     822             :     else // (mRole == kBleRole_Peripheral), verified on Init
     823             :     {
     824             :         ChipLogDebugBleEndPoint(Ble, "got peripheral handshake indication confirmation");
     825             : 
     826           0 :         if (mState == kState_Connected) // If we accepted BTP connection...
     827             :         {
     828             :             // If local receive window size has shrunk to or below immediate ack threshold, AND a message fragment is not
     829             :             // pending on which to piggyback an ack, send immediate stand-alone ack.
     830           0 :             if (mLocalReceiveWindowSize <= BLE_CONFIG_IMMEDIATE_ACK_WINDOW_THRESHOLD && mSendQueue.IsNull())
     831             :             {
     832           0 :                 err = DriveStandAloneAck(); // Encode stand-alone ack and drive sending.
     833           0 :                 SuccessOrExit(err);
     834             :             }
     835             :             else
     836             :             {
     837             :                 // Drive sending in case application callend Send() after we sent the handshake indication, but
     838             :                 // before the GATT confirmation for this indication was received.
     839           0 :                 err = DriveSending();
     840           0 :                 SuccessOrExit(err);
     841             :             }
     842             :         }
     843           0 :         else if (mState == kState_Aborting) // Else, if we rejected BTP connection...
     844             :         {
     845           0 :             closeFlags |= kBleCloseFlag_SuppressCallback;
     846           0 :             err = BLE_ERROR_INCOMPATIBLE_PROTOCOL_VERSIONS;
     847           0 :             ExitNow();
     848             :         }
     849             :     }
     850             : 
     851           0 : exit:
     852             :     ChipLogDebugBleEndPoint(Ble, "exiting HandleHandshakeConfirmationReceived");
     853             : 
     854           0 :     if (err != CHIP_NO_ERROR)
     855             :     {
     856           0 :         DoClose(closeFlags, err);
     857             :     }
     858             : 
     859           0 :     return err;
     860             : }
     861             : 
     862           0 : CHIP_ERROR BLEEndPoint::HandleFragmentConfirmationReceived()
     863             : {
     864           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     865             : 
     866             :     ChipLogDebugBleEndPoint(Ble, "entered HandleFragmentConfirmationReceived");
     867             : 
     868             :     // Suppress error logging if GATT confirmation overlaps with unsubscribe on final close.
     869           0 :     if (IsUnsubscribePending())
     870             :     {
     871             :         ChipLogDebugBleEndPoint(Ble, "send conf rx'd while unsubscribe in flight");
     872           0 :         ExitNow();
     873             :     }
     874             : 
     875             :     // Ensure we're in correct state to receive confirmation of non-handshake GATT send.
     876           0 :     VerifyOrExit(IsConnected(mState), err = CHIP_ERROR_INCORRECT_STATE);
     877             : 
     878           0 :     if (mConnStateFlags.Has(ConnectionStateFlag::kStandAloneAckInFlight))
     879             :     {
     880             :         // If confirmation was received for stand-alone ack, free its tx buffer.
     881           0 :         mAckToSend = nullptr;
     882             : 
     883           0 :         mConnStateFlags.Clear(ConnectionStateFlag::kStandAloneAckInFlight);
     884             :     }
     885             : 
     886             :     // If local receive window size has shrunk to or below immediate ack threshold, AND a message fragment is not
     887             :     // pending on which to piggyback an ack, send immediate stand-alone ack.
     888             :     //
     889             :     // This check covers the case where the local receive window has shrunk between transmission and confirmation of
     890             :     // the stand-alone ack, and also the case where a window size < the immediate ack threshold was detected in
     891             :     // Receive(), but the stand-alone ack was deferred due to a pending outbound message fragment.
     892           0 :     if (mLocalReceiveWindowSize <= BLE_CONFIG_IMMEDIATE_ACK_WINDOW_THRESHOLD && mSendQueue.IsNull() &&
     893           0 :         mBtpEngine.TxState() != BtpEngine::kState_InProgress)
     894             :     {
     895           0 :         err = DriveStandAloneAck(); // Encode stand-alone ack and drive sending.
     896           0 :         SuccessOrExit(err);
     897             :     }
     898             :     else
     899             :     {
     900           0 :         err = DriveSending();
     901           0 :         SuccessOrExit(err);
     902             :     }
     903             : 
     904           0 : exit:
     905           0 :     if (err != CHIP_NO_ERROR)
     906             :     {
     907           0 :         DoClose(kBleCloseFlag_AbortTransmission, err);
     908             :     }
     909             : 
     910           0 :     return err;
     911             : }
     912             : 
     913           0 : CHIP_ERROR BLEEndPoint::HandleGattSendConfirmationReceived()
     914             : {
     915             :     ChipLogDebugBleEndPoint(Ble, "entered HandleGattSendConfirmationReceived");
     916             : 
     917             :     // Mark outstanding GATT operation as finished.
     918           0 :     mConnStateFlags.Clear(ConnectionStateFlag::kGattOperationInFlight);
     919             : 
     920             :     // If confirmation was for outbound portion of BTP connect handshake...
     921           0 :     if (!mConnStateFlags.Has(ConnectionStateFlag::kCapabilitiesConfReceived))
     922             :     {
     923           0 :         mConnStateFlags.Set(ConnectionStateFlag::kCapabilitiesConfReceived);
     924             : 
     925           0 :         return HandleHandshakeConfirmationReceived();
     926             :     }
     927             : 
     928           0 :     return HandleFragmentConfirmationReceived();
     929             : }
     930             : 
     931           0 : CHIP_ERROR BLEEndPoint::DriveStandAloneAck()
     932             : {
     933             :     // Stop send-ack timer if running.
     934           0 :     StopSendAckTimer();
     935             : 
     936             :     // If stand-alone ack not already pending, allocate new payload buffer here.
     937           0 :     if (mAckToSend.IsNull())
     938             :     {
     939           0 :         mAckToSend = System::PacketBufferHandle::New(kTransferProtocolStandaloneAckHeaderSize);
     940           0 :         VerifyOrReturnError(!mAckToSend.IsNull(), CHIP_ERROR_NO_MEMORY);
     941             :     }
     942             : 
     943             :     // Attempt to send stand-alone ack.
     944           0 :     return DriveSending();
     945             : }
     946             : 
     947           0 : CHIP_ERROR BLEEndPoint::DoSendStandAloneAck()
     948             : {
     949             :     ChipLogDebugBleEndPoint(Ble, "entered DoSendStandAloneAck; sending stand-alone ack");
     950             : 
     951             :     // Encode and transmit stand-alone ack.
     952           0 :     mBtpEngine.EncodeStandAloneAck(mAckToSend);
     953           0 :     ReturnErrorOnFailure(SendCharacteristic(mAckToSend.Retain()));
     954             : 
     955             :     // Reset local receive window counter.
     956           0 :     mLocalReceiveWindowSize = mReceiveWindowMaxSize;
     957             :     ChipLogDebugBleEndPoint(Ble, "reset local rx window on stand-alone ack tx, size = %u", mLocalReceiveWindowSize);
     958             : 
     959           0 :     mConnStateFlags.Set(ConnectionStateFlag::kStandAloneAckInFlight);
     960             : 
     961             :     // Start ack received timer, if it's not already running.
     962           0 :     return StartAckReceivedTimer();
     963             : }
     964             : 
     965           0 : CHIP_ERROR BLEEndPoint::DriveSending()
     966             : {
     967             :     ChipLogDebugBleEndPoint(Ble, "entered DriveSending");
     968             : 
     969             :     // If receiver's window is almost closed and we don't have an ack to send, OR we do have an ack to send but
     970             :     // receiver's window is completely empty, OR another GATT operation is in flight, awaiting confirmation...
     971           0 :     if ((mRemoteReceiveWindowSize <= BTP_WINDOW_NO_ACK_SEND_THRESHOLD &&
     972           0 :          !mTimerStateFlags.Has(TimerStateFlag::kSendAckTimerRunning) && mAckToSend.IsNull()) ||
     973           0 :         (mRemoteReceiveWindowSize == 0) || (mConnStateFlags.Has(ConnectionStateFlag::kGattOperationInFlight)))
     974             :     {
     975             : #ifdef CHIP_BLE_END_POINT_DEBUG_LOGGING_ENABLED
     976             :         if (mRemoteReceiveWindowSize <= BTP_WINDOW_NO_ACK_SEND_THRESHOLD &&
     977             :             !mTimerStateFlags.Has(TimerStateFlag::kSendAckTimerRunning) && mAckToSend.IsNull())
     978             :         {
     979             :             ChipLogDebugBleEndPoint(Ble, "NO SEND: receive window almost closed, and no ack to send");
     980             :         }
     981             : 
     982             :         if (mRemoteReceiveWindowSize == 0)
     983             :         {
     984             :             ChipLogDebugBleEndPoint(Ble, "NO SEND: remote receive window closed");
     985             :         }
     986             : 
     987             :         if (mConnStateFlags.Has(ConnectionStateFlag::kGattOperationInFlight))
     988             :         {
     989             :             ChipLogDebugBleEndPoint(Ble, "NO SEND: Gatt op in flight");
     990             :         }
     991             : #endif
     992             : 
     993             :         // Can't send anything.
     994           0 :         return CHIP_NO_ERROR;
     995             :     }
     996             : 
     997             :     // Otherwise, let's see what we can send.
     998             : 
     999           0 :     if (!mAckToSend.IsNull()) // If immediate, stand-alone ack is pending, send it.
    1000             :     {
    1001           0 :         ReturnErrorOnFailure(DoSendStandAloneAck());
    1002             :     }
    1003           0 :     else if (mBtpEngine.TxState() == BtpEngine::kState_Idle) // Else send next message fragment, if any.
    1004             :     {
    1005             :         // Fragmenter's idle, let's see what's in the send queue...
    1006           0 :         if (!mSendQueue.IsNull())
    1007             :         {
    1008             :             // Transmit first fragment of next whole message in send queue.
    1009           0 :             ReturnErrorOnFailure(SendNextMessage());
    1010             :         }
    1011             :         else
    1012             :         {
    1013             :             // Nothing to send!
    1014             :         }
    1015             :     }
    1016           0 :     else if (mBtpEngine.TxState() == BtpEngine::kState_InProgress)
    1017             :     {
    1018             :         // Send next fragment of message currently held by fragmenter.
    1019           0 :         ReturnErrorOnFailure(ContinueMessageSend());
    1020             :     }
    1021           0 :     else if (mBtpEngine.TxState() == BtpEngine::kState_Complete)
    1022             :     {
    1023             :         // Clear fragmenter's pointer to sent message buffer and reset its Tx state.
    1024             :         // Buffer will be freed at scope exit.
    1025           0 :         PacketBufferHandle sentBuf = mBtpEngine.TakeTxPacket();
    1026             : #if CHIP_ENABLE_CHIPOBLE_TEST
    1027             :         mBtpEngineTest.DoTxTiming(sentBuf, BTP_TX_DONE);
    1028             : #endif // CHIP_ENABLE_CHIPOBLE_TEST
    1029             : 
    1030           0 :         if (!mSendQueue.IsNull())
    1031             :         {
    1032             :             // Transmit first fragment of next whole message in send queue.
    1033           0 :             ReturnErrorOnFailure(SendNextMessage());
    1034             :         }
    1035           0 :         else if (mState == kState_Closing && !mBtpEngine.ExpectingAck()) // and mSendQueue is NULL, per above...
    1036             :         {
    1037             :             // If end point closing, got last ack, and got out-of-order confirmation for last send, finalize close.
    1038           0 :             FinalizeClose(mState, kBleCloseFlag_SuppressCallback, CHIP_NO_ERROR);
    1039             :         }
    1040             :         else
    1041             :         {
    1042             :             // Nothing to send!
    1043           0 :             mBle->mApplicationDelegate->CheckNonConcurrentBleClosing();
    1044             :         }
    1045           0 :     }
    1046             : 
    1047           0 :     return CHIP_NO_ERROR;
    1048             : }
    1049             : 
    1050           0 : CHIP_ERROR BLEEndPoint::HandleCapabilitiesRequestReceived(PacketBufferHandle && data)
    1051             : {
    1052             :     BleTransportCapabilitiesRequestMessage req;
    1053             :     BleTransportCapabilitiesResponseMessage resp;
    1054             :     uint16_t mtu;
    1055             : 
    1056           0 :     VerifyOrReturnError(!data.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
    1057             : 
    1058           0 :     mState = kState_Connecting;
    1059             : 
    1060             :     // Decode BTP capabilities request.
    1061           0 :     ReturnErrorOnFailure(BleTransportCapabilitiesRequestMessage::Decode(data, req));
    1062             : 
    1063           0 :     PacketBufferHandle responseBuf = System::PacketBufferHandle::New(kCapabilitiesResponseLength);
    1064           0 :     VerifyOrReturnError(!responseBuf.IsNull(), CHIP_ERROR_NO_MEMORY);
    1065             : 
    1066             :     // Determine BLE connection's negotiated ATT MTU, if possible.
    1067           0 :     if (req.mMtu > 0) // If MTU was observed and provided by central...
    1068             :     {
    1069           0 :         mtu = req.mMtu; // Accept central's observation of the MTU.
    1070             :     }
    1071             :     else // Otherwise, retrieve it via the platform delegate...
    1072             :     {
    1073           0 :         mtu = mBle->mPlatformDelegate->GetMTU(mConnObj);
    1074             :     }
    1075             : 
    1076             :     // Select fragment size for connection based on ATT MTU.
    1077           0 :     if (mtu > 0) // If one or both device knows connection's MTU...
    1078             :     {
    1079           0 :         resp.mFragmentSize =
    1080           0 :             chip::min(static_cast<uint16_t>(mtu - 3), BtpEngine::sMaxFragmentSize); // Reserve 3 bytes of MTU for ATT header.
    1081             :     }
    1082             :     else // Else, if neither device knows MTU...
    1083             :     {
    1084           0 :         ChipLogProgress(Ble, "cannot determine ATT MTU; selecting default fragment size = %u", BtpEngine::sDefaultFragmentSize);
    1085           0 :         resp.mFragmentSize = BtpEngine::sDefaultFragmentSize;
    1086             :     }
    1087             : 
    1088             :     // Select local and remote max receive window size based on local resources available for both incoming writes AND
    1089             :     // GATT confirmations.
    1090           0 :     mRemoteReceiveWindowSize = mLocalReceiveWindowSize = mReceiveWindowMaxSize =
    1091           0 :         chip::min(req.mWindowSize, static_cast<uint8_t>(BLE_MAX_RECEIVE_WINDOW_SIZE));
    1092           0 :     resp.mWindowSize = mReceiveWindowMaxSize;
    1093             : 
    1094           0 :     ChipLogProgress(Ble, "local and remote recv window sizes = %u", resp.mWindowSize);
    1095             : 
    1096             :     // Select BLE transport protocol version from those supported by central, or none if no supported version found.
    1097           0 :     resp.mSelectedProtocolVersion = BleLayer::GetHighestSupportedProtocolVersion(req);
    1098           0 :     ChipLogProgress(Ble, "selected BTP version %d", resp.mSelectedProtocolVersion);
    1099             : 
    1100           0 :     if (resp.mSelectedProtocolVersion == kBleTransportProtocolVersion_None)
    1101             :     {
    1102             :         // If BLE transport protocol versions incompatible, prepare to close connection after subscription has been
    1103             :         // received and capabilities response has been sent.
    1104           0 :         ChipLogError(Ble, "incompatible BTP versions; peripheral expected between %d and %d",
    1105             :                      CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION, CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION);
    1106           0 :         mState = kState_Aborting;
    1107             :     }
    1108             :     else
    1109             :     {
    1110             :         // Set Rx and Tx fragment sizes to the same value
    1111           0 :         mBtpEngine.SetRxFragmentSize(resp.mFragmentSize);
    1112           0 :         mBtpEngine.SetTxFragmentSize(resp.mFragmentSize);
    1113             :     }
    1114             : 
    1115           0 :     ChipLogProgress(Ble, "using BTP fragment sizes rx %d / tx %d.", mBtpEngine.GetRxFragmentSize(), mBtpEngine.GetTxFragmentSize());
    1116             : 
    1117           0 :     ReturnErrorOnFailure(resp.Encode(responseBuf));
    1118             : 
    1119             :     // Stash capabilities response payload and wait for subscription from central.
    1120           0 :     QueueTx(std::move(responseBuf), kType_Data);
    1121             : 
    1122             :     // Start receive timer. Canceled when end point freed or connection established.
    1123           0 :     return StartReceiveConnectionTimer();
    1124           0 : }
    1125             : 
    1126           0 : CHIP_ERROR BLEEndPoint::HandleCapabilitiesResponseReceived(PacketBufferHandle && data)
    1127             : {
    1128             :     BleTransportCapabilitiesResponseMessage resp;
    1129             : 
    1130           0 :     VerifyOrReturnError(!data.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
    1131             : 
    1132             :     // Decode BTP capabilities response.
    1133           0 :     ReturnErrorOnFailure(BleTransportCapabilitiesResponseMessage::Decode(data, resp));
    1134             : 
    1135           0 :     VerifyOrReturnError(resp.mFragmentSize > 0, BLE_ERROR_INVALID_FRAGMENT_SIZE);
    1136             : 
    1137           0 :     ChipLogProgress(Ble, "peripheral chose BTP version %d; central expected between %d and %d", resp.mSelectedProtocolVersion,
    1138             :                     CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION, CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION);
    1139             : 
    1140           0 :     if ((resp.mSelectedProtocolVersion < CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION) ||
    1141           0 :         (resp.mSelectedProtocolVersion > CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION))
    1142             :     {
    1143           0 :         return BLE_ERROR_INCOMPATIBLE_PROTOCOL_VERSIONS;
    1144             :     }
    1145             : 
    1146             :     // Set fragment size as minimum of (reported ATT MTU, BTP characteristic size)
    1147           0 :     resp.mFragmentSize = chip::min(resp.mFragmentSize, BtpEngine::sMaxFragmentSize);
    1148             : 
    1149           0 :     mBtpEngine.SetRxFragmentSize(resp.mFragmentSize);
    1150           0 :     mBtpEngine.SetTxFragmentSize(resp.mFragmentSize);
    1151             : 
    1152           0 :     ChipLogProgress(Ble, "using BTP fragment sizes rx %d / tx %d.", mBtpEngine.GetRxFragmentSize(), mBtpEngine.GetTxFragmentSize());
    1153             : 
    1154             :     // Select local and remote max receive window size based on local resources available for both incoming indications
    1155             :     // AND GATT confirmations.
    1156           0 :     mRemoteReceiveWindowSize = mLocalReceiveWindowSize = mReceiveWindowMaxSize = resp.mWindowSize;
    1157             : 
    1158           0 :     ChipLogProgress(Ble, "local and remote recv window size = %u", resp.mWindowSize);
    1159             : 
    1160             :     // Shrink local receive window counter by 1, since connect handshake indication requires acknowledgement.
    1161           0 :     mLocalReceiveWindowSize = static_cast<SequenceNumber_t>(mLocalReceiveWindowSize - 1);
    1162             :     ChipLogDebugBleEndPoint(Ble, "decremented local rx window, new size = %u", mLocalReceiveWindowSize);
    1163             : 
    1164             :     // Send ack for connection handshake indication when timer expires. Sequence numbers always start at 0,
    1165             :     // and the reassembler's "last received seq num" is initialized to 0 and updated when new fragments are
    1166             :     // received from the peripheral, so we don't need to explicitly mark the ack num to send here.
    1167           0 :     ReturnErrorOnFailure(StartSendAckTimer());
    1168             : 
    1169             :     // We've sent a capabilities request write and received a compatible response, so the connect
    1170             :     // operation has completed successfully.
    1171           0 :     return HandleConnectComplete();
    1172             : }
    1173             : 
    1174             : // Returns number of open slots in remote receive window given the input values.
    1175           0 : SequenceNumber_t BLEEndPoint::AdjustRemoteReceiveWindow(SequenceNumber_t lastReceivedAck, SequenceNumber_t maxRemoteWindowSize,
    1176             :                                                         SequenceNumber_t newestUnackedSentSeqNum)
    1177             : {
    1178             :     // Assumption: SequenceNumber_t is uint8_t.
    1179             :     // Assumption: Maximum possible sequence number value is UINT8_MAX.
    1180             :     // Assumption: Sequence numbers incremented past maximum value wrap to 0.
    1181             :     // Assumption: newest unacked sent sequence number never exceeds current (and by extension, new and un-wrapped)
    1182             :     //             window boundary, so it never wraps relative to last received ack, if new window boundary would not
    1183             :     //             also wrap.
    1184             : 
    1185             :     // Define new window boundary (inclusive) as uint16_t, so its value can temporarily exceed UINT8_MAX.
    1186           0 :     uint16_t newRemoteWindowBoundary = static_cast<uint16_t>(lastReceivedAck + maxRemoteWindowSize);
    1187             : 
    1188           0 :     if (newRemoteWindowBoundary > UINT8_MAX && newestUnackedSentSeqNum < lastReceivedAck)
    1189             :     {
    1190             :         // New window boundary WOULD wrap, and latest unacked seq num already HAS wrapped, so add offset to difference.
    1191           0 :         return static_cast<uint8_t>(newRemoteWindowBoundary - (newestUnackedSentSeqNum + UINT8_MAX));
    1192             :     }
    1193             : 
    1194             :     // Neither values would or have wrapped, OR new boundary WOULD wrap but latest unacked seq num does not, so no
    1195             :     // offset required.
    1196           0 :     return static_cast<uint8_t>(newRemoteWindowBoundary - newestUnackedSentSeqNum);
    1197             : }
    1198             : 
    1199           0 : CHIP_ERROR BLEEndPoint::Receive(PacketBufferHandle && data)
    1200             : {
    1201             :     ChipLogDebugBleEndPoint(Ble, "+++++++++++++++++++++ entered receive");
    1202           0 :     CHIP_ERROR err               = CHIP_NO_ERROR;
    1203           0 :     SequenceNumber_t receivedAck = 0;
    1204           0 :     uint8_t closeFlags           = kBleCloseFlag_AbortTransmission;
    1205           0 :     bool didReceiveAck           = false;
    1206             : 
    1207             : #if CHIP_ENABLE_CHIPOBLE_TEST
    1208             :     if (mBtpEngine.IsCommandPacket(data))
    1209             :     {
    1210             :         ChipLogDebugBleEndPoint(Ble, "%s: Received Control frame: Flags %x", __FUNCTION__, *(data->Start()));
    1211             :     }
    1212             :     else
    1213             : #endif
    1214             :     { // This is a special handling on the first CHIPoBLE data packet, the CapabilitiesRequest.
    1215             :         // Suppress error logging if peer's send overlaps with our unsubscribe on final close.
    1216           0 :         if (IsUnsubscribePending())
    1217             :         {
    1218             :             ChipLogDebugBleEndPoint(Ble, "characteristic rx'd while unsubscribe in flight");
    1219           0 :             ExitNow();
    1220             :         }
    1221             : 
    1222             :         // If we're receiving the first inbound packet of a BLE transport connection handshake...
    1223           0 :         if (!mConnStateFlags.Has(ConnectionStateFlag::kCapabilitiesMsgReceived))
    1224             :         {
    1225           0 :             if (mRole == kBleRole_Central) // If we're a central receiving a capabilities response indication...
    1226             :             {
    1227             :                 // Ensure end point's in the right state before continuing.
    1228           0 :                 VerifyOrExit(mState == kState_Connecting, err = CHIP_ERROR_INCORRECT_STATE);
    1229           0 :                 mConnStateFlags.Set(ConnectionStateFlag::kCapabilitiesMsgReceived);
    1230             : 
    1231           0 :                 err = HandleCapabilitiesResponseReceived(std::move(data));
    1232           0 :                 SuccessOrExit(err);
    1233             :             }
    1234             :             else // Or, a peripheral receiving a capabilities request write...
    1235             :             {
    1236             :                 // Ensure end point's in the right state before continuing.
    1237           0 :                 VerifyOrExit(mState == kState_Ready, err = CHIP_ERROR_INCORRECT_STATE);
    1238           0 :                 mConnStateFlags.Set(ConnectionStateFlag::kCapabilitiesMsgReceived);
    1239             : 
    1240           0 :                 err = HandleCapabilitiesRequestReceived(std::move(data));
    1241             : 
    1242           0 :                 if (err != CHIP_NO_ERROR)
    1243             :                 {
    1244             :                     // If an error occurred decoding and handling the capabilities request, release the BLE connection.
    1245             :                     // Central's connect attempt will time out if peripheral's application decides to keep the BLE
    1246             :                     // connection open, or fail immediately if the application closes the connection.
    1247           0 :                     closeFlags = closeFlags | kBleCloseFlag_SuppressCallback;
    1248           0 :                     ExitNow();
    1249             :                 }
    1250             :             }
    1251             : 
    1252             :             // If received data was handshake packet, don't feed it to message reassembler.
    1253           0 :             ExitNow();
    1254             :         }
    1255             :     } // End handling the CapabilitiesRequest
    1256             : 
    1257             :     ChipLogDebugBleEndPoint(Ble, "prepared to rx post-handshake btp packet");
    1258             : 
    1259             :     // We've received a post-handshake BTP packet.
    1260             :     // Ensure end point's in the right state before continuing.
    1261           0 :     if (!IsConnected(mState))
    1262             :     {
    1263           0 :         ChipLogError(Ble, "ep rx'd packet in bad state");
    1264           0 :         err = CHIP_ERROR_INCORRECT_STATE;
    1265             : 
    1266           0 :         ExitNow();
    1267             :     }
    1268             : 
    1269             :     ChipLogDebugBleEndPoint(Ble, "BTP about to rx characteristic, state before:");
    1270           0 :     mBtpEngine.LogStateDebug();
    1271             : 
    1272             :     // Pass received packet into BTP protocol engine.
    1273           0 :     err = mBtpEngine.HandleCharacteristicReceived(std::move(data), receivedAck, didReceiveAck);
    1274             : 
    1275             :     ChipLogDebugBleEndPoint(Ble, "BTP rx'd characteristic, state after:");
    1276           0 :     mBtpEngine.LogStateDebug();
    1277             : 
    1278           0 :     SuccessOrExit(err);
    1279             : 
    1280             :     // Protocol engine accepted the fragment, so shrink local receive window counter by 1.
    1281           0 :     mLocalReceiveWindowSize = static_cast<SequenceNumber_t>(mLocalReceiveWindowSize - 1);
    1282             :     ChipLogDebugBleEndPoint(Ble, "decremented local rx window, new size = %u", mLocalReceiveWindowSize);
    1283             : 
    1284             :     // Respond to received ack, if any.
    1285           0 :     if (didReceiveAck)
    1286             :     {
    1287             :         ChipLogDebugBleEndPoint(Ble, "got btp ack = %u", receivedAck);
    1288             : 
    1289             :         // If ack was rx'd for neweset unacked sent fragment, stop ack received timer.
    1290           0 :         if (!mBtpEngine.ExpectingAck())
    1291             :         {
    1292             :             ChipLogDebugBleEndPoint(Ble, "got ack for last outstanding fragment");
    1293           0 :             StopAckReceivedTimer();
    1294             : 
    1295           0 :             if (mState == kState_Closing && mSendQueue.IsNull() && mBtpEngine.TxState() == BtpEngine::kState_Idle)
    1296             :             {
    1297             :                 // If end point closing, got confirmation for last send, and waiting for last ack, finalize close.
    1298           0 :                 FinalizeClose(mState, kBleCloseFlag_SuppressCallback, CHIP_NO_ERROR);
    1299           0 :                 ExitNow();
    1300             :             }
    1301             :         }
    1302             :         else // Else there are still sent fragments for which acks are expected, so restart ack received timer.
    1303             :         {
    1304             :             ChipLogDebugBleEndPoint(Ble, "still expecting ack(s), restarting timer...");
    1305           0 :             err = RestartAckReceivedTimer();
    1306           0 :             SuccessOrExit(err);
    1307             :         }
    1308             : 
    1309             :         ChipLogDebugBleEndPoint(Ble, "about to adjust remote rx window; got ack num = %u, newest unacked sent seq num = %u, \
    1310             :                 old window size = %u, max window size = %u",
    1311             :                                 receivedAck, mBtpEngine.GetNewestUnackedSentSequenceNumber(), mRemoteReceiveWindowSize,
    1312             :                                 mReceiveWindowMaxSize);
    1313             : 
    1314             :         // Open remote device's receive window according to sequence number it just acknowledged.
    1315           0 :         mRemoteReceiveWindowSize =
    1316           0 :             AdjustRemoteReceiveWindow(receivedAck, mReceiveWindowMaxSize, mBtpEngine.GetNewestUnackedSentSequenceNumber());
    1317             : 
    1318             :         ChipLogDebugBleEndPoint(Ble, "adjusted remote rx window, new size = %u", mRemoteReceiveWindowSize);
    1319             : 
    1320             :         // Restart message transmission if it was previously paused due to window exhaustion.
    1321           0 :         err = DriveSending();
    1322           0 :         SuccessOrExit(err);
    1323             :     }
    1324             : 
    1325             :     // The previous DriveSending() might have generated a piggyback acknowledgement if there was
    1326             :     // previously un-acked data.  Otherwise, prepare to send acknowledgement for newly received fragment.
    1327             :     //
    1328             :     // If local receive window is below immediate ack threshold, AND there is no previous stand-alone ack in
    1329             :     // flight, AND there is no pending outbound message fragment on which the ack can and will be piggybacked,
    1330             :     // send immediate stand-alone ack to reopen window for sender.
    1331             :     //
    1332             :     // The "GATT operation in flight" check below covers "pending outbound message fragment" by extension, as when
    1333             :     // a message has been passed to the end point via Send(), its next outbound fragment must either be in flight
    1334             :     // itself, or awaiting the completion of another in-flight GATT operation.
    1335             :     //
    1336             :     // If any GATT operation is in flight that is NOT a stand-alone ack, the window size will be checked against
    1337             :     // this threshold again when the GATT operation is confirmed.
    1338           0 :     if (mBtpEngine.HasUnackedData())
    1339             :     {
    1340           0 :         if (mLocalReceiveWindowSize <= BLE_CONFIG_IMMEDIATE_ACK_WINDOW_THRESHOLD &&
    1341           0 :             !mConnStateFlags.Has(ConnectionStateFlag::kGattOperationInFlight))
    1342             :         {
    1343             :             ChipLogDebugBleEndPoint(Ble, "sending immediate ack");
    1344           0 :             err = DriveStandAloneAck();
    1345           0 :             SuccessOrExit(err);
    1346             :         }
    1347             :         else
    1348             :         {
    1349             :             ChipLogDebugBleEndPoint(Ble, "starting send-ack timer");
    1350             : 
    1351             :             // Send ack when timer expires.
    1352           0 :             err = StartSendAckTimer();
    1353           0 :             SuccessOrExit(err);
    1354             :         }
    1355             :     }
    1356             : 
    1357             :     // If we've reassembled a whole message...
    1358           0 :     if (mBtpEngine.RxState() == BtpEngine::kState_Complete)
    1359             :     {
    1360             :         // Take ownership of message buffer
    1361           0 :         System::PacketBufferHandle full_packet = mBtpEngine.TakeRxPacket();
    1362             : 
    1363             :         ChipLogDebugBleEndPoint(Ble, "reassembled whole msg, len = %d", full_packet->DataLength());
    1364             : 
    1365             : #if CHIP_ENABLE_CHIPOBLE_TEST
    1366             :         // If we have a control message received callback, and end point is not closing...
    1367             :         if (mBtpEngine.RxPacketType() == kType_Control && OnCommandReceived && mState != kState_Closing)
    1368             :         {
    1369             :             ChipLogDebugBleEndPoint(Ble, "%s: calling OnCommandReceived, seq# %u, len = %u, type %u", __FUNCTION__, receivedAck,
    1370             :                                     full_packet->DataLength(), mBtpEngine.RxPacketType());
    1371             :             // Pass received control message up the stack.
    1372             :             mBtpEngine.SetRxPacketSeq(receivedAck);
    1373             :             OnCommandReceived(this, std::move(full_packet));
    1374             :         }
    1375             :         else
    1376             : #endif
    1377             :             // If we have a message received callback, and end point is not closing...
    1378           0 :             if (mBleTransport != nullptr && mState != kState_Closing)
    1379             :             {
    1380             :                 // Pass received message up the stack.
    1381           0 :                 mBleTransport->OnEndPointMessageReceived(this, std::move(full_packet));
    1382             :             }
    1383           0 :     }
    1384             : 
    1385           0 : exit:
    1386           0 :     if (err != CHIP_NO_ERROR)
    1387             :     {
    1388           0 :         DoClose(closeFlags, err);
    1389             :     }
    1390             : 
    1391           0 :     return err;
    1392             : }
    1393             : 
    1394           0 : bool BLEEndPoint::SendWrite(PacketBufferHandle && buf)
    1395             : {
    1396           0 :     mConnStateFlags.Set(ConnectionStateFlag::kGattOperationInFlight);
    1397             : 
    1398           0 :     return mBle->mPlatformDelegate->SendWriteRequest(mConnObj, &CHIP_BLE_SVC_ID, &mBle->CHIP_BLE_CHAR_1_ID, std::move(buf));
    1399             : }
    1400             : 
    1401           0 : bool BLEEndPoint::SendIndication(PacketBufferHandle && buf)
    1402             : {
    1403           0 :     mConnStateFlags.Set(ConnectionStateFlag::kGattOperationInFlight);
    1404             : 
    1405           0 :     return mBle->mPlatformDelegate->SendIndication(mConnObj, &CHIP_BLE_SVC_ID, &mBle->CHIP_BLE_CHAR_2_ID, std::move(buf));
    1406             : }
    1407             : 
    1408           0 : CHIP_ERROR BLEEndPoint::StartConnectTimer()
    1409             : {
    1410             :     const CHIP_ERROR timerErr =
    1411           0 :         mBle->mSystemLayer->StartTimer(System::Clock::Milliseconds32(BTP_CONN_RSP_TIMEOUT_MS), HandleConnectTimeout, this);
    1412           0 :     ReturnErrorOnFailure(timerErr);
    1413           0 :     mTimerStateFlags.Set(TimerStateFlag::kConnectTimerRunning);
    1414             : 
    1415           0 :     return CHIP_NO_ERROR;
    1416             : }
    1417             : 
    1418           0 : CHIP_ERROR BLEEndPoint::StartReceiveConnectionTimer()
    1419             : {
    1420           0 :     const CHIP_ERROR timerErr = mBle->mSystemLayer->StartTimer(System::Clock::Milliseconds32(BTP_CONN_RSP_TIMEOUT_MS),
    1421             :                                                                HandleReceiveConnectionTimeout, this);
    1422           0 :     ReturnErrorOnFailure(timerErr);
    1423           0 :     mTimerStateFlags.Set(TimerStateFlag::kReceiveConnectionTimerRunning);
    1424             : 
    1425           0 :     return CHIP_NO_ERROR;
    1426             : }
    1427             : 
    1428           0 : CHIP_ERROR BLEEndPoint::StartAckReceivedTimer()
    1429             : {
    1430           0 :     if (!mTimerStateFlags.Has(TimerStateFlag::kAckReceivedTimerRunning))
    1431             :     {
    1432             :         const CHIP_ERROR timerErr =
    1433           0 :             mBle->mSystemLayer->StartTimer(System::Clock::Milliseconds32(BTP_ACK_TIMEOUT_MS), HandleAckReceivedTimeout, this);
    1434           0 :         ReturnErrorOnFailure(timerErr);
    1435             : 
    1436           0 :         mTimerStateFlags.Set(TimerStateFlag::kAckReceivedTimerRunning);
    1437             :     }
    1438             : 
    1439           0 :     return CHIP_NO_ERROR;
    1440             : }
    1441             : 
    1442           0 : CHIP_ERROR BLEEndPoint::RestartAckReceivedTimer()
    1443             : {
    1444           0 :     VerifyOrReturnError(mTimerStateFlags.Has(TimerStateFlag::kAckReceivedTimerRunning), CHIP_ERROR_INCORRECT_STATE);
    1445             : 
    1446           0 :     StopAckReceivedTimer();
    1447             : 
    1448           0 :     return StartAckReceivedTimer();
    1449             : }
    1450             : 
    1451           0 : CHIP_ERROR BLEEndPoint::StartSendAckTimer()
    1452             : {
    1453             :     ChipLogDebugBleEndPoint(Ble, "entered StartSendAckTimer");
    1454             : 
    1455           0 :     if (!mTimerStateFlags.Has(TimerStateFlag::kSendAckTimerRunning))
    1456             :     {
    1457             :         ChipLogDebugBleEndPoint(Ble, "starting new SendAckTimer");
    1458             :         const CHIP_ERROR timerErr =
    1459           0 :             mBle->mSystemLayer->StartTimer(System::Clock::Milliseconds32(BTP_ACK_SEND_TIMEOUT_MS), HandleSendAckTimeout, this);
    1460           0 :         ReturnErrorOnFailure(timerErr);
    1461             : 
    1462           0 :         mTimerStateFlags.Set(TimerStateFlag::kSendAckTimerRunning);
    1463             :     }
    1464             : 
    1465           0 :     return CHIP_NO_ERROR;
    1466             : }
    1467             : 
    1468           0 : CHIP_ERROR BLEEndPoint::StartUnsubscribeTimer()
    1469             : {
    1470             :     const CHIP_ERROR timerErr =
    1471           0 :         mBle->mSystemLayer->StartTimer(System::Clock::Milliseconds32(BLE_UNSUBSCRIBE_TIMEOUT_MS), HandleUnsubscribeTimeout, this);
    1472           0 :     ReturnErrorOnFailure(timerErr);
    1473           0 :     mTimerStateFlags.Set(TimerStateFlag::kUnsubscribeTimerRunning);
    1474             : 
    1475           0 :     return CHIP_NO_ERROR;
    1476             : }
    1477             : 
    1478           0 : void BLEEndPoint::StopConnectTimer()
    1479             : {
    1480             :     // Cancel any existing connect timer.
    1481           0 :     mBle->mSystemLayer->CancelTimer(HandleConnectTimeout, this);
    1482           0 :     mTimerStateFlags.Clear(TimerStateFlag::kConnectTimerRunning);
    1483           0 : }
    1484             : 
    1485           0 : void BLEEndPoint::StopReceiveConnectionTimer()
    1486             : {
    1487             :     // Cancel any existing receive connection timer.
    1488           0 :     mBle->mSystemLayer->CancelTimer(HandleReceiveConnectionTimeout, this);
    1489           0 :     mTimerStateFlags.Clear(TimerStateFlag::kReceiveConnectionTimerRunning);
    1490           0 : }
    1491             : 
    1492           0 : void BLEEndPoint::StopAckReceivedTimer()
    1493             : {
    1494             :     // Cancel any existing ack-received timer.
    1495           0 :     mBle->mSystemLayer->CancelTimer(HandleAckReceivedTimeout, this);
    1496           0 :     mTimerStateFlags.Clear(TimerStateFlag::kAckReceivedTimerRunning);
    1497           0 : }
    1498             : 
    1499           0 : void BLEEndPoint::StopSendAckTimer()
    1500             : {
    1501             :     // Cancel any existing send-ack timer.
    1502           0 :     mBle->mSystemLayer->CancelTimer(HandleSendAckTimeout, this);
    1503           0 :     mTimerStateFlags.Clear(TimerStateFlag::kSendAckTimerRunning);
    1504           0 : }
    1505             : 
    1506           0 : void BLEEndPoint::StopUnsubscribeTimer()
    1507             : {
    1508             :     // Cancel any existing unsubscribe timer.
    1509           0 :     mBle->mSystemLayer->CancelTimer(HandleUnsubscribeTimeout, this);
    1510           0 :     mTimerStateFlags.Clear(TimerStateFlag::kUnsubscribeTimerRunning);
    1511           0 : }
    1512             : 
    1513           0 : void BLEEndPoint::HandleConnectTimeout(chip::System::Layer * systemLayer, void * appState)
    1514             : {
    1515           0 :     BLEEndPoint * ep = static_cast<BLEEndPoint *>(appState);
    1516             : 
    1517             :     // Check for event-based timer race condition.
    1518           0 :     if (ep->mTimerStateFlags.Has(TimerStateFlag::kConnectTimerRunning))
    1519             :     {
    1520           0 :         ChipLogError(Ble, "connect handshake timed out, closing ep %p", ep);
    1521           0 :         ep->mTimerStateFlags.Clear(TimerStateFlag::kConnectTimerRunning);
    1522           0 :         ep->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_CONNECT_TIMED_OUT);
    1523             :     }
    1524           0 : }
    1525             : 
    1526           0 : void BLEEndPoint::HandleReceiveConnectionTimeout(chip::System::Layer * systemLayer, void * appState)
    1527             : {
    1528           0 :     BLEEndPoint * ep = static_cast<BLEEndPoint *>(appState);
    1529             : 
    1530             :     // Check for event-based timer race condition.
    1531           0 :     if (ep->mTimerStateFlags.Has(TimerStateFlag::kReceiveConnectionTimerRunning))
    1532             :     {
    1533           0 :         ChipLogError(Ble, "receive handshake timed out, closing ep %p", ep);
    1534           0 :         ep->mTimerStateFlags.Clear(TimerStateFlag::kReceiveConnectionTimerRunning);
    1535           0 :         ep->DoClose(kBleCloseFlag_SuppressCallback | kBleCloseFlag_AbortTransmission, BLE_ERROR_RECEIVE_TIMED_OUT);
    1536             :     }
    1537           0 : }
    1538             : 
    1539           0 : void BLEEndPoint::HandleAckReceivedTimeout(chip::System::Layer * systemLayer, void * appState)
    1540             : {
    1541           0 :     BLEEndPoint * ep = static_cast<BLEEndPoint *>(appState);
    1542             : 
    1543             :     // Check for event-based timer race condition.
    1544           0 :     if (ep->mTimerStateFlags.Has(TimerStateFlag::kAckReceivedTimerRunning))
    1545             :     {
    1546           0 :         ChipLogError(Ble, "ack recv timeout, closing ep %p", ep);
    1547           0 :         ep->mBtpEngine.LogStateDebug();
    1548           0 :         ep->mTimerStateFlags.Clear(TimerStateFlag::kAckReceivedTimerRunning);
    1549           0 :         ep->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_FRAGMENT_ACK_TIMED_OUT);
    1550             :     }
    1551           0 : }
    1552             : 
    1553           0 : void BLEEndPoint::HandleSendAckTimeout(chip::System::Layer * systemLayer, void * appState)
    1554             : {
    1555           0 :     BLEEndPoint * ep = static_cast<BLEEndPoint *>(appState);
    1556             : 
    1557             :     // Check for event-based timer race condition.
    1558           0 :     if (ep->mTimerStateFlags.Has(TimerStateFlag::kSendAckTimerRunning))
    1559             :     {
    1560           0 :         ep->mTimerStateFlags.Clear(TimerStateFlag::kSendAckTimerRunning);
    1561             : 
    1562             :         // If previous stand-alone ack isn't still in flight...
    1563           0 :         if (!ep->mConnStateFlags.Has(ConnectionStateFlag::kStandAloneAckInFlight))
    1564             :         {
    1565           0 :             CHIP_ERROR sendErr = ep->DriveStandAloneAck();
    1566             : 
    1567           0 :             if (sendErr != CHIP_NO_ERROR)
    1568             :             {
    1569           0 :                 ep->DoClose(kBleCloseFlag_AbortTransmission, sendErr);
    1570             :             }
    1571             :         }
    1572             :     }
    1573           0 : }
    1574             : 
    1575           0 : void BLEEndPoint::HandleUnsubscribeTimeout(chip::System::Layer * systemLayer, void * appState)
    1576             : {
    1577           0 :     BLEEndPoint * ep = static_cast<BLEEndPoint *>(appState);
    1578             : 
    1579             :     // Check for event-based timer race condition.
    1580           0 :     if (ep->mTimerStateFlags.Has(TimerStateFlag::kUnsubscribeTimerRunning))
    1581             :     {
    1582           0 :         ChipLogError(Ble, "unsubscribe timed out, ble ep %p", ep);
    1583           0 :         ep->mTimerStateFlags.Clear(TimerStateFlag::kUnsubscribeTimerRunning);
    1584           0 :         ep->HandleUnsubscribeComplete();
    1585             :     }
    1586           0 : }
    1587             : 
    1588             : } /* namespace Ble */
    1589             : } /* namespace chip */
    1590             : 
    1591             : #endif /* CONFIG_NETWORK_LAYER_BLE */

Generated by: LCOV version 1.14