blob: 42f2181d0dd2ad467b90207e58bae27a4e82d791 [file] [log] [blame]
/*
*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2020 Texas Instruments Incorporated
*
* 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
* Provides an implementation of the BLEManager object for the Texas
* Instruments cc13xx_cc26xx platform.
*/
#pragma once
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#include "FreeRTOS.h"
#include <queue.h>
#include <task.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <icall.h>
#include <icall_ble_api.h>
#include "hal_types.h"
#include "ti_ble_config.h"
#include "ti_drivers_config.h"
#ifdef __cplusplus
}
#endif
#include "chipOBleProfile.h"
namespace chip {
namespace DeviceLayer {
namespace Internal {
using namespace chip::Ble;
// Internal Events for RTOS application
#define ICALL_EVT ICALL_MSG_EVENT_ID // Event_Id_31
#define QUEUE_EVT UTIL_QUEUE_EVENT_ID // Event_Id_30
// Application events
#define BLEManagerIMPL_STATE_UPDATE_EVT (0)
// 500ms interval
#define BLEMANAGERIMPL_ADV_INT_SLOW (800)
// 100ms interval (Default)
#define BLEMANAGERIMPL_ADV_INT_FAST (160)
#define CHIPOBLE_ADV_SIZE_NO_DEVICE_ID_INFO (4)
#define CHIPOBLE_SCANRES_SIZE_NO_NAME (6)
#define CHIPOBLE_ADV_DATA_MAX_SIZE (GAP_DEVICE_NAME_LEN + CHIPOBLE_SCANRES_SIZE_NO_NAME)
#define CHIPOBLE_DEVICE_DESC_LENGTH (4)
// How often to read current current RPA (in ms)
#define READ_RPA_EVT_PERIOD 3000
// 15 Minute Advertisement CHIP Timeout period
#define ADV_TIMEOUT (900000)
#define STATE_CHANGE_EVT 0
#define CHAR_CHANGE_EVT 1
#define CHIPOBLE_CHAR_CHANGE_EVT 2
#define BLEManagerIMPL_CHIPOBLE_TX_IND_EVT 3
#define ADV_EVT 4
#define PAIR_STATE_EVT 5
#define PASSCODE_EVT 6
#define READ_RPA_EVT 7
#define SEND_PARAM_UPDATE_EVT 8
#define BLEManagerIMPL_CHIPOBLE_CLOSE_CONN_EVT 9
#define CONN_EVT 10
// For storing the active connections
#define RSSI_TRACK_CHNLS 1 // Max possible channels can be GAP_BONDINGS_MAX
#define MAX_RSSI_STORE_DEPTH 5
#define INVALID_HANDLE 0xFFFF
#define RSSI_2M_THRSHLD -30
#define RSSI_1M_THRSHLD -40
#define RSSI_S2_THRSHLD -50
#define RSSI_S8_THRSHLD -60
#define PHY_NONE LL_PHY_NONE // No PHY set
#define AUTO_PHY_UPDATE 0xFF
// Set initial values to maximum, RX is set to max. by default(251 octets, 2120us)
// Some brand smartphone is essentially needing 251/2120, so we set them here.
#define BLEMANAGER_SUGGESTED_PDU_SIZE 251 // default is 27 octets(TX)
#define BLEMANAGER_SUGGESTED_TX_TIME 2120 // default is 328us(TX)
typedef struct
{
uint8_t len; // data length
void * pData; // pointer to message
} CHIPoBLEIndEvt_t;
typedef struct
{
uint8_t paramId; // Parameter written
uint16_t len; // data length
uint16_t connHandle; // Active connection which received the write
} CHIPoBLEProfChgEvt_t;
// App event passed from stack modules. This type is defined by the application
// since it can queue events to itself however it wants.
typedef struct
{
uint8_t event; // event type
void * pData; // pointer to message
} QueuedEvt_t;
// Container to store advertising event data when passing from advertising
// callback to app event. See the respective event in GapAdvScan_Event_IDs
// in gap_advertiser.h for the type that pBuf should be cast to.
typedef struct
{
uint32_t event;
void * pBuf;
} GapAdvEventData_t;
// Container to store information from clock expiration using a flexible array
// since data is not always needed
typedef struct
{
uint8_t event;
uint8_t data[];
} ClockEventData_t;
// List element for parameter update and PHY command status lists
typedef struct
{
List_Elem elem;
uint16_t connHandle;
} ConnHandleEntry_t;
// Connected device information
typedef struct
{
uint16_t connHandle; // Connection Handle
ClockP_Struct * pUpdateClock; // pointer to clock struct
int8_t rssiArr[MAX_RSSI_STORE_DEPTH];
uint8_t rssiCntr;
int8_t rssiAvg;
bool phyCngRq; // Set to true if PHY change request is in progress
uint8_t currPhy;
uint8_t rqPhy;
uint8_t phyRqFailCnt; // PHY change request count
bool isAutoPHYEnable; // Flag to indicate auto phy change
uint16_t mtu;
ClockEventData_t * pParamUpdateEventData;
} ConnRec_t;
// Container to store passcode data when passing from gapbondmgr callback
// to app event. See the pfnPairStateCB_t documentation from the gapbondmgr.h
// header file for more information on each parameter.
typedef struct
{
uint8_t state;
uint16_t connHandle;
uint8_t status;
} PairStateData_t;
// Container to store passcode data when passing from gapbondmgr callback
// to app event. See the pfnPasscodeCB_t documentation from the gapbondmgr.h
// header file for more information on each parameter.
typedef struct
{
uint8_t deviceAddr[B_ADDR_LEN];
uint16_t connHandle;
uint8_t uiInputs;
uint8_t uiOutputs;
uint32_t numComparison;
} PasscodeData_t;
/**
* Concrete implementation of the BLEManager singleton object for cc13x2_cc26x2.
*/
class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePlatformDelegate, private BleApplicationDelegate
{
// Allow the BLEManager interface class to delegate method calls to
// the implementation methods provided by this class.
friend BLEManager;
public:
// ===== Platform-specific members that may be accessed directly by the application.
private:
// ===== Members that implement the BLEManager internal interface.
CHIP_ERROR _Init(void);
void _Shutdown() {}
CHIPoBLEServiceMode _GetCHIPoBLEServiceMode(void);
CHIP_ERROR _SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val);
bool _IsAdvertisingEnabled(void);
CHIP_ERROR _SetAdvertisingEnabled(bool val);
bool _IsAdvertising(void);
CHIP_ERROR _SetAdvertisingMode(BLEAdvertisingMode mode);
CHIP_ERROR _GetDeviceName(char * buf, size_t bufSize);
CHIP_ERROR _SetDeviceName(const char * deviceName);
uint16_t _NumConnections(void);
void _OnPlatformEvent(const ChipDeviceEvent * event);
BleLayer * _GetBleLayer(void);
// ===== Members that implement virtual methods on BlePlatformDelegate.
bool SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
const Ble::ChipBleUUID * charId) override;
bool UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
const Ble::ChipBleUUID * charId) override;
bool CloseConnection(BLE_CONNECTION_OBJECT conId) override;
uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const override;
bool SendIndication(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
System::PacketBufferHandle pBuf) override;
bool SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
System::PacketBufferHandle pBuf) override;
bool SendReadRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
System::PacketBufferHandle pBuf) override;
bool SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, const Ble::ChipBleUUID * svcId,
const Ble::ChipBleUUID * charId) override;
// ===== Members that implement virtual methods on BleApplicationDelegate.
void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) override;
const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42,
0x9F, 0x9D, 0x11 } };
const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42,
0x9F, 0x9D, 0x12 } };
friend BLEManager & BLEMgr(void);
friend BLEManagerImpl & BLEMgrImpl(void);
static BLEManagerImpl sInstance;
/* BLE stack task handle */
static TaskHandle_t sBleTaskHndl;
// Entity ID globally used to check for source and/or destination of messages
static ICall_EntityID sSelfEntity;
// Event globally used to post local events and pend on system and
// local events.
static ICall_SyncHandle sSyncEvent;
static QueueHandle_t sEventHandlerMsgQueueID;
static chipOBleProfileCBs_t CHIPoBLEProfile_CBs;
static gapBondCBs_t BLEMgr_BondMgrCBs;
enum class Flags : uint16_t
{
kAdvertisingEnabled = 0x0001, /* App enabled CHIPoBLE advertising */
kFastAdvertisingEnabled = 0x0002, /* App enabled Fash CHIPoBLE advertising */
kAdvertising = 0x0004, /* TI BLE stack actively advertising */
kBLEStackInitialized = 0x0008, /* TI BLE Stack GAP/GATT Intilization complete */
kBLEStackAdvInitialized = 0x0010, /* TI BLE Stack Advertisement Intilization complete */
kBLEStackGATTNameUpdate = 0x0020, /* Trigger TI BLE Stack name update, must be performed prior to adv start */
kBLEStackGATTNameSet = 0x0040, /* Device name has been set externally*/
kAdvertisingRefreshNeeded = 0x0080, /* Advertising settings changed and it should be restarted */
};
BitFlags<Flags> mFlags;
CHIPoBLEServiceMode mServiceMode;
char mDeviceName[GAP_DEVICE_NAME_LEN];
ConnRec_t connList[MAX_NUM_BLE_CONNS];
// List to store connection handles for queued param updates
List_List paramUpdateList;
// Advertising handles
uint8_t advHandleLegacy;
// Address mode
GAP_Addr_Modes_t addrMode = DEFAULT_ADDRESS_MODE;
// Current Random Private Address
uint8_t rpa[B_ADDR_LEN] = { 0 };
uint8_t mAdvDatachipOBle[CHIPOBLE_ADV_DATA_MAX_SIZE];
uint8_t mScanResDatachipOBle[CHIPOBLE_ADV_DATA_MAX_SIZE];
ClockP_Struct clkRpaRead;
ClockP_Struct clkAdvTimeout;
// Memory to pass RPA read event ID to clock handler
ClockEventData_t argRpaRead = { .event = READ_RPA_EVT };
// ===== Private BLE Stack Helper functions.
void ConfigureAdvertisements(void);
void EventHandler_init(void);
void InitPHYRSSIArray(void);
CHIP_ERROR CreateEventHandler(void);
uint8_t ProcessStackEvent(ICall_Hdr * pMsg);
void ProcessEvtHdrMsg(QueuedEvt_t * pMsg);
void ProcessGapMessage(gapEventHdr_t * pMsg);
uint8_t ProcessGATTMsg(gattMsgEvent_t * pMsg);
void ProcessAdvEvent(GapAdvEventData_t * pEventData);
CHIP_ERROR ProcessParamUpdate(uint16_t connHandle);
status_t EnqueueEvtHdrMsg(uint8_t event, void * pData);
uint8_t AddBLEConn(uint16_t connHandle);
uint8_t RemoveBLEConn(uint16_t connHandle);
uint8_t GetBLEConnIndex(uint16_t connHandle) const;
uint8_t ClearBLEConnListEntry(uint16_t connHandle);
void ClearPendingBLEParamUpdate(uint16_t connHandle);
void UpdateBLERPA(void);
static void HandleIncomingBleConnection(Ble::BLEEndPoint * bleEP);
/* Static helper function */
static void EventHandler(void * arg);
static CHIP_ERROR DriveBLEState(void);
/* Declared static to acquire function ptr */
static void advCallback(uint32_t event, void * pBuf, uintptr_t arg);
static void ClockHandler(uintptr_t arg);
static void AdvTimeoutHandler(uintptr_t arg);
static void CHIPoBLEProfile_charValueChangeCB(uint8_t paramId, uint16_t len, uint16_t connHandle);
static void PasscodeCb(uint8_t * pDeviceAddr, uint16_t connHandle, uint8_t uiInputs, uint8_t uiOutputs, uint32_t numComparison);
static void PairStateCb(uint16_t connHandle, uint8_t state, uint8_t status);
static void AssertHandler(uint8 assertCause, uint8 assertSubcause);
};
/**
* Returns a reference to the public interface of the BLEManager singleton object.
*
* Internal components should use this to access features of the BLEManager object
* that are common to all platforms.
*/
inline BLEManager & BLEMgr(void)
{
return BLEManagerImpl::sInstance;
}
/**
* Returns the platform-specific implementation of the BLEManager singleton object.
*
* Internal components can use this to gain access to features of the BLEManager
* that are specific to the cc13x2_cc26x2 platforms.
*/
inline BLEManagerImpl & BLEMgrImpl(void)
{
return BLEManagerImpl::sInstance;
}
inline BleLayer * BLEManagerImpl::_GetBleLayer()
{
return this;
}
} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE