blob: 5f9f67149635c9be0f27b1ca84f9c84081dd6aae [file] [log] [blame]
/*
*
* <COPYRIGHT>
*
* 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 objects that provide an abstraction layer between a
* platform's Bluetooth Low Energy (BLE) implementation and the chip
* stack.
*
* The BleLayer obect accepts BLE data and control input from the
* application via a functional interface. It performs the fragmentation
* and reassembly required to transmit chip message via a BLE GATT
* characteristic interface, and drives incoming messages up the chip
* stack.
*
* During initialization, the BleLayer object requires a pointer to the
* platform's implementation of the BleAdapter object. This object is
* defined but not implemented by the chip stack, and provides the
* BleLayer with a functional interface to drive outgoing GATT
* characteristic writes and indications. It also provides a mechanism
* for chip to inform the application when it has finished using a given
* BLE connection, i.e., when the chipConnection object wrapping this
* connection has closed.
*
* To enable chip over BLE for a new platform, the application developer
* must implement the BleAdapter class for their platform, pass it to the
* BleLayer on startup, pass a pointer to this BleLayer to their instance
* of chipMessageLayer, and ensure that the application calls the
* necessary BleLayer functions to drive BLE data and control input up the
* stack.
*/
#ifndef BLELAYER_H_
#define BLELAYER_H_
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#include <stdint.h>
#include <ble/BleConfig.h>
#include <system/SystemLayer.h>
#include <system/SystemPacketBuffer.h>
#include <ble/BlePlatformDelegate.h>
#include <ble/BleApplicationDelegate.h>
#include <ble/BleUUID.h>
#include <ble/BleError.h>
#if BLE_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
#include <inet/InetLayer.h>
#endif // BLE_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
namespace chip {
namespace Ble {
using ::chip::System::PacketBuffer;
/**
* @def NUM_SUPPORTED_PROTOCOL_VERSIONS
*
* Number of unsigned 4-bit representations of supported transport protocol
* versions encapsulated in a BleTransportCapabilitiesRequest. Defined by chip
* over BLE protocol specification.
*/
#define NUM_SUPPORTED_PROTOCOL_VERSIONS 8
/// Version(s) of the CHIP BLE Transport Protocol that this stack supports.
#define CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION kBleTransportProtocolVersion_V2
#define CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION kBleTransportProtocolVersion_V3
/// Forward declarations.
class BleLayer;
class BLEEndPoint;
/// Role of end points' associated BLE connections. Determines means used by end points to send and receive data.
typedef enum
{
kBleRole_Central = 0,
kBleRole_Peripheral = 1
} BleRole;
/// Enum defining versions of chip over BLE transport protocol.
typedef enum
{
kBleTransportProtocolVersion_None = 0,
kBleTransportProtocolVersion_V1 = 1, // Prototype WoBLe version without ACKs or flow-control.
kBleTransportProtocolVersion_V2 = 2, // First WoBLE version with ACKs and flow-control.
kBleTransportProtocolVersion_V3 = 3 // First WoBLE version with asymetric fragement sizes.
} BleTransportProtocolVersion;
class BleLayerObject
{
friend class BleLayer;
public:
// Public data members:
BleLayer * mBle; ///< [READ-ONLY] Pointer to the BleLayer object that owns this object.
void * mAppState; ///< Generic pointer to app-specific data associated with the object.
protected:
uint32_t mRefCount;
void AddRef(void) { mRefCount++; }
void Release(void);
};
class BleTransportCapabilitiesRequestMessage
{
public:
/**
* An array of size NUM_SUPPORTED_PROTOCOL_VERSIONS listing versions of the
* BLE transport protocol that this node supports. Each protocol version is
* specified as a 4-bit unsigned integer. A zero-value represents unused
* array elements. Counting up from the zero-index, the first zero-value
* specifies the end of the list of supported protocol versions.
*/
uint8_t mSupportedProtocolVersions[(NUM_SUPPORTED_PROTOCOL_VERSIONS / 2) + (NUM_SUPPORTED_PROTOCOL_VERSIONS % 2)];
/**
* The MTU that has been negotiated for this BLE connection. Specified in
* the BleTransportCapabilitiesRequestMessage because the remote node may
* be unable to glean this info from its own BLE hardware/software stack,
* such as on older Android platforms.
*
* A value of 0 means that the central could not determine the negotiated
* BLE connection MTU.
*/
uint16_t mMtu;
/**
* The initial and maximum receive window size offered by the central,
* defined in terms of GATT indication payloads.
*/
uint8_t mWindowSize;
/**
* Set supported version value at given index in
* SupportedProtocolVersions. uint8_t version argument is truncated to 4
* least-significant bits. Index shall be 0 through number of
* SupportedProtocolVersions elements - 1.
*/
void SetSupportedProtocolVersion(uint8_t index, uint8_t version);
/// Must be able to reserve 20 byte data length in msgBuf.
BLE_ERROR Encode(PacketBuffer * msgBuf) const;
static BLE_ERROR Decode(const PacketBuffer & msgBuf, BleTransportCapabilitiesRequestMessage & msg);
};
class BleTransportCapabilitiesResponseMessage
{
public:
/**
* The lower 4 bits specify the BLE transport protocol version that the BLE
* peripheral has selected for this connection.
*
* A value of kBleTransportProtocolVersion_None means that no supported
* protocol version was found in the central's capabilities request. The
* central should unsubscribe after such a response has been sent to free
* up the peripheral for connections from devices with supported protocol
* versions.
*/
uint8_t mSelectedProtocolVersion;
/**
* BLE transport fragment size selected by peripheral in response to MTU
* value in BleTransportCapabilitiesRequestMessage and its local
* observation of the BLE connection MTU.
*/
uint16_t mFragmentSize;
/**
* The initial and maximum receive window size offered by the peripheral,
* defined in terms of GATT write payloads.
*/
uint8_t mWindowSize;
/// Must be able to reserve 20 byte data length in msgBuf.
BLE_ERROR Encode(PacketBuffer * msgBuf) const;
static BLE_ERROR Decode(const PacketBuffer & msgBuf, BleTransportCapabilitiesResponseMessage & msg);
};
/**
* @class BleLayer
*
* @brief
* This class provides an interface for a single thread to drive data
* either up the stack via the BleLayer platform interface functions,
* or down the stack via a chipConnection object associated with a
* BLEEndPoint.
*
* There are two ways to associate a chipConnection (defined by the
* chipMessageLayer) with a BLE connection:
*
* First, the application can passively receive an incoming BLE connection
* and hand the platform-specific BLE_CONNECTION_OBJECT that this receipt
* generates to BleLayer via the corresponding platform interface function.
* This causes BleLayer to wrap the BLE_CONNECTION_OBJECT in a BLEEndPoint,
* and notify chipMessageLayer that a new BLE conneciotn has been received.
* The message layer then wraps the new BLEEndPoint object in a
* chipConnection, and hands this object to the application via the message
* layer's OnConnectionReceived callback.
*
* Second, the application can actively form an outgoing BLE connection, e.g.,
* by connecting to a BLE peripheral. It then creates a new chipConnection
* via the chipMessageLayer, assigns an authentication type to this
* connection, and binds it to the BLE_CONNECTION_OBJECT for the new BLE
* connection via chipConnection::ConnectBle. This function then
* establishes the secure session type specified by the chipConnection's
* authentication type member variable.
*
*/
class DLL_EXPORT BleLayer
{
friend class BLEEndPoint;
#if CHIP_ENABLE_WOBLE_TEST
friend class WoBleTest;
#endif
public:
// Public data members:
enum
{
kState_NotInitialized = 0,
kState_Initialized = 1
} mState; ///< [READ-ONLY] Current state
void * mAppState;
typedef void (*BleConnectionReceivedFunct)(BLEEndPoint * newEndPoint);
BleConnectionReceivedFunct OnchipBleConnectReceived;
public:
// Public functions:
BleLayer(void);
BLE_ERROR Init(BlePlatformDelegate * platformDelegate, BleApplicationDelegate * appDelegate,
chip::System::Layer * systemLayer);
#if BLE_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
BLE_ERROR Init(BlePlatformDelegate * platformDelegate, BleApplicationDelegate * appDelegate, Inet::InetLayer * inetLayer);
#endif // BLE_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
BLE_ERROR Shutdown(void);
BLE_ERROR NewBleEndPoint(BLEEndPoint ** retEndPoint, BLE_CONNECTION_OBJECT connObj, BleRole role, bool autoClose);
chip::System::Error ScheduleWork(chip::System::Layer::TimerCompleteFunct aComplete, void* aAppState)
{
return mSystemLayer->ScheduleWork(aComplete, aAppState);
}
/**< Platform interface functions:
* Calling conventions:
* chip takes ownership of PacketBuffers received through these functions,
* and will free them or pass ownership up the stack.
*
* Beyond each call, no guarantees are provided as to the lifetime of UUID arguments.
*
* A 'true' return value means the chip stack successfully handled the
* corresponding message or state indication. 'false' means the chip stack either
* failed or chose not to handle this. In case of 'false,' the chip stack will not
* have freed or taken ownership of any PacketBuffer arguments. This contract allows the
* platform to pass BLE events to chip without needing to know which characteristics
* chip cares about.
* Platform must call this function when a GATT subscription has been established to any chip service
* charateristic.
*
* If this function returns true, chip has accepted the BLE connection and wrapped it
* in a chipConnection object. If chip accepts a BLE connection, the platform MUST
* notify chip if the subscription is canceled or the underlying BLE connection is
* closed, or the associated chipConnection will never be closed or freed. */
bool HandleSubscribeReceived(BLE_CONNECTION_OBJECT connObj, const chipBleUUID * svcId, const chipBleUUID * charId);
/// Call when a GATT subscribe request succeeds.
bool HandleSubscribeComplete(BLE_CONNECTION_OBJECT connObj, const chipBleUUID * svcId, const chipBleUUID * charId);
/**< Platform must call this function when a GATT unsubscribe is requested on any chip
* service charateristic, that is, when an existing GATT subscription on a chip service
* characteristic is canceled. */
bool HandleUnsubscribeReceived(BLE_CONNECTION_OBJECT connObj, const chipBleUUID * svcId, const chipBleUUID * charId);
/// Call when a GATT unsubscribe request succeeds.
bool HandleUnsubscribeComplete(BLE_CONNECTION_OBJECT connObj, const chipBleUUID * svcId, const chipBleUUID * charId);
/// Call when a GATT write request is received.
bool HandleWriteReceived(BLE_CONNECTION_OBJECT connObj, const chipBleUUID * svcId, const chipBleUUID * charId,
PacketBuffer * pBuf);
/// Call when a GATT indication is received.
bool HandleIndicationReceived(BLE_CONNECTION_OBJECT connObj, const chipBleUUID * svcId, const chipBleUUID * charId,
PacketBuffer * pBuf);
/// Call when an outstanding GATT write request receives a positive receipt confirmation.
bool HandleWriteConfirmation(BLE_CONNECTION_OBJECT connObj, const chipBleUUID * svcId, const chipBleUUID * charId);
/// Call when an oustanding GATT indication receives a positive receipt confirmation.
bool HandleIndicationConfirmation(BLE_CONNECTION_OBJECT connObj, const chipBleUUID * svcId, const chipBleUUID * charId);
/// Call when a GATT read request is received.
bool HandleReadReceived(BLE_CONNECTION_OBJECT connObj, BLE_READ_REQUEST_CONTEXT requestContext, const chipBleUUID * svcId,
const chipBleUUID * charId);
/**< Platform must call this function when any previous operation undertaken by the BleLayer via BleAdapter
* fails, such as a characteristic write request or subscribe attempt, or when a BLE connection is closed.
*
* In most cases, this will prompt chip to close the associated chipConnection and notify that platform that
* it has abandoned the underlying BLE connection.
*
* NOTE: if the application explicitly closes a BLE connection with an associated chipConnection such that
* the BLE connection close will not generate an upcall to chip, HandleConnectionError must be called with
* err = BLE_ERROR_APP_CLOSED_CONNECTION to prevent the leak of this chipConnection and its end point object. */
void HandleConnectionError(BLE_CONNECTION_OBJECT connObj, BLE_ERROR err);
#if CHIP_ENABLE_WOBLE_TEST
BLEEndPoint * mTestBleEndPoint;
#endif
private:
// Private data members:
// UUID of chip service characteristic used for central writes.
static const chipBleUUID CHIP_BLE_CHAR_1_ID;
// UUID of chip service characteristic used for peripheral indications.
static const chipBleUUID CHIP_BLE_CHAR_2_ID;
BlePlatformDelegate * mPlatformDelegate;
BleApplicationDelegate * mApplicationDelegate;
chip::System::Layer * mSystemLayer;
private:
// Private functions:
void HandleDataReceived(BLE_CONNECTION_OBJECT connObj, PacketBuffer * pBuf);
void HandleAckReceived(BLE_CONNECTION_OBJECT connObj);
void DriveSending(void);
BLE_ERROR HandleBleTransportConnectionInitiated(BLE_CONNECTION_OBJECT connObj, PacketBuffer * pBuf);
static BleTransportProtocolVersion GetHighestSupportedProtocolVersion(const BleTransportCapabilitiesRequestMessage & reqMsg);
};
#if BLE_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
inline BLE_ERROR BleLayer::Init(BlePlatformDelegate * aPlatformDelegate, BleApplicationDelegate * aAppDelegate,
Inet::InetLayer * aInetLayer)
{
return Init(aPlatformDelegate, aAppDelegate, aInetLayer->SystemLayer());
}
#endif // BLE_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
} /* namespace Ble */
} /* namespace chip */
#include "BLEEndPoint.h"
#endif /* BLELAYER_H_ */