| /* |
| * |
| * Copyright (c) 2020-2021 Project CHIP Authors |
| * Copyright (c) 2014-2017 Nest Labs, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @file |
| * This file defines a Bluetooth Low Energy (BLE) connection |
| * endpoint abstraction for the byte-streaming, |
| * connection-oriented CHIP over Bluetooth Low Energy (CHIPoBLE) |
| * Bluetooth Transport Protocol (BTP). |
| * |
| */ |
| |
| #pragma once |
| |
| #include <system/SystemLayer.h> |
| #include <system/SystemMutex.h> |
| |
| #include <ble/BleRole.h> |
| #include <ble/BtpEngine.h> |
| #if CHIP_ENABLE_CHIPOBLE_TEST |
| #include <ble/BtpEngineTest.h> |
| #endif |
| |
| namespace chip { |
| namespace Ble { |
| |
| using ::chip::System::PacketBufferHandle; |
| |
| enum |
| { |
| kBleCloseFlag_SuppressCallback = 0x01, |
| kBleCloseFlag_AbortTransmission = 0x02 |
| }; |
| |
| // Forward declarations |
| class BleLayer; |
| class BleEndPointPool; |
| // BLEEndPoint holds a pointer to BleLayerDelegate for messages, while BleLayerDelegate functions also accepts BLEEndPoint. |
| class BleLayerDelegate; |
| #if CHIP_ENABLE_CHIPOBLE_TEST |
| class BtpEngineTest; |
| #endif |
| |
| class DLL_EXPORT BLEEndPoint |
| { |
| friend class BleLayer; |
| friend class BleEndPointPool; |
| #if CHIP_ENABLE_CHIPOBLE_TEST |
| friend class BtpEngineTest; |
| #endif |
| |
| public: |
| typedef uint64_t AlignT; |
| |
| // Public data members: |
| enum |
| { |
| kState_Ready = 0, |
| kState_Connecting = 1, |
| kState_Aborting = 2, |
| kState_Connected = 3, |
| kState_Closing = 4, |
| kState_Closed = 5 |
| } mState; // [READ-ONLY] End point connection state. Refers to state of CHIP over |
| // BLE transport protocol connection, not of underlying BLE connection. |
| |
| // Public function pointers: |
| typedef void (*OnConnectCompleteFunct)(BLEEndPoint * endPoint, CHIP_ERROR err); |
| OnConnectCompleteFunct OnConnectComplete; |
| |
| typedef void (*OnMessageReceivedFunct)(BLEEndPoint * endPoint, PacketBufferHandle && msg); |
| OnMessageReceivedFunct OnMessageReceived; |
| |
| typedef void (*OnConnectionClosedFunct)(BLEEndPoint * endPoint, CHIP_ERROR err); |
| OnConnectionClosedFunct OnConnectionClosed; |
| |
| #if CHIP_ENABLE_CHIPOBLE_TEST |
| typedef void (*OnCommandReceivedFunct)(BLEEndPoint * endPoint, PacketBufferHandle && msg); |
| OnCommandReceivedFunct OnCommandReceived; |
| inline void SetOnCommandReceivedCB(OnCommandReceivedFunct cb) { OnCommandReceived = cb; }; |
| BtpEngineTest mBtpEngineTest; |
| inline void SetTxWindowSize(uint8_t size) { mRemoteReceiveWindowSize = size; }; |
| inline void SetRxWindowSize(uint8_t size) { mReceiveWindowMaxSize = size; }; |
| #endif |
| |
| // Public functions: |
| CHIP_ERROR Send(PacketBufferHandle && data); |
| CHIP_ERROR Receive(PacketBufferHandle && data); |
| CHIP_ERROR StartConnect(); |
| |
| bool IsUnsubscribePending() const; |
| bool ConnectionObjectIs(BLE_CONNECTION_OBJECT connObj) { return connObj == mConnObj; } |
| void Close(); |
| void Abort(); |
| void ReleaseBleConnection(); |
| |
| private: |
| BleLayer * mBle; ///< [READ-ONLY] Pointer to the BleLayer object that owns this object. |
| BleLayerDelegate * mBleTransport; |
| |
| uint32_t mRefCount; |
| |
| void AddRef() { mRefCount++; } |
| void Release(); |
| |
| // Private data members: |
| enum class ConnectionStateFlag : uint8_t |
| { |
| kAutoClose = 0x01, // End point should close underlying BLE conn on BTP close. |
| kCapabilitiesConfReceived = 0x02, // GATT confirmation received for sent capabilities req/resp. |
| kCapabilitiesMsgReceived = 0x04, // Capabilities request or response message received. |
| kDidBeginSubscribe = 0x08, // GATT subscribe request sent; must unsubscribe on close. |
| kStandAloneAckInFlight = 0x10, // Stand-alone ack in flight, awaiting GATT confirmation. |
| kGattOperationInFlight = 0x20 // GATT write, indication, subscribe, or unsubscribe in flight, |
| // awaiting GATT confirmation. |
| }; |
| |
| enum class TimerStateFlag : uint8_t |
| { |
| kConnectTimerRunning = 0x01, // BTP connect completion timer running. |
| kReceiveConnectionTimerRunning = 0x02, // BTP receive connection completion timer running. |
| kAckReceivedTimerRunning = 0x04, // Ack received timer running due to unacked sent fragment. |
| kSendAckTimerRunning = 0x08, // Send ack timer running; indicates pending ack to send. |
| kUnsubscribeTimerRunning = 0x10, // Unsubscribe completion timer running. |
| #if CHIP_ENABLE_CHIPOBLE_TEST |
| kUnderTestTimerRunnung = 0x80 // running throughput Tx test |
| #endif |
| }; |
| |
| // BLE connection to which an end point is uniquely bound. Type BLE_CONNECTION_OBJECT is defined by the platform or |
| // void* by default. This object is passed back to the platform delegate with each call to send traffic over or |
| // modify the state of the underlying BLE connection. |
| BLE_CONNECTION_OBJECT mConnObj; |
| |
| // Queue of outgoing messages to send when current BtpEngine transmission completes. |
| // |
| // Re-used during connection setup to cache capabilities request and response payloads; payloads are freed when |
| // connection is established. |
| PacketBufferHandle mSendQueue; |
| |
| // Pending stand-alone BTP acknowledgement. Pre-empts regular send queue or fragmented message transmission in |
| // progress. |
| PacketBufferHandle mAckToSend; |
| |
| BtpEngine mBtpEngine; |
| BleRole mRole; |
| BitFlags<ConnectionStateFlag> mConnStateFlags; |
| BitFlags<TimerStateFlag> mTimerStateFlags; |
| SequenceNumber_t mLocalReceiveWindowSize; |
| SequenceNumber_t mRemoteReceiveWindowSize; |
| SequenceNumber_t mReceiveWindowMaxSize; |
| #if CHIP_ENABLE_CHIPOBLE_TEST |
| chip::System::Mutex mTxQueueMutex; // For MT-safe Tx queuing |
| #endif |
| |
| // Private functions: |
| BLEEndPoint() = delete; |
| ~BLEEndPoint() = delete; |
| |
| CHIP_ERROR Init(BleLayer * bleLayer, BLE_CONNECTION_OBJECT connObj, BleRole role, bool autoClose); |
| bool IsConnected(uint8_t state) const; |
| void DoClose(uint8_t flags, CHIP_ERROR err); |
| |
| // Transmit path: |
| CHIP_ERROR DriveSending(); |
| CHIP_ERROR DriveStandAloneAck(); |
| bool PrepareNextFragment(PacketBufferHandle && data, bool & sentAck); |
| CHIP_ERROR SendNextMessage(); |
| CHIP_ERROR ContinueMessageSend(); |
| CHIP_ERROR DoSendStandAloneAck(); |
| CHIP_ERROR SendCharacteristic(PacketBufferHandle && buf); |
| bool SendIndication(PacketBufferHandle && buf); |
| bool SendWrite(PacketBufferHandle && buf); |
| |
| // Receive path: |
| CHIP_ERROR HandleConnectComplete(); |
| CHIP_ERROR HandleReceiveConnectionComplete(); |
| void HandleSubscribeReceived(); |
| void HandleSubscribeComplete(); |
| void HandleUnsubscribeComplete(); |
| CHIP_ERROR HandleGattSendConfirmationReceived(); |
| CHIP_ERROR HandleHandshakeConfirmationReceived(); |
| CHIP_ERROR HandleFragmentConfirmationReceived(); |
| CHIP_ERROR HandleCapabilitiesRequestReceived(PacketBufferHandle && data); |
| CHIP_ERROR HandleCapabilitiesResponseReceived(PacketBufferHandle && data); |
| SequenceNumber_t AdjustRemoteReceiveWindow(SequenceNumber_t lastReceivedAck, SequenceNumber_t maxRemoteWindowSize, |
| SequenceNumber_t newestUnackedSentSeqNum); |
| |
| // Timer control functions: |
| CHIP_ERROR StartConnectTimer(); // Start connect timer. |
| CHIP_ERROR StartReceiveConnectionTimer(); // Start receive connection timer. |
| CHIP_ERROR StartAckReceivedTimer(); // Start ack-received timer if it's not already running. |
| CHIP_ERROR RestartAckReceivedTimer(); // Restart ack-received timer. |
| CHIP_ERROR StartSendAckTimer(); // Start send-ack timer if it's not already running. |
| CHIP_ERROR StartUnsubscribeTimer(); |
| void StopConnectTimer(); // Stop connect timer. |
| void StopReceiveConnectionTimer(); // Stop receive connection timer. |
| void StopAckReceivedTimer(); // Stop ack-received timer. |
| void StopSendAckTimer(); // Stop send-ack timer. |
| void StopUnsubscribeTimer(); // Stop unsubscribe timer. |
| |
| // Timer expired callbacks: |
| static void HandleConnectTimeout(chip::System::Layer * systemLayer, void * appState); |
| static void HandleReceiveConnectionTimeout(chip::System::Layer * systemLayer, void * appState); |
| static void HandleAckReceivedTimeout(chip::System::Layer * systemLayer, void * appState); |
| static void HandleSendAckTimeout(chip::System::Layer * systemLayer, void * appState); |
| static void HandleUnsubscribeTimeout(chip::System::Layer * systemLayer, void * appState); |
| |
| // Close functions: |
| void DoCloseCallback(uint8_t state, uint8_t flags, CHIP_ERROR err); |
| void FinalizeClose(uint8_t state, uint8_t flags, CHIP_ERROR err); |
| void Free(); |
| void FreeBtpEngine(); |
| |
| // Mutex lock on Tx queue. Used only in BtpEngine test build for now. |
| #if CHIP_ENABLE_CHIPOBLE_TEST |
| inline void QueueTxLock() { mTxQueueMutex.Lock(); } |
| inline void QueueTxUnlock() { mTxQueueMutex.Unlock(); } |
| #else |
| inline void QueueTxLock() {} |
| inline void QueueTxUnlock() {} |
| #endif |
| void QueueTx(PacketBufferHandle && data, PacketType_t type); |
| }; |
| |
| } /* namespace Ble */ |
| } /* namespace chip */ |