blob: 7a50256ca064a4d9c86405b05d5b40eeb39d903b [file] [log] [blame]
/*
*
* 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();
private:
BleLayer * mBle; ///< [READ-ONLY] Pointer to the BleLayer object that owns this object.
BleLayerDelegate * mBleTransport;
uint32_t mRefCount;
void AddRef();
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 ReleaseBleConnection();
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 */