| |
| /* |
| * |
| * Copyright (c) 2020-2022 Project CHIP Authors |
| * Copyright (c) 2019 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 |
| * Provides an implementation of the BLEManager object for cc13xx_cc26xx |
| * platform using the Texas Instruments SDK and the OpenThread stack. |
| */ |
| #include <string.h> |
| |
| /* this file behaves like a config.h, comes first */ |
| #include <platform/internal/CHIPDeviceLayerInternal.h> |
| |
| #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE |
| |
| #include <ble/Ble.h> |
| #include <platform/internal/BLEManager.h> |
| |
| #include "FreeRTOS.h" |
| #include <queue.h> |
| #include <task.h> |
| |
| /* Include DMM module */ |
| #include "chipOBleProfile.h" |
| #include "hal_types.h" |
| #include "ti_dmm_application_policy.h" |
| #include <bcomdef.h> |
| #include <devinfoservice.h> |
| #include <dmm/apps/common/freertos/util.h> |
| #include <dmm/dmm_policy.h> |
| #include <dmm/dmm_priority_ble_thread.h> |
| #include <dmm/dmm_scheduler.h> |
| #include <icall.h> |
| #include <icall_ble_api.h> |
| #include <util.h> |
| |
| extern "C" { |
| #include "ti_ble_config.h" |
| #include "ti_drivers_config.h" |
| #ifndef ICALL_FEATURE_SEPARATE_IMGINFO |
| #include <icall_addrs.h> |
| #endif /* ICALL_FEATURE_SEPARATE_IMGINFO */ |
| } |
| |
| // BLE Manager Debug Logs |
| extern "C" { |
| #ifdef BLEMGR_DBG_LOGGING |
| extern void cc13xx_26xxLog(const char * aFormat, ...); |
| #define BLEMGR_LOG(...) cc13xx_26xxLog(__VA_ARGS__); |
| #else |
| #define BLEMGR_LOG(...) |
| #endif |
| } |
| |
| #ifndef USE_DEFAULT_USER_CFG |
| #include "ble_user_config.h" |
| // BLE user defined configuration. Required to be globally accesible for BLE initialization |
| icall_userCfg_t user0Cfg = BLE_USER_CFG; |
| #endif // USE_DEFAULT_USER_CFG |
| |
| using namespace ::chip; |
| using namespace ::chip::Ble; |
| |
| namespace chip { |
| namespace DeviceLayer { |
| namespace Internal { |
| |
| /* Static class member initialization */ |
| BLEManagerImpl BLEManagerImpl::sInstance; |
| TaskHandle_t BLEManagerImpl::sBleTaskHndl; |
| ICall_EntityID BLEManagerImpl::sSelfEntity; |
| ICall_SyncHandle BLEManagerImpl::sSyncEvent; |
| QueueHandle_t BLEManagerImpl::sEventHandlerMsgQueueID; |
| |
| chipOBleProfileCBs_t BLEManagerImpl::CHIPoBLEProfile_CBs = { |
| // Provisioning GATT Characteristic value change callback |
| CHIPoBLEProfile_charValueChangeCB |
| }; |
| |
| // GAP Bond Manager Callbacks |
| gapBondCBs_t BLEManagerImpl::BLEMgr_BondMgrCBs = { |
| PasscodeCb, // Passcode callback |
| PairStateCb // Pairing/Bonding state Callback |
| }; |
| |
| // ===== Members that implement the BLEManager internal interface. |
| CHIP_ERROR BLEManagerImpl::_Init(void) |
| { |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| |
| BLEMGR_LOG("BLEMGR: BLE Initialization Start"); |
| // Initialize the CHIP BleLayer. |
| err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer()); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| /* Register BLE Stack assert handler */ |
| RegisterAssertCback(AssertHandler); |
| |
| mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART); |
| mFlags.Set(Flags::kFastAdvertisingEnabled, true); |
| |
| mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; |
| |
| err = CreateEventHandler(); |
| return err; |
| } |
| |
| bool BLEManagerImpl::_IsAdvertisingEnabled(void) |
| { |
| return mFlags.Has(Flags::kAdvertisingEnabled); |
| } |
| |
| /* Post event to app processing loop to begin CHIP advertising */ |
| CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) |
| { |
| mFlags.Set(Flags::kAdvertisingEnabled, val); |
| |
| /* Send event to process state change request */ |
| return DriveBLEState(); |
| } |
| |
| CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) |
| { |
| CHIP_ERROR ret = CHIP_NO_ERROR; |
| |
| switch (mode) |
| { |
| case BLEAdvertisingMode::kFastAdvertising: |
| mFlags.Set(Flags::kFastAdvertisingEnabled, true); |
| break; |
| case BLEAdvertisingMode::kSlowAdvertising: |
| mFlags.Set(Flags::kFastAdvertisingEnabled, false); |
| break; |
| default: |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| mFlags.Set(Flags::kAdvertisingRefreshNeeded); |
| ret = DriveBLEState(); |
| return ret; |
| } |
| |
| bool BLEManagerImpl::_IsAdvertising(void) |
| { |
| return mFlags.Has(Flags::kAdvertising); |
| } |
| |
| CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize) |
| { |
| CHIP_ERROR ret = CHIP_NO_ERROR; |
| |
| if (bufSize <= GAP_DEVICE_NAME_LEN) |
| { |
| Platform::CopyString(buf, bufSize, mDeviceName); |
| } |
| else |
| { |
| ret = CHIP_ERROR_BUFFER_TOO_SMALL; |
| } |
| |
| return ret; |
| } |
| |
| CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName) |
| { |
| CHIP_ERROR ret = CHIP_NO_ERROR; |
| |
| if (strlen(deviceName) <= GAP_DEVICE_NAME_LEN) |
| { |
| Platform::CopyString(mDeviceName, deviceName); |
| |
| mFlags.Set(Flags::kBLEStackGATTNameUpdate); |
| mFlags.Set(Flags::kAdvertisingRefreshNeeded); |
| ret = DriveBLEState(); |
| } |
| else |
| { |
| ret = CHIP_ERROR_BUFFER_TOO_SMALL; |
| } |
| |
| return ret; |
| } |
| |
| uint16_t BLEManagerImpl::_NumConnections(void) |
| { |
| uint8_t i, numConns = 0; |
| |
| // Try to find an available entry |
| for (i = 0; i < MAX_NUM_BLE_CONNS; i++) |
| { |
| if (connList[i].connHandle != LL_CONNHANDLE_INVALID) |
| { |
| numConns++; |
| } |
| } |
| |
| return numConns; |
| } |
| |
| void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) |
| { |
| switch (event->Type) |
| { |
| case DeviceEventType::kCHIPoBLESubscribe: { |
| ChipDeviceEvent connEstEvent; |
| |
| BLEMGR_LOG("BLEMGR: OnPlatformEvent, kCHIPoBLESubscribe"); |
| HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); |
| |
| connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished; |
| |
| PlatformMgr().PostEventOrDie(&connEstEvent); |
| } |
| break; |
| |
| case DeviceEventType::kCHIPoBLEUnsubscribe: { |
| BLEMGR_LOG("BLEMGR: OnPlatformEvent, kCHIPoBLEUnsubscribe"); |
| HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); |
| } |
| break; |
| |
| case DeviceEventType::kCHIPoBLEWriteReceived: { |
| BLEMGR_LOG("BLEMGR: OnPlatformEvent, kCHIPoBLEWriteReceived"); |
| HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX, |
| PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); |
| } |
| break; |
| |
| case DeviceEventType::kCHIPoBLEIndicateConfirm: |
| HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); |
| break; |
| |
| case DeviceEventType::kCHIPoBLEConnectionError: { |
| BLEMGR_LOG("BLEMGR: OnPlatformEvent, kCHIPoBLEConnectionError"); |
| HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason); |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| // ===== Members that implement virtual methods on BlePlatformDelegate. |
| bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) |
| { |
| void * pMsg = (void *) ICall_malloc(sizeof(void *)); |
| pMsg = (void *) conId; |
| |
| return (EnqueueEvtHdrMsg(BLEManagerIMPL_CHIPOBLE_CLOSE_CONN_EVT, (void *) pMsg) == true); |
| } |
| |
| uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const |
| { |
| uint8_t index; |
| uint16_t mtu = 0; |
| |
| index = GetBLEConnIndex(*((uint32_t *) conId)); |
| |
| if (index != MAX_NUM_BLE_CONNS) |
| { |
| mtu = sInstance.connList[index].mtu; |
| /* Prior to MTU update event, MTU is determined by the below formula */ |
| if (mtu == 0) |
| { |
| mtu = MAX_PDU_SIZE - 4; |
| } |
| } |
| |
| return mtu; |
| } |
| |
| // ===== Members that implement virtual methods on BleApplicationDelegate. |
| |
| void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) |
| { |
| // Unused |
| } |
| |
| bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, |
| PacketBufferHandle data) |
| { |
| BLEMGR_LOG("BLEMGR: BLE SendIndication "); |
| |
| // Allocate buffers to send to BLE app task |
| uint8_t dataLen = static_cast<uint8_t>(data->DataLength()); |
| CHIPoBLEIndEvt_t * pMsg; |
| uint8_t * pBuf; |
| |
| pMsg = (CHIPoBLEIndEvt_t *) ICall_malloc(sizeof(CHIPoBLEIndEvt_t)); |
| if (NULL == pMsg) |
| { |
| return false; |
| } |
| |
| pBuf = (uint8_t *) ICall_malloc(dataLen); |
| if (NULL == pBuf) |
| { |
| ICall_free((void *) pMsg); |
| return false; |
| } |
| |
| memset(pBuf, 0x00, dataLen); |
| memcpy(pBuf, data->Start(), dataLen); |
| |
| pMsg->pData = pBuf; |
| pMsg->len = dataLen; |
| |
| EnqueueEvtHdrMsg(BLEManagerIMPL_CHIPOBLE_TX_IND_EVT, (void *) pMsg); |
| |
| BLEMGR_LOG("BLEMGR: BLE SendIndication RETURN, Length: %d ", dataLen); |
| return true; |
| } |
| |
| bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, |
| const Ble::ChipBleUUID * charId) |
| { |
| /* Unsupported on TI peripheral device implementation */ |
| return false; |
| } |
| |
| bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, |
| const Ble::ChipBleUUID * charId) |
| { |
| /* Unsupported on TI peripheral device implementation */ |
| return false; |
| } |
| |
| bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, |
| PacketBufferHandle pBuf) |
| { |
| /* Unsupported on TI peripheral device implementation */ |
| BLEMGR_LOG("BLEMGR: BLE SendWriteRequest"); |
| return false; |
| } |
| |
| bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, |
| PacketBufferHandle pBuf) |
| { |
| /* Unsupported on TI peripheral device implementation */ |
| return false; |
| } |
| |
| bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, |
| const ChipBleUUID * svcId, const ChipBleUUID * charId) |
| { |
| /* Unsupported on TI peripheral device implementation */ |
| return false; |
| } |
| |
| // ===== Helper Members that implement the Low level BLE Stack behavior. |
| |
| /********************************************************************* |
| * @fn ConfigureAdvertisements |
| * |
| * @brief Initialize CHIPoBLE Advertisements. |
| */ |
| void BLEManagerImpl::ConfigureAdvertisements(void) |
| { |
| bStatus_t status = FAILURE; |
| uint16_t deviceDiscriminator; |
| uint8_t localDeviceNameLen; |
| uint8_t scanIndex = 0; |
| uint8_t advIndex = 0; |
| uint8_t scanResLength; |
| uint8_t advLength; |
| |
| GapAdv_params_t advParams = { .eventProps = GAP_ADV_PROP_CONNECTABLE | GAP_ADV_PROP_LEGACY | GAP_ADV_PROP_SCANNABLE, |
| .primIntMin = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN, |
| .primIntMax = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN, |
| .primChanMap = GAP_ADV_CHAN_ALL, |
| .peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID, |
| .peerAddr = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, |
| .filterPolicy = GAP_ADV_AL_POLICY_ANY_REQ, |
| .txPower = GAP_ADV_TX_POWER_NO_PREFERENCE, |
| .primPhy = GAP_ADV_PRIM_PHY_1_MBPS, |
| .secPhy = GAP_ADV_SEC_PHY_1_MBPS, |
| .sid = 0 }; |
| |
| BLEMGR_LOG("BLEMGR: ConfigureAdvertisements"); |
| |
| ChipBLEDeviceIdentificationInfo mDeviceIdInfo; |
| ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo); |
| |
| memset(sInstance.mScanResDatachipOBle, 0, CHIPOBLE_ADV_DATA_MAX_SIZE); |
| memset(sInstance.mAdvDatachipOBle, 0, CHIPOBLE_ADV_DATA_MAX_SIZE); |
| |
| // Verify device name was not already set |
| if (!sInstance.mFlags.Has(Flags::kBLEStackGATTNameSet)) |
| { |
| /* Default device name is CHIP-<DISCRIMINATOR> */ |
| deviceDiscriminator = mDeviceIdInfo.GetDeviceDiscriminator(); |
| |
| localDeviceNameLen = strlen(CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX) + CHIPOBLE_DEVICE_DESC_LENGTH; |
| |
| memset(sInstance.mDeviceName, 0, GAP_DEVICE_NAME_LEN); |
| snprintf(sInstance.mDeviceName, GAP_DEVICE_NAME_LEN, "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, |
| deviceDiscriminator); |
| |
| // Set the Device Name characteristic in the GAP GATT Service |
| // For more information, see the section in the User's Guide: |
| // http://software-dl.ti.com/lprf/ble5stack-latest/ |
| GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, sInstance.mDeviceName); |
| |
| BLEMGR_LOG("BLEMGR: AdvInit New device name set: %s", sInstance.mDeviceName); |
| } |
| else |
| { |
| sInstance.mFlags.Clear(Flags::kBLEStackGATTNameUpdate); |
| |
| localDeviceNameLen = strlen(sInstance.mDeviceName); |
| } |
| |
| scanResLength = localDeviceNameLen + CHIPOBLE_SCANRES_SIZE_NO_NAME; |
| |
| /* Verify scan response data length */ |
| assert(scanResLength < CHIPOBLE_ADV_DATA_MAX_SIZE); |
| |
| sInstance.mScanResDatachipOBle[scanIndex++] = localDeviceNameLen + 1; |
| sInstance.mScanResDatachipOBle[scanIndex++] = GAP_ADTYPE_LOCAL_NAME_COMPLETE; |
| memcpy(&sInstance.mScanResDatachipOBle[scanIndex], sInstance.mDeviceName, localDeviceNameLen); |
| scanIndex += localDeviceNameLen; |
| sInstance.mScanResDatachipOBle[scanIndex++] = 0x03; |
| sInstance.mScanResDatachipOBle[scanIndex++] = GAP_ADTYPE_16BIT_COMPLETE; |
| sInstance.mScanResDatachipOBle[scanIndex++] = static_cast<uint8_t>(LO_UINT16(CHIPOBLE_SERV_UUID)); |
| sInstance.mScanResDatachipOBle[scanIndex++] = static_cast<uint8_t>(HI_UINT16(CHIPOBLE_SERV_UUID)); |
| |
| for (uint8_t temp = 0; temp < scanIndex; temp++) |
| { |
| BLEMGR_LOG("BLEMGR: AdvInit Scan Response Data: %x", sInstance.mScanResDatachipOBle[temp]); |
| } |
| |
| advLength = sizeof(static_cast<uint16_t>(CHIPOBLE_SERV_UUID)) + static_cast<uint8_t>(sizeof(mDeviceIdInfo)) + 1; |
| |
| /* Verify advertising data length */ |
| assert((CHIPOBLE_ADV_SIZE_NO_DEVICE_ID_INFO + advLength) < CHIPOBLE_ADV_DATA_MAX_SIZE); |
| |
| BLEMGR_LOG("BLEMGR: AdvInit: MDeviceIDInfo Size: %d", sizeof(mDeviceIdInfo)); |
| BLEMGR_LOG("BLEMGR: AdvInit: advlength: %d", advLength); |
| BLEMGR_LOG("BLEMGR: AdvInit:Desc : %d", mDeviceIdInfo.GetDeviceDiscriminator()); |
| |
| sInstance.mAdvDatachipOBle[advIndex++] = 0x02; |
| sInstance.mAdvDatachipOBle[advIndex++] = GAP_ADTYPE_FLAGS; |
| sInstance.mAdvDatachipOBle[advIndex++] = GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED | GAP_ADTYPE_FLAGS_GENERAL; |
| sInstance.mAdvDatachipOBle[advIndex++] = advLength; |
| sInstance.mAdvDatachipOBle[advIndex++] = GAP_ADTYPE_SERVICE_DATA; |
| sInstance.mAdvDatachipOBle[advIndex++] = static_cast<uint8_t>(LO_UINT16(CHIPOBLE_SERV_UUID)); |
| sInstance.mAdvDatachipOBle[advIndex++] = static_cast<uint8_t>(HI_UINT16(CHIPOBLE_SERV_UUID)); |
| memcpy(&sInstance.mAdvDatachipOBle[advIndex], (void *) &mDeviceIdInfo, static_cast<uint8_t>(sizeof(mDeviceIdInfo))); |
| |
| // Setup and start Advertising |
| // For more information, see the GAP section in the User's Guide: |
| // http://software-dl.ti.com/lprf/ble5stack-latest/ |
| |
| if (!sInstance.mFlags.Has(Flags::kBLEStackAdvInitialized)) |
| { |
| // Create Advertisement set #1 and assign handle |
| status = (bStatus_t) GapAdv_create(&advCallback, &advParams, &sInstance.advHandleLegacy); |
| assert(status == SUCCESS); |
| |
| // Set event mask for set #1 |
| status = (bStatus_t) GapAdv_setEventMask(sInstance.advHandleLegacy, |
| GAP_ADV_EVT_MASK_START_AFTER_ENABLE | GAP_ADV_EVT_MASK_END_AFTER_DISABLE | |
| GAP_ADV_EVT_MASK_SET_TERMINATED); |
| |
| Util_constructClock(&sInstance.clkAdvTimeout, AdvTimeoutHandler, ADV_TIMEOUT, 0, false, (uintptr_t) NULL); |
| } |
| if (sInstance.mFlags.Has(Flags::kBLEStackAdvInitialized)) |
| |
| { |
| |
| // Don't free anything since we're going to use the same buffer to re-load |
| GapAdv_prepareLoadByHandle(sInstance.advHandleLegacy, GAP_ADV_FREE_OPTION_DONT_FREE); |
| } |
| // Load advertising data for set #1 that is statically allocated by the app |
| status = (bStatus_t) GapAdv_loadByHandle(sInstance.advHandleLegacy, GAP_ADV_DATA_TYPE_ADV, |
| CHIPOBLE_ADV_SIZE_NO_DEVICE_ID_INFO + advLength, sInstance.mAdvDatachipOBle); |
| assert(status == SUCCESS); |
| |
| if (sInstance.mFlags.Has(Flags::kBLEStackAdvInitialized)) |
| { |
| |
| // Don't free anything since we're going to use the same buffer to re-load |
| GapAdv_prepareLoadByHandle(sInstance.advHandleLegacy, GAP_ADV_FREE_OPTION_DONT_FREE); |
| } |
| |
| // Load scan response data for set #1 that is statically allocated by the app |
| status = (bStatus_t) GapAdv_loadByHandle(sInstance.advHandleLegacy, GAP_ADV_DATA_TYPE_SCAN_RSP, scanResLength, |
| sInstance.mScanResDatachipOBle); |
| assert(status == SUCCESS); |
| } |
| |
| /********************************************************************* |
| * @fn EventHandler_init |
| * |
| * @brief Called during initialization and contains application |
| * specific initialization (ie. hardware initialization/setup, |
| * table initialization, power up notification, etc), and |
| * profile initialization/setup. |
| */ |
| void BLEManagerImpl::EventHandler_init(void) |
| { |
| BLEMGR_LOG("BLEMGR: EventHandler_init"); |
| |
| /* Update User Configuration of the stack */ |
| user0Cfg.appServiceInfo->timerTickPeriod = ICall_getTickPeriod(); |
| user0Cfg.appServiceInfo->timerMaxMillisecond = ICall_getMaxMSecs(); |
| |
| /* Initialize ICall module */ |
| ICall_init(); |
| |
| /* Start tasks of external images */ |
| ICall_createRemoteTasks(); |
| BLEManagerImpl::sBleTaskHndl = (TaskHandle_t) (*((TaskHandle_t *) ICall_getRemoteTaskHandle(0))); |
| DMMSch_registerClient((TaskHandle_t) BLEManagerImpl::sBleTaskHndl, DMMPolicy_StackRole_BlePeripheral); |
| /* set the stacks in default states */ |
| DMMPolicy_updateStackState(DMMPolicy_StackRole_BlePeripheral, DMMPOLICY_BLE_IDLE); |
| |
| vTaskPrioritySet(xTaskGetCurrentTaskHandle(), 3); |
| |
| // ****************************************************************** |
| // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp |
| // ****************************************************************** |
| // Register the current thread as an ICall dispatcher application |
| // so that the application can send and receive messages. |
| ICall_registerApp(&BLEManagerImpl::sSelfEntity, &BLEManagerImpl::sSyncEvent); |
| |
| #ifdef USE_RCOSC |
| RCOSC_enableCalibration(); |
| #endif // USE_RCOSC |
| |
| // Create an RTOS queue for message from profile to be sent to app. |
| Util_constructQueue(&BLEManagerImpl::sEventHandlerMsgQueueID); |
| |
| // Configure GAP |
| { |
| uint16_t paramUpdateDecision = DEFAULT_PARAM_UPDATE_REQ_DECISION; |
| |
| // Pass all parameter update requests to the app for it to decide |
| GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, paramUpdateDecision); |
| } |
| |
| // Setup the GAP Bond Manager. For more information see the GAP Bond Manager |
| // section in the User's Guide: |
| // http://software-dl.ti.com/lprf/ble5stack-latest/ |
| setBondManagerParameters(); |
| |
| // Initialize GATT attributes |
| GGS_AddService(GATT_ALL_SERVICES); // GAP GATT Service |
| GATTServApp_AddService(GATT_ALL_SERVICES); // GATT Service |
| DevInfo_AddService(); // Device Information Service |
| |
| CHIPoBLEProfile_AddService(GATT_ALL_SERVICES); |
| |
| // Start Bond Manager and register callback |
| VOID GAPBondMgr_Register(BLEMgr_BondMgrCBs); |
| |
| // Register with GAP for HCI/Host messages. This is needed to receive HCI |
| // events. For more information, see the HCI section in the User's Guide: |
| // http://software-dl.ti.com/lprf/ble5stack-latest/ |
| GAP_RegisterForMsgs(BLEManagerImpl::sSelfEntity); |
| |
| // Register for GATT local events and ATT Responses pending for transmission |
| GATT_RegisterForMsgs(BLEManagerImpl::sSelfEntity); |
| |
| CHIPoBLEProfile_RegisterAppCBs(&CHIPoBLEProfile_CBs); |
| // Set default values for Data Length Extension |
| // Extended Data Length Feature is already enabled by default |
| { |
| // This API is documented in hci.h |
| // See the LE Data Length Extension section in the BLE5-Stack User's Guide for information on using this command: |
| // http://software-dl.ti.com/lprf/ble5stack-latest/ |
| HCI_LE_WriteSuggestedDefaultDataLenCmd(BLEMANAGER_SUGGESTED_PDU_SIZE, BLEMANAGER_SUGGESTED_TX_TIME); |
| } |
| |
| // Initialize GATT Client |
| GATT_InitClient(""); |
| |
| // Initialize Connection List |
| ClearBLEConnListEntry(LL_CONNHANDLE_ALL); |
| |
| // Initialize GAP layer for Peripheral role and register to receive GAP events |
| GAP_DeviceInit(GAP_PROFILE_PERIPHERAL, BLEManagerImpl::sSelfEntity, sInstance.addrMode, &pRandomAddress); |
| |
| // Initialize array to store connection handle and RSSI values |
| InitPHYRSSIArray(); |
| BLEMGR_LOG("BLEMGR: EventHandler_init Done"); |
| } |
| |
| /********************************************************************* |
| * @fn InitPHYRSSIArray |
| * |
| * @brief Initializes the array of structure/s to store data related |
| * RSSI based auto PHy change |
| * |
| * @param connHandle - the connection handle |
| * |
| * @param addr - pointer to device address |
| * |
| * @return index of connection handle |
| */ |
| void BLEManagerImpl::InitPHYRSSIArray(void) |
| { |
| BLEMGR_LOG("BLEMGR: InitPHYRSSIArray"); |
| |
| // Initialize array to store connection handle and RSSI values |
| memset(sInstance.connList, 0, sizeof(sInstance.connList)); |
| |
| for (uint8_t index = 0; index < MAX_NUM_BLE_CONNS; index++) |
| { |
| sInstance.connList[index].connHandle = INVALID_HANDLE; |
| } |
| } |
| |
| /********************************************************************* |
| * @fn CreateEventHandler |
| * |
| * @brief Create FreeRTOS Task for BLE Event handling |
| * |
| */ |
| CHIP_ERROR BLEManagerImpl::CreateEventHandler(void) |
| { |
| BLEMGR_LOG("BLEMGR: CreateEventHandler"); |
| |
| BaseType_t xReturned; |
| |
| /* Create the task, storing the handle. */ |
| xReturned = xTaskCreate(EventHandler, /* Function that implements the task. */ |
| "ble_hndlr", /* Text name for the task. */ |
| BLEMANAGER_EVENT_HANDLER_STACK_SIZE, /* Stack size in words, not bytes. */ |
| this, /* Parameter passed into the task. */ |
| ICALL_TASK_PRIORITIES, /* Keep priority the same as ICALL until init is complete */ |
| NULL); /* Used to pass out the created task's handle. */ |
| |
| if (xReturned == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY) |
| { |
| return CHIP_ERROR_NO_MEMORY; |
| } |
| else |
| { |
| return CHIP_NO_ERROR; |
| } |
| } |
| |
| /********************************************************************* |
| * @fn RemoteDisplay_processStackMsg |
| * |
| * @brief Process an incoming stack message. |
| * |
| * @param pMsg - message to process |
| * |
| * @return TRUE if safe to deallocate incoming message, FALSE otherwise. |
| */ |
| uint8_t BLEManagerImpl::ProcessStackEvent(ICall_Hdr * pMsg) |
| { |
| // Always dealloc pMsg unless set otherwise |
| uint8_t safeToDealloc = TRUE; |
| |
| switch (pMsg->event) |
| { |
| case GAP_MSG_EVENT: |
| ProcessGapMessage((gapEventHdr_t *) pMsg); |
| break; |
| |
| case GATT_MSG_EVENT: |
| // Process GATT message |
| safeToDealloc = ProcessGATTMsg((gattMsgEvent_t *) pMsg); |
| break; |
| case HCI_GAP_EVENT_EVENT: { |
| // Process HCI message |
| switch (pMsg->status) |
| { |
| case HCI_COMMAND_COMPLETE_EVENT_CODE: |
| // Process HCI Command Complete Events here |
| { |
| // RemoteDisplay_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg); |
| break; |
| } |
| case HCI_BLE_HARDWARE_ERROR_EVENT_CODE: |
| assert(false); |
| break; |
| // HCI Commands Events |
| case HCI_COMMAND_STATUS_EVENT_CODE: { |
| hciEvt_CommandStatus_t * pMyMsg = (hciEvt_CommandStatus_t *) pMsg; |
| switch (pMyMsg->cmdOpcode) |
| { |
| case HCI_LE_SET_PHY: { |
| if (pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE) |
| { |
| /* PHY Change failure, peer does not support this */ |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| break; |
| } |
| |
| case HCI_LE_EVENT_CODE: { |
| hciEvt_BLEPhyUpdateComplete_t * pPUC = (hciEvt_BLEPhyUpdateComplete_t *) pMsg; |
| |
| // A Phy Update Has Completed or Failed |
| if (pPUC->BLEEventCode == HCI_BLE_PHY_UPDATE_COMPLETE_EVENT) |
| { |
| if (pPUC->status != SUCCESS) |
| { |
| /* PHY Change failure */ |
| } |
| else |
| { |
| /* PHY Update successful */ |
| } |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| |
| break; |
| } |
| |
| default: |
| // do nothing |
| break; |
| } |
| |
| return safeToDealloc; |
| } |
| |
| /********************************************************************* |
| * @fn ProcessEvtHdrMsg |
| * |
| * @brief Process an incoming callback from a profile. |
| * |
| * @param pMsg - message to process |
| * |
| * @return None. |
| */ |
| void BLEManagerImpl::ProcessEvtHdrMsg(QueuedEvt_t * pMsg) |
| { |
| bool dealloc = TRUE; |
| |
| switch (pMsg->event) |
| { |
| /* External CHIPoBLE Event trigger */ |
| case BLEManagerIMPL_STATE_UPDATE_EVT: { |
| bStatus_t status; |
| |
| /* Verify BLE service mode is enabled */ |
| if ((sInstance.mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled) && |
| sInstance.mFlags.Has(Flags::kBLEStackInitialized)) |
| { |
| if (sInstance.mFlags.Has(Flags::kAdvertisingEnabled)) |
| { |
| BLEMGR_LOG("BLEMGR: BLE Process Application Message: kAdvertisingEnabled"); |
| |
| if (sInstance.mFlags.Has(Flags::kAdvertisingRefreshNeeded)) |
| { |
| BLEMGR_LOG("BLEMGR: BLE Process Application Message: kAdvertisingRefreshNeeded"); |
| |
| // Disable advertisements and proceed with updates |
| sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded); |
| |
| GapAdv_disable(sInstance.advHandleLegacy); |
| sInstance.mFlags.Clear(Flags::kAdvertising); |
| |
| uint32_t newParamMax = 0, newParamMin = 0; |
| if (sInstance.mFlags.Has(Flags::kFastAdvertisingEnabled)) |
| { |
| // Update advertising interval |
| BLEMGR_LOG("BLEMGR: ConfigureAdvertisements: Fast Advertising Enabled"); |
| newParamMax = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX; |
| newParamMin = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN; |
| } |
| else |
| { |
| // Decrease advertising interval |
| BLEMGR_LOG("BLEMGR: ConfigureAdvertisements: Slow Advertising Enabled"); |
| newParamMax = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; |
| newParamMin = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; |
| } |
| |
| // Set a parameter |
| GapAdv_setParam(sInstance.advHandleLegacy, GAP_ADV_PARAM_PRIMARY_INTERVAL_MAX, &newParamMax); |
| GapAdv_setParam(sInstance.advHandleLegacy, GAP_ADV_PARAM_PRIMARY_INTERVAL_MIN, &newParamMin); |
| |
| // Update advertisement parameters |
| ConfigureAdvertisements(); |
| } |
| } |
| |
| // Turn on advertisements |
| if (sInstance.mFlags.Has(Flags::kAdvertisingEnabled) && !sInstance.mFlags.Has(Flags::kAdvertising)) |
| { |
| // Send notification to thread manager that CHIPoBLE advertising is starting |
| |
| // Enable legacy advertising for set #1 |
| status = (bStatus_t) GapAdv_enable(sInstance.advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0); |
| |
| // If adverisement fails, keep flags set |
| if (status == SUCCESS) |
| { |
| |
| // Start advertisement timeout timer |
| if (sInstance.mFlags.Has(Flags::kFastAdvertisingEnabled)) |
| { |
| Util_rescheduleClock(&sInstance.clkAdvTimeout, CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME); |
| } |
| else |
| { |
| Util_rescheduleClock(&sInstance.clkAdvTimeout, |
| ADV_TIMEOUT - CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME); |
| } |
| Util_startClock(&sInstance.clkAdvTimeout); |
| |
| sInstance.mFlags.Set(Flags::kAdvertising); |
| } |
| } |
| // Advertising should be disabled |
| if ((!sInstance.mFlags.Has(Flags::kAdvertisingEnabled)) && sInstance.mFlags.Has(Flags::kAdvertising)) |
| { |
| BLEMGR_LOG("BLEMGR: BLE Process Application Message: ADvertisements disabled"); |
| |
| // Stop advertising |
| GapAdv_disable(sInstance.advHandleLegacy); |
| sInstance.mFlags.Clear(Flags::kAdvertising); |
| |
| Util_stopClock(&sInstance.clkAdvTimeout); |
| |
| // reset fast advertising |
| sInstance.mFlags.Set(Flags::kFastAdvertisingEnabled); |
| } |
| } |
| } |
| break; |
| |
| case BLEManagerIMPL_CHIPOBLE_CLOSE_CONN_EVT: { |
| uint16_t connHandle = *((uint16_t *) (pMsg->pData)); |
| |
| // Close active connection |
| GAP_TerminateLinkReq(connHandle, HCI_DISCONNECT_REMOTE_USER_TERM); |
| } |
| break; |
| |
| case BLEManagerIMPL_CHIPOBLE_TX_IND_EVT: { |
| uint8_t dataLen = ((CHIPoBLEIndEvt_t *) (pMsg->pData))->len; |
| |
| CHIPoBLEProfile_SetParameter(CHIPOBLEPROFILE_TX_CHAR, dataLen, (void *) (((CHIPoBLEIndEvt_t *) (pMsg->pData))->pData), |
| BLEManagerImpl::sSelfEntity); |
| |
| BLEMGR_LOG("BLEMGR: BLE Process Application Message: BLEManagerIMPL_CHIPOBLE_TX_IND_EVT: Length: %d", dataLen); |
| |
| ICall_free((void *) (((CHIPoBLEIndEvt_t *) (pMsg->pData))->pData)); |
| |
| dealloc = TRUE; |
| } |
| break; |
| |
| case CHIPOBLE_CHAR_CHANGE_EVT: { |
| uint16_t writeLen = ((CHIPoBLEProfChgEvt_t *) (pMsg->pData))->len; |
| uint8_t paramId = ((CHIPoBLEProfChgEvt_t *) (pMsg->pData))->paramId; |
| uint16_t connHandleId = ((CHIPoBLEProfChgEvt_t *) (pMsg->pData))->connHandle; |
| void * connHandle; |
| ChipDeviceEvent event; |
| |
| uint8_t i; |
| ConnRec_t * activeConnObj = NULL; |
| |
| // Find active connection |
| for (i = 0; i < MAX_NUM_BLE_CONNS; i++) |
| { |
| if (sInstance.connList[i].connHandle == connHandleId) |
| { |
| activeConnObj = &sInstance.connList[i]; |
| } |
| } |
| |
| connHandle = (void *) &activeConnObj->connHandle; |
| |
| if (paramId == CHIPOBLEPROFILE_RX_CHAR) |
| { |
| BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, CHIPOBLEPROFILE_RX_CHAR"); |
| // Pull written data from CHIPOBLE Profile based on extern server write |
| uint8_t * rxBuf = (uint8_t *) ICall_malloc(writeLen); |
| |
| if (rxBuf == NULL) |
| { |
| // alloc error |
| return; |
| } |
| |
| memset(rxBuf, 0x00, writeLen); |
| |
| BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, length: %d", writeLen); |
| CHIPoBLEProfile_GetParameter(CHIPOBLEPROFILE_RX_CHAR, rxBuf, writeLen); |
| |
| System::PacketBufferHandle packetBuf = System::PacketBufferHandle::NewWithData(rxBuf, writeLen, 0, 0); |
| |
| ICall_free(rxBuf); |
| |
| if (packetBuf.IsNull()) |
| { |
| // alloc error |
| return; |
| } |
| |
| // Arrange to post a CHIPoBLERXWriteEvent event to the CHIP queue. |
| event.Type = DeviceEventType::kCHIPoBLEWriteReceived; |
| event.CHIPoBLEWriteReceived.ConId = (void *) connHandle; |
| event.CHIPoBLEWriteReceived.Data = std::move(packetBuf).UnsafeRelease(); |
| } |
| else if (paramId == CHIPOBLEPROFILE_CCCWrite) |
| { |
| BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, CHIPOBLEPROFILE_CCCWrite"); |
| |
| // TODO: Add check to see if subscribing OR unsubscribing from char indications |
| uint8_t cccValue; |
| |
| CHIPoBLEProfile_GetParameter(CHIPOBLEPROFILE_CCCWrite, &cccValue, 1); |
| |
| // Check whether it is a sub/unsub event. 0x1 = Notifications enabled, 0x2 = Indications enabled |
| if (cccValue & 0x2) |
| { |
| // Post event to CHIP |
| BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, Subscrbe"); |
| event.Type = DeviceEventType::kCHIPoBLESubscribe; |
| } |
| else |
| { |
| BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, unsubscrbe"); |
| event.Type = DeviceEventType::kCHIPoBLEUnsubscribe; |
| } |
| |
| // Post event to CHIP |
| event.CHIPoBLESubscribe.ConId = (void *) connHandle; |
| } |
| PlatformMgr().PostEventOrDie(&event); |
| } |
| break; |
| |
| case ADV_EVT: |
| ProcessAdvEvent((GapAdvEventData_t *) (pMsg->pData)); |
| break; |
| |
| case PAIR_STATE_EVT: { |
| BLEMGR_LOG("BLEMGR: PAIR_STATE_EVT"); |
| |
| // Send passcode response |
| GAPBondMgr_PasscodeRsp(((PasscodeData_t *) (pMsg->pData))->connHandle, SUCCESS, B_APP_DEFAULT_PASSCODE); |
| } |
| break; |
| |
| case PASSCODE_EVT: { |
| BLEMGR_LOG("BLEMGR: PASSCODE_EVT"); |
| } |
| break; |
| |
| case READ_RPA_EVT: |
| UpdateBLERPA(); |
| break; |
| |
| case SEND_PARAM_UPDATE_EVT: { |
| // Extract connection handle from data |
| uint16_t connHandle = *(uint16_t *) (((ClockEventData_t *) pMsg->pData)->data); |
| |
| if (CHIP_NO_ERROR != ProcessParamUpdate(connHandle)) |
| { |
| // error |
| return; |
| } |
| |
| // This data is not dynamically allocated |
| dealloc = FALSE; |
| |
| /* If we are sending a param update request then the service discovery |
| * should have ended. Changed state to connected */ |
| DMMPolicy_updateStackState(DMMPolicy_StackRole_BlePeripheral, DMMPOLICY_BLE_CONNECTED); |
| |
| break; |
| } |
| |
| case CONN_EVT: |
| break; |
| |
| default: |
| // Do nothing. |
| break; |
| } |
| |
| // Free message data if it exists and we are to dealloc |
| if ((dealloc == TRUE) && (pMsg->pData != NULL)) |
| { |
| ICall_free(pMsg->pData); |
| } |
| } |
| |
| /********************************************************************* |
| * @fn ProcessGapMessage |
| * |
| * @brief Process an incoming GAP event. |
| * |
| * @param pMsg - message to process |
| */ |
| void BLEManagerImpl::ProcessGapMessage(gapEventHdr_t * pMsg) |
| { |
| BLEMGR_LOG("BLEMGR: ProcessGapMessage"); |
| |
| switch (pMsg->opcode) |
| { |
| case GAP_DEVICE_INIT_DONE_EVENT: { |
| BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_DEVICE_INIT_DONE_EVENT"); |
| |
| gapDeviceInitDoneEvent_t * pPkt = (gapDeviceInitDoneEvent_t *) pMsg; |
| |
| if (pPkt->hdr.status == SUCCESS) |
| { |
| // Store the system ID |
| uint8_t systemId[DEVINFO_SYSTEM_ID_LEN]; |
| |
| // use 6 bytes of device address for 8 bytes of system ID value |
| systemId[0] = pPkt->devAddr[0]; |
| systemId[1] = pPkt->devAddr[1]; |
| systemId[2] = pPkt->devAddr[2]; |
| |
| // set middle bytes to zero |
| systemId[4] = 0x00; |
| systemId[3] = 0x00; |
| |
| // shift three bytes up |
| systemId[7] = pPkt->devAddr[5]; |
| systemId[6] = pPkt->devAddr[4]; |
| systemId[5] = pPkt->devAddr[3]; |
| |
| // Set Device Info Service Parameter |
| DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); |
| |
| ConfigureAdvertisements(); |
| |
| sInstance.mFlags.Set(Flags::kBLEStackInitialized); |
| sInstance.mFlags.Set(Flags::kBLEStackAdvInitialized); |
| |
| /* Trigger post-initialization state update */ |
| DriveBLEState(); |
| |
| if (sInstance.addrMode > ADDRMODE_RANDOM) |
| { |
| UpdateBLERPA(); |
| // Create one-shot clock for RPA check event. |
| Util_constructClock(&sInstance.clkRpaRead, ClockHandler, READ_RPA_EVT_PERIOD, 0, true, |
| (uintptr_t) &sInstance.argRpaRead); |
| } |
| } |
| break; |
| } |
| |
| case GAP_LINK_ESTABLISHED_EVENT: { |
| gapEstLinkReqEvent_t * pPkt = (gapEstLinkReqEvent_t *) pMsg; |
| BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_LINK_ESTABLISHED_EVENT"); |
| |
| // Display the amount of current connections |
| uint8_t numActive = (uint8_t) linkDB_NumActive(""); |
| |
| if (pPkt->hdr.status == SUCCESS) |
| { |
| // Add connection to list and start RSSI |
| AddBLEConn(pPkt->connectionHandle); |
| } |
| |
| DMMPolicy_updateStackState(DMMPolicy_StackRole_BlePeripheral, DMMPOLICY_BLE_HIGH_BANDWIDTH); |
| |
| if (numActive >= MAX_NUM_BLE_CONNS) |
| { |
| // Stop advertising since there is no room for more connections |
| BLEMGR_LOG("BLEMGR: BLE event GAP_LINK_ESTABLISHED_EVENT: MAX connections"); |
| sInstance.mFlags.Clear(Flags::kAdvertisingEnabled).Clear(Flags::kAdvertising); |
| } |
| |
| /* Stop advertisement timeout timer */ |
| Util_stopClock(&sInstance.clkAdvTimeout); |
| // reset fast advertising |
| sInstance.mFlags.Set(Flags::kFastAdvertisingEnabled); |
| |
| DriveBLEState(); |
| |
| break; |
| } |
| |
| case GAP_LINK_TERMINATED_EVENT: { |
| gapTerminateLinkEvent_t * pPkt = (gapTerminateLinkEvent_t *) pMsg; |
| BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_LINK_TERMINATED_EVENT, reason: %d", pPkt->reason); |
| |
| // Remove the connection from the list and disable RSSI if needed |
| RemoveBLEConn(pPkt->connectionHandle); |
| |
| ChipDeviceEvent event; |
| event.Type = DeviceEventType::kCHIPoBLEConnectionError; |
| event.CHIPoBLEConnectionError.ConId = (void *) &pPkt->connectionHandle; |
| event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED; |
| PlatformMgr().PostEventOrDie(&event); |
| |
| DriveBLEState(); |
| |
| break; |
| } |
| |
| case GAP_UPDATE_LINK_PARAM_REQ_EVENT: { |
| BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_UPDATE_LINK_PARAM_REQ_EVENT"); |
| |
| gapUpdateLinkParamReqReply_t rsp; |
| |
| gapUpdateLinkParamReqEvent_t * pReq = (gapUpdateLinkParamReqEvent_t *) pMsg; |
| |
| rsp.connectionHandle = pReq->req.connectionHandle; |
| rsp.signalIdentifier = pReq->req.signalIdentifier; |
| |
| // Only accept connection intervals with slave latency of 0 |
| // This is just an example of how the application can send a response |
| if (pReq->req.connLatency == 0) |
| { |
| rsp.intervalMin = pReq->req.intervalMin; |
| rsp.intervalMax = pReq->req.intervalMax; |
| rsp.connLatency = pReq->req.connLatency; |
| rsp.connTimeout = pReq->req.connTimeout; |
| rsp.accepted = TRUE; |
| BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_UPDATE_LINK_PARAM_REQ_EVENT Accecpted"); |
| } |
| else |
| { |
| rsp.accepted = FALSE; |
| BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_UPDATE_LINK_PARAM_REQ_EVENT Rejected"); |
| } |
| |
| // Send Reply |
| VOID GAP_UpdateLinkParamReqReply(&rsp); |
| |
| break; |
| } |
| |
| case GAP_LINK_PARAM_UPDATE_EVENT: { |
| BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_LINK_PARAM_UPDATE_EVENT"); |
| |
| gapLinkUpdateEvent_t * pPkt = (gapLinkUpdateEvent_t *) pMsg; |
| |
| // Get the address from the connection handle |
| linkDBInfo_t linkInfo; |
| linkDB_GetInfo(pPkt->connectionHandle, &linkInfo); |
| |
| // Check if there are any queued parameter updates |
| ConnHandleEntry_t * connHandleEntry = (ConnHandleEntry_t *) List_get(&sInstance.paramUpdateList); |
| if (connHandleEntry != NULL) |
| { |
| // Attempt to send queued update now |
| ProcessParamUpdate(connHandleEntry->connHandle); |
| |
| // Free list element |
| ICall_free(connHandleEntry); |
| } |
| |
| break; |
| } |
| |
| default: |
| break; |
| } |
| } |
| |
| /********************************************************************* |
| * @fn ProcessGATTMsg |
| * |
| * @brief Process GATT messages and events. |
| * |
| * @return TRUE if safe to deallocate incoming message, FALSE otherwise. |
| */ |
| uint8_t BLEManagerImpl::ProcessGATTMsg(gattMsgEvent_t * pMsg) |
| { |
| uint8_t index; |
| BLEMGR_LOG("BLEMGR: ProcessGATTMsg"); |
| |
| if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT) |
| { |
| // ATT request-response or indication-confirmation flow control is |
| // The app is informed in case it wants to drop the connection. |
| } |
| else if (pMsg->method == ATT_MTU_UPDATED_EVENT) |
| { |
| index = GetBLEConnIndex(pMsg->connHandle); |
| |
| sInstance.connList[index].mtu = pMsg->msg.mtuEvt.MTU; |
| BLEMGR_LOG("BLEMGR: ProcessGATTMsg, ATT_MTU_UPDATED_EVENT: %d", pMsg->msg.mtuEvt.MTU); |
| } |
| else if (pMsg->method == ATT_HANDLE_VALUE_CFM) |
| { |
| void * connHandle; |
| ChipDeviceEvent event; |
| |
| ConnRec_t * activeConnObj = NULL; |
| |
| activeConnObj = &sInstance.connList[0]; |
| connHandle = (void *) &activeConnObj->connHandle; |
| |
| event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm; |
| event.CHIPoBLEIndicateConfirm.ConId = connHandle; |
| PlatformMgr().PostEventOrDie(&event); |
| |
| BLEMGR_LOG("BLEMGR: ProcessGATTMsg, ATT_HANDLE_VALUE_CFM:"); |
| } |
| // Free message payload. Needed only for ATT Protocol messages |
| GATT_bm_free(&pMsg->msg, pMsg->method); |
| |
| // It's safe to free the incoming message |
| return TRUE; |
| } |
| |
| /********************************************************************* |
| * @fn ProcessAdvEvent |
| * |
| * @brief Process advertising event in app context |
| * |
| * @param pEventData |
| */ |
| void BLEManagerImpl::ProcessAdvEvent(GapAdvEventData_t * pEventData) |
| { |
| BLEMGR_LOG("BLEMGR: ProcessAdvEvent"); |
| |
| switch (pEventData->event) |
| { |
| case GAP_EVT_ADV_START_AFTER_ENABLE: { |
| BLEMGR_LOG("BLEMGR: ProcessAdvEvent: GAP_EVT_ADV_START_AFTER_ENABLE"); |
| |
| if (linkDB_NumActive("") == 0) |
| { |
| DMMPolicy_updateStackState(DMMPolicy_StackRole_BlePeripheral, DMMPOLICY_BLE_ADV); |
| } |
| } |
| break; |
| |
| case GAP_EVT_ADV_END_AFTER_DISABLE: { |
| BLEMGR_LOG("BLEMGR: ProcessAdvEvent: GAP_EVT_ADV_END_AFTER_DISABLE"); |
| } |
| break; |
| |
| case GAP_EVT_ADV_START: |
| break; |
| |
| case GAP_EVT_ADV_END: |
| break; |
| |
| // BLE Stack has ended advertising due to connection |
| case GAP_EVT_ADV_SET_TERMINATED: { |
| BLEMGR_LOG("BLEMGR: ProcessAdvEvent: GAP_EVT_ADV_SET_TERMINATED"); |
| } |
| break; |
| |
| case GAP_EVT_SCAN_REQ_RECEIVED: |
| break; |
| |
| case GAP_EVT_INSUFFICIENT_MEMORY: |
| break; |
| |
| default: |
| break; |
| } |
| |
| // All events have associated memory to free except the insufficient memory |
| // event |
| if (pEventData->event != GAP_EVT_INSUFFICIENT_MEMORY) |
| { |
| ICall_free(pEventData->pBuf); |
| } |
| } |
| |
| /********************************************************************* |
| * @fn ProcessParamUpdate |
| * |
| * @brief Process a parameters update request |
| * |
| * @return None |
| */ |
| CHIP_ERROR BLEManagerImpl::ProcessParamUpdate(uint16_t connHandle) |
| { |
| gapUpdateLinkParamReq_t req; |
| uint8_t connIndex; |
| BLEMGR_LOG("BLEMGR: ProcessParamUpdate"); |
| |
| req.connectionHandle = connHandle; |
| req.connLatency = DEFAULT_DESIRED_PERIPHERAL_LATENCY; |
| req.connTimeout = DEFAULT_DESIRED_CONN_TIMEOUT; |
| req.intervalMin = DEFAULT_DESIRED_MIN_CONN_INTERVAL; |
| req.intervalMax = DEFAULT_DESIRED_MAX_CONN_INTERVAL; |
| |
| connIndex = GetBLEConnIndex(connHandle); |
| if (!(connIndex < MAX_NUM_BLE_CONNS)) |
| { |
| return CHIP_ERROR_TOO_MANY_CONNECTIONS; |
| } |
| |
| // Deconstruct the clock object |
| ClockP_destruct(sInstance.connList[connIndex].pUpdateClock); |
| // Free clock struct |
| if (sInstance.connList[connIndex].pUpdateClock != NULL) |
| { |
| ICall_free(sInstance.connList[connIndex].pUpdateClock); |
| sInstance.connList[connIndex].pUpdateClock = NULL; |
| } |
| // Free ParamUpdateEventData |
| if (sInstance.connList[connIndex].pParamUpdateEventData != NULL) |
| { |
| ICall_free(sInstance.connList[connIndex].pParamUpdateEventData); |
| } |
| |
| BLEMGR_LOG("BLEMGR: ProcessParamUpdate Send Link Param Req"); |
| // Send parameter update |
| bStatus_t status = GAP_UpdateLinkParamReq(&req); |
| |
| // If there is an ongoing update, queue this for when the udpate completes |
| if (status == bleAlreadyInRequestedMode) |
| { |
| |
| BLEMGR_LOG("BLEMGR: ProcessParamUpdate pending"); |
| ConnHandleEntry_t * connHandleEntry = (ConnHandleEntry_t *) (ICall_malloc(sizeof(ConnHandleEntry_t))); |
| if (connHandleEntry) |
| { |
| connHandleEntry->connHandle = connHandle; |
| List_put(&sInstance.paramUpdateList, (List_Elem *) connHandleEntry); |
| } |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| /********************************************************************* |
| * @fn EnqueueEvtHdrMsg |
| * |
| * @brief Creates a message and puts the message in RTOS queue. |
| * |
| * @param event - message event. |
| * @param state - message state. |
| */ |
| status_t BLEManagerImpl::EnqueueEvtHdrMsg(uint8_t event, void * pData) |
| { |
| uint8_t success; |
| |
| if (sInstance.mFlags.Has(Flags::kBLEStackInitialized)) |
| { |
| QueuedEvt_t * pMsg = (QueuedEvt_t *) ICall_malloc(sizeof(QueuedEvt_t)); |
| |
| // Create dynamic pointer to message. |
| if (pMsg) |
| { |
| pMsg->event = event; |
| pMsg->pData = pData; |
| |
| // Enqueue the message. |
| success = Util_enqueueMsg(sEventHandlerMsgQueueID, BLEManagerImpl::sSyncEvent, (uint8_t *) pMsg); |
| |
| return (success) ? SUCCESS : FAILURE; |
| } |
| |
| return bleMemAllocError; |
| } |
| else |
| { |
| return true; |
| } |
| } |
| |
| /********************************************************************* |
| * @fn AddBLEConn |
| * |
| * @brief Add a device to the connected device list |
| * |
| * @return index of the connected device list entry where the new connection |
| * info is put in. |
| * if there is no room, MAX_NUM_BLE_CONNS will be returned. |
| */ |
| uint8_t BLEManagerImpl::AddBLEConn(uint16_t connHandle) |
| { |
| uint8_t i; |
| uint8_t status = bleNoResources; |
| BLEMGR_LOG("BLEMGR: AddBLEConn"); |
| |
| // Try to find an available entry |
| for (i = 0; i < MAX_NUM_BLE_CONNS; i++) |
| { |
| if (sInstance.connList[i].connHandle == LL_CONNHANDLE_INVALID) |
| { |
| // Found available entry to put a new connection info in |
| sInstance.connList[i].connHandle = connHandle; |
| |
| // Allocate data to send through clock handler |
| sInstance.connList[i].pParamUpdateEventData = |
| (ClockEventData_t *) ICall_malloc(sizeof(ClockEventData_t) + sizeof(uint16_t)); |
| if (sInstance.connList[i].pParamUpdateEventData) |
| { |
| sInstance.connList[i].pParamUpdateEventData->event = SEND_PARAM_UPDATE_EVT; |
| *((uint16_t *) sInstance.connList[i].pParamUpdateEventData->data) = connHandle; |
| |
| // Create a clock object and start |
| sInstance.connList[i].pUpdateClock = (ClockP_Struct *) ICall_malloc(sizeof(ClockP_Struct)); |
| |
| if (sInstance.connList[i].pUpdateClock) |
| { |
| Util_constructClock(sInstance.connList[i].pUpdateClock, ClockHandler, SEND_PARAM_UPDATE_DELAY, 0, true, |
| (uintptr_t) sInstance.connList[i].pParamUpdateEventData); |
| } |
| else |
| { |
| ICall_free(sInstance.connList[i].pParamUpdateEventData); |
| } |
| } |
| else |
| { |
| status = bleMemAllocError; |
| } |
| |
| break; |
| } |
| } |
| return status; |
| } |
| |
| /********************************************************************* |
| * @fn RemoveBLEConn |
| * |
| * @brief Remove a device from the connected device list |
| * |
| * @return index of the connected device list entry where the new connection |
| * info is removed from. |
| * if connHandle is not found, MAX_NUM_BLE_CONNS will be returned. |
| */ |
| uint8_t BLEManagerImpl::RemoveBLEConn(uint16_t connHandle) |
| { |
| uint8_t connIndex = GetBLEConnIndex(connHandle); |
| BLEMGR_LOG("BLEMGR: RemoveBLEConn"); |
| |
| if (connIndex != MAX_NUM_BLE_CONNS) |
| { |
| ClockP_Struct * pUpdateClock = sInstance.connList[connIndex].pUpdateClock; |
| |
| if (pUpdateClock != NULL) |
| { |
| // Stop and destruct the RTOS clock if it's still alive |
| if (Util_isActive(pUpdateClock)) |
| { |
| Util_stopClock(pUpdateClock); |
| } |
| |
| // Destruct the clock object |
| ClockP_destruct(pUpdateClock); |
| // Free clock struct |
| ICall_free(pUpdateClock); |
| // Free ParamUpdateEventData |
| ICall_free(sInstance.connList[connIndex].pParamUpdateEventData); |
| } |
| // Clear pending update requests from paramUpdateList |
| ClearPendingBLEParamUpdate(connHandle); |
| |
| // Clear Connection List Entry |
| ClearBLEConnListEntry(connHandle); |
| } |
| return connIndex; |
| } |
| |
| /********************************************************************* |
| * @fn GetBLEConnIndex |
| * |
| * @brief Find index in the connected device list by connHandle |
| * |
| * @return the index of the entry that has the given connection handle. |
| * if there is no match, MAX_NUM_BLE_CONNS will be returned. |
| */ |
| uint8_t BLEManagerImpl::GetBLEConnIndex(uint16_t connHandle) const |
| { |
| uint8_t i; |
| |
| BLEMGR_LOG("BLEMGR: GetBLEConnIndex"); |
| |
| for (i = 0; i < MAX_NUM_BLE_CONNS; i++) |
| { |
| if (sInstance.connList[i].connHandle == connHandle) |
| { |
| return i; |
| } |
| } |
| |
| return MAX_NUM_BLE_CONNS; |
| } |
| |
| /********************************************************************* |
| * @fn ClearBLEConnListEntry |
| * |
| * @brief Find index in the connected device list by connHandle |
| * |
| * @return the index of the entry that has the given connection handle. |
| * if there is no match, MAX_NUM_BLE_CONNS will be returned. |
| */ |
| uint8_t BLEManagerImpl::ClearBLEConnListEntry(uint16_t connHandle) |
| { |
| uint8_t i; |
| // Set to invalid connection index initially |
| uint8_t connIndex = MAX_NUM_BLE_CONNS; |
| |
| BLEMGR_LOG("BLEMGR: ClearBLEConnListEntry"); |
| if (connHandle != LL_CONNHANDLE_ALL) |
| { |
| // Get connection index from handle |
| connIndex = GetBLEConnIndex(connHandle); |
| if (connIndex >= MAX_NUM_BLE_CONNS) |
| { |
| return bleInvalidRange; |
| } |
| } |
| |
| // Clear specific handle or all handles |
| for (i = 0; i < MAX_NUM_BLE_CONNS; i++) |
| { |
| if ((connIndex == i) || (connHandle == LL_CONNHANDLE_ALL)) |
| { |
| sInstance.connList[i].connHandle = LL_CONNHANDLE_INVALID; |
| sInstance.connList[i].currPhy = 0; |
| sInstance.connList[i].phyCngRq = 0; |
| sInstance.connList[i].phyRqFailCnt = 0; |
| sInstance.connList[i].rqPhy = 0; |
| memset(sInstance.connList[i].rssiArr, 0, MAX_RSSI_STORE_DEPTH); |
| sInstance.connList[i].rssiAvg = 0; |
| sInstance.connList[i].rssiCntr = 0; |
| sInstance.connList[i].isAutoPHYEnable = FALSE; |
| sInstance.connList[i].mtu = 0; |
| } |
| } |
| |
| return SUCCESS; |
| } |
| |
| /********************************************************************* |
| * @fn ClearPendingBLEParamUpdate |
| * |
| * @brief clean pending param update request in the paramUpdateList list |
| * |
| * @param connHandle - connection handle to clean |
| * |
| * @return none |
| */ |
| void BLEManagerImpl::ClearPendingBLEParamUpdate(uint16_t connHandle) |
| { |
| List_Elem * curr; |
| |
| BLEMGR_LOG("BLEMGR: ClearPendingBLEParamUpdate"); |
| |
| for (curr = List_head(&sInstance.paramUpdateList); curr != NULL; curr = List_next(curr)) |
| { |
| if (((ConnHandleEntry_t *) curr)->connHandle == connHandle) |
| { |
| List_remove(&sInstance.paramUpdateList, curr); |
| } |
| } |
| } |
| |
| /********************************************************************* |
| * @fn UpdateBLERPA |
| * |
| * @brief Read the current RPA from the stack and update display |
| * if the RPA has changed. |
| * |
| * @param None. |
| * |
| * @return None. |
| */ |
| void BLEManagerImpl::UpdateBLERPA(void) |
| { |
| uint8_t * pRpaNew; |
| |
| // Read the current RPA. |
| pRpaNew = GAP_GetDevAddress(FALSE); |
| |
| if (memcmp(pRpaNew, sInstance.rpa, B_ADDR_LEN)) |
| { |
| memcpy(sInstance.rpa, pRpaNew, B_ADDR_LEN); |
| } |
| } |
| |
| void BLEManagerImpl::EventHandler(void * arg) |
| { |
| PlatformMgr().LockChipStack(); |
| sInstance.EventHandler_init(); |
| |
| PlatformMgr().UnlockChipStack(); |
| |
| for (;;) |
| { |
| uint32_t events; |
| |
| // Waits for an event to be posted associated with the calling thread. |
| // Note that an event associated with a thread is posted when a |
| // message is queued to the message receive queue of the thread |
| xQueueReceive((QueueHandle_t) BLEManagerImpl::sSyncEvent, (char *) &events, portMAX_DELAY); |
| |
| if (events) |
| { |
| ICall_EntityID dest; |
| ICall_ServiceEnum src; |
| ICall_HciExtEvt * hcipMsg = NULL; |
| |
| /* Lock CHIP Stack while processing BLE Stack/App events */ |
| PlatformMgr().LockChipStack(); |
| |
| // Fetch any available messages that might have been sent from the stack |
| if (ICall_fetchServiceMsg(&src, &dest, (void **) &hcipMsg) == ICALL_ERRNO_SUCCESS) |
| { |
| uint8 safeToDealloc = TRUE; |
| |
| if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == BLEManagerImpl::sSelfEntity)) |
| { |
| ICall_Stack_Event * pEvt = (ICall_Stack_Event *) hcipMsg; |
| |
| // Check for non-BLE stack events |
| if (pEvt->signature != 0xffff) |
| { |
| // Process inter-task message |
| safeToDealloc = sInstance.ProcessStackEvent((ICall_Hdr *) hcipMsg); |
| } |
| } |
| |
| if (hcipMsg && safeToDealloc) |
| { |
| ICall_freeMsg(hcipMsg); |
| } |
| } |
| |
| // If RTOS queue is not empty, process CHIP messages. |
| if (events & QUEUE_EVT) |
| { |
| QueuedEvt_t * pMsg; |
| for (;;) |
| { |
| pMsg = (QueuedEvt_t *) Util_dequeueMsg(BLEManagerImpl::sEventHandlerMsgQueueID); |
| if (NULL != pMsg) |
| { |
| // Process message. |
| sInstance.ProcessEvtHdrMsg(pMsg); |
| |
| // Free the space from the message. |
| ICall_free(pMsg); |
| } |
| else |
| { |
| break; |
| } |
| } |
| } |
| |
| PlatformMgr().UnlockChipStack(); |
| } |
| } |
| } |
| |
| /* Post event to app processing loop to begin CHIP advertising */ |
| CHIP_ERROR BLEManagerImpl::DriveBLEState(void) |
| { |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| BLEMGR_LOG("BLEMGR: DriveBLEState"); |
| |
| if (sInstance.EnqueueEvtHdrMsg(BLEManagerIMPL_STATE_UPDATE_EVT, NULL) != SUCCESS) |
| { |
| err = CHIP_ERROR_NO_MEMORY; |
| } |
| return err; |
| } |
| |
| /********************************************************************* |
| * @fn advCallback |
| * |
| * @brief GapAdv module callback |
| * |
| * @param pMsg - message to process |
| */ |
| void BLEManagerImpl::advCallback(uint32_t event, void * pBuf, uintptr_t arg) |
| { |
| BLEMGR_LOG("BLEMGR: advCallback"); |
| |
| GapAdvEventData_t * pData = (GapAdvEventData_t *) ICall_malloc(sizeof(GapAdvEventData_t)); |
| |
| if (pData) |
| { |
| pData->event = event; |
| pData->pBuf = pBuf; |
| if (sInstance.EnqueueEvtHdrMsg(ADV_EVT, pData) != SUCCESS) |
| { |
| ICall_free(pData); |
| } |
| } |
| } |
| |
| void BLEManagerImpl::AdvTimeoutHandler(uintptr_t arg) |
| { |
| BLEMGR_LOG("BLEMGR: AdvTimeoutHandler"); |
| |
| if (sInstance.mFlags.Has(Flags::kAdvertisingEnabled)) |
| { |
| if (sInstance.mFlags.Has(Flags::kFastAdvertisingEnabled)) |
| { |
| BLEMGR_LOG("BLEMGR: Fast advertising timeout reached"); |
| |
| sInstance.mFlags.Clear(Flags::kFastAdvertisingEnabled); |
| sInstance.mFlags.Set(Flags::kAdvertisingRefreshNeeded); |
| } |
| else |
| { |
| BLEMGR_LOG("BLEMGR: Advertising timeout reached"); |
| |
| sInstance.mFlags.Clear(Flags::kAdvertisingEnabled); |
| } |
| /* Send event to process state change request */ |
| DriveBLEState(); |
| } |
| } |
| |
| void BLEManagerImpl::ClockHandler(uintptr_t arg) |
| { |
| ClockEventData_t * pData = (ClockEventData_t *) arg; |
| |
| if (pData->event == READ_RPA_EVT) |
| { |
| // Start the next period |
| Util_startClock(&sInstance.clkRpaRead); |
| |
| // Post event to read the current RPA |
| sInstance.EnqueueEvtHdrMsg(READ_RPA_EVT, NULL); |
| } |
| else if (pData->event == SEND_PARAM_UPDATE_EVT) |
| { |
| // Send message to app |
| if (sInstance.EnqueueEvtHdrMsg(SEND_PARAM_UPDATE_EVT, pData) != SUCCESS) |
| { |
| ICall_free(pData); |
| } |
| } |
| } |
| |
| /********************************************************************* |
| * @fn CHIPoBLEProfile_charValueChangeCB |
| * |
| * @brief Callback from CHIPoBLE Profile indicating a characteristic |
| * value change. |
| * Calling context (BLE Stack Task) |
| * |
| * @param paramId - parameter Id of the value that was changed. |
| * |
| * @return None. |
| */ |
| void BLEManagerImpl::CHIPoBLEProfile_charValueChangeCB(uint8_t paramId, uint16_t len, uint16_t connHandle) |
| { |
| CHIPoBLEProfChgEvt_t * pValue = (CHIPoBLEProfChgEvt_t *) ICall_malloc(sizeof(CHIPoBLEProfChgEvt_t)); |
| BLEMGR_LOG("BLEMGR: CHIPoBLEProfile_charValueChangeCB"); |
| |
| if (pValue) |
| { |
| pValue->paramId = paramId; |
| pValue->len = len; |
| pValue->connHandle = connHandle; |
| |
| if (sInstance.EnqueueEvtHdrMsg(CHIPOBLE_CHAR_CHANGE_EVT, pValue) != SUCCESS) |
| { |
| ICall_free(pValue); |
| } |
| } |
| } |
| |
| /********************************************************************* |
| * @fn RemoteDisplay_passcodeCb |
| * |
| * @brief Passcode callback. |
| * |
| * @return none |
| */ |
| void BLEManagerImpl::PasscodeCb(uint8_t * pDeviceAddr, uint16_t connHandle, uint8_t uiInputs, uint8_t uiOutputs, |
| uint32_t numComparison) |
| { |
| PasscodeData_t * pData = (PasscodeData_t *) ICall_malloc(sizeof(PasscodeData_t)); |
| |
| // Allocate space for the passcode event. |
| if (pData) |
| { |
| pData->connHandle = connHandle; |
| memcpy(pData->deviceAddr, pDeviceAddr, B_ADDR_LEN); |
| pData->uiInputs = uiInputs; |
| pData->uiOutputs = uiOutputs; |
| pData->numComparison = numComparison; |
| |
| // Enqueue the event. |
| if (sInstance.EnqueueEvtHdrMsg(PASSCODE_EVT, pData) != SUCCESS) |
| { |
| ICall_free(pData); |
| } |
| } |
| } |
| |
| /********************************************************************* |
| * @fn PairStateCb |
| * |
| * @brief Pairing state callback. |
| * |
| * @return none |
| */ |
| void BLEManagerImpl::PairStateCb(uint16_t connHandle, uint8_t state, uint8_t status) |
| { |
| PairStateData_t * pData = (PairStateData_t *) ICall_malloc(sizeof(PairStateData_t)); |
| |
| // Allocate space for the event data. |
| if (pData) |
| { |
| pData->state = state; |
| pData->connHandle = connHandle; |
| pData->status = status; |
| |
| // Queue the event. |
| if (sInstance.EnqueueEvtHdrMsg(PAIR_STATE_EVT, pData) != SUCCESS) |
| { |
| ICall_free(pData); |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| * @fn AssertHandler |
| * |
| * @brief This is the Application's callback handler for asserts raised |
| * in the stack. When EXT_HAL_ASSERT is defined in the Stack |
| * project this function will be called when an assert is raised, |
| * and can be used to observe or trap a violation from expected |
| * behavior. |
| * |
| * As an example, for Heap allocation failures the Stack will raise |
| * HAL_ASSERT_CAUSE_OUT_OF_MEMORY as the assertCause and |
| * HAL_ASSERT_SUBCAUSE_NONE as the assertSubcause. An application |
| * developer could trap any malloc failure on the stack by calling |
| * HAL_ASSERT_SPINLOCK under the matching case. |
| * |
| * An application developer is encouraged to extend this function |
| * for use by their own application. To do this, add hal_assert.c |
| * to your project workspace, the path to hal_assert.h (this can |
| * be found on the stack side). Asserts are raised by including |
| * hal_assert.h and using macro HAL_ASSERT(cause) to raise an |
| * assert with argument assertCause. the assertSubcause may be |
| * optionally set by macro HAL_ASSERT_SET_SUBCAUSE(subCause) prior |
| * to asserting the cause it describes. More information is |
| * available in hal_assert.h. |
| * |
| * input parameters |
| * |
| * @param assertCause - Assert cause as defined in hal_assert.h. |
| * @param assertSubcause - Optional assert subcause (see hal_assert.h). |
| * |
| * output parameters |
| * |
| * @param None. |
| * |
| * @return None. |
| */ |
| void BLEManagerImpl::AssertHandler(uint8 assertCause, uint8 assertSubcause) |
| { |
| // check the assert cause |
| switch (assertCause) |
| { |
| case HAL_ASSERT_CAUSE_OUT_OF_MEMORY: |
| assert(false); |
| break; |
| |
| case HAL_ASSERT_CAUSE_INTERNAL_ERROR: |
| // check the subcause |
| if (assertSubcause == HAL_ASSERT_SUBCAUSE_FW_INERNAL_ERROR) |
| { |
| assert(false); |
| } |
| else |
| { |
| assert(false); |
| } |
| break; |
| case HAL_ASSERT_CAUSE_ICALL_ABORT: |
| assert(false); |
| |
| case HAL_ASSERT_CAUSE_ICALL_TIMEOUT: |
| assert(false); |
| break; |
| case HAL_ASSERT_CAUSE_WRONG_API_CALL: |
| assert(false); |
| break; |
| default: |
| assert(false); |
| break; |
| } |
| return; |
| } |
| |
| } // namespace Internal |
| } // namespace DeviceLayer |
| } // namespace chip |
| |
| #endif /* CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE */ |