/* * * 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_26XX platform. */ #pragma once #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE #include "FreeRTOS.h" #include #include #ifdef __cplusplus extern "C" { #endif #include #include #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 CC13XX_26XX. */ 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() {} 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. CHIP_ERROR SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId) override; CHIP_ERROR UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId) override; CHIP_ERROR CloseConnection(BLE_CONNECTION_OBJECT conId) override; uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const override; CHIP_ERROR SendIndication(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, System::PacketBufferHandle pBuf) override; CHIP_ERROR SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, System::PacketBufferHandle pBuf) override; // ===== Members that implement virtual methods on BleApplicationDelegate. void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) override; 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 mFlags; CHIPoBLEServiceMode mServiceMode; char mDeviceName[GAP_DEVICE_NAME_LEN]; ConnRec_t connList[LL_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 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 FastAdvTimeoutHandler(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 CC13XX_26XX 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