/* * * Copyright (c) 2020-2021 Project CHIP Authors * * 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 singleton object * for the stm32wb55 platforms. */ /* this file behaves like a config.h, comes first */ #include #include #include #include #include #include /**** STM32 api files for ble and led support ****/ #include "app_ble.h" #include "app_matter.h" #include "ble_gap_aci.h" #include "cmsis_os.h" using namespace ::chip; using namespace ::chip::Ble; using namespace ::chip::System; namespace chip { namespace DeviceLayer { namespace Internal { namespace { // Advertising data content definitions #define CHIP_ADV_DATA_TYPE_FLAGS 0x01 #define CHIP_ADV_DATA_TYPE_UUID 0x03 #define CHIP_ADV_DATA_FLAGS 0x06 #define CHIP_ADV_DATA_TYPE_NAME 0x09 #define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16 #define STM32_MTU 247 #define CHIP_ADV_SHORT_UUID_LEN 2 #define CONNECTION_CLOSE 0x13 // FreeeRTOS sw timer TimerHandle_t sbleAdvTimeoutTimer; // Full service UUID - CHIP_BLE_SVC_ID - taken from BleUUID.h header const uint8_t chipUUID_CHIPoBLE_Service[CHIP_ADV_SHORT_UUID_LEN] = { 0xFF, 0xF6 }; } // unnamed namespace BLEManagerImpl BLEManagerImpl::sInstance; uint16_t gconnid = 0; CHIP_ERROR BLEManagerImpl::_Init() { CHIP_ERROR err; mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART); mFlags.Set(Flags::kFastAdvertisingEnabled); mNumGAPCons = 0; for (int i = 0; i < kMaxConnections; i++) { mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED; } // Initialize the CHIP BleLayer. err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer()); SuccessOrExit(err); // Create FreeRTOS sw timer for BLE timeouts and interval change. sbleAdvTimeoutTimer = xTimerCreate("BleAdvTimer", // Just a text name, not used by the RTOS kernel pdMS_TO_TICKS(1), // == default timer period (mS) false, // no timer reload (==one-shot) (void *) this, // init timer id = ble obj context BleAdvTimeoutHandler // timer callback handler ); VerifyOrExit(sbleAdvTimeoutTimer != NULL, err = CHIP_ERROR_INCORRECT_STATE); PlatformMgr().ScheduleWork(DriveBLEState, 0); APP_MATTER_BLE_Set_Receive_Callback(HandleRXCharWrite); APP_MATTER_BLE_Set_Connection_Callback(HandleGAPConnect); APP_MATTER_BLE_Set_Disconnection_Callback(HandleGAPDisconnect); APP_MATTER_BLE_Set_TXCharCCCDWrite_Callback(HandleTXCharCCCDWrite); APP_MATTER_BLE_Set_Ack_After_Indicate_Callback(HandleAck); exit: ChipLogProgress(DeviceLayer, "BLEManagerImpl::Init() complete"); return err; } CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val) { CHIP_ERROR err = CHIP_NO_ERROR; VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); if (val != mServiceMode) { mServiceMode = val; PlatformMgr().ScheduleWork(DriveBLEState, 0); } exit: return err; } CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) { CHIP_ERROR err = CHIP_NO_ERROR; VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); ChipLogDetail(DeviceLayer, "CHIPoBLE advertising set to %s", val ? "on" : "off"); if (mFlags.Has(Flags::kAdvertisingEnabled) != val) { mFlags.Set(Flags::kAdvertisingEnabled, val); PlatformMgr().ScheduleWork(DriveBLEState, 0); } exit: return err; } CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) { switch (mode) { case BLEAdvertisingMode::kFastAdvertising: mFlags.Set(Flags::kFastAdvertisingEnabled); break; case BLEAdvertisingMode::kSlowAdvertising: mFlags.Clear(Flags::kFastAdvertisingEnabled); break; default: return CHIP_ERROR_INVALID_ARGUMENT; } mFlags.Set(Flags::kAdvertisingRefreshNeeded); PlatformMgr().ScheduleWork(DriveBLEState, 0); return CHIP_NO_ERROR; } CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize) { CHIP_ERROR err = CHIP_NO_ERROR; return err; } CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * devName) { CHIP_ERROR err = CHIP_NO_ERROR; VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); if (devName != nullptr && devName[0] != 0) { // TODO set device name SuccessOrExit(err); mFlags.Set(Flags::kDeviceNameSet); } exit: return err; } void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) { switch (event->Type) { // Platform specific events case DeviceEventType::kCHIPoBLESubscribe: { ChipDeviceEvent connEstEvent; HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished; PlatformMgr().PostEventOrDie(&connEstEvent); } break; case DeviceEventType::kCHIPoBLEUnsubscribe: { HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); } break; case DeviceEventType::kCHIPoBLEWriteReceived: { HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_1_UUID, PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); } break; case DeviceEventType::kCHIPoBLEConnectionError: { HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason); } break; // Generic CHIP events case DeviceEventType::kServiceProvisioningChange: // Force the advertising state to be refreshed to reflect new provisioning state. mFlags.Set(Flags::kAdvertisingRefreshNeeded); PlatformMgr().ScheduleWork(DriveBLEState, 0); break; case DeviceEventType::kCHIPoBLEIndicateConfirm: { HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); } break; default: break; } } CHIP_ERROR BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) { ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported"); return CHIP_ERROR_NOT_IMPLEMENTED; } CHIP_ERROR BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) { ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported"); return CHIP_ERROR_NOT_IMPLEMENTED; } CHIP_ERROR BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) { CHIP_ERROR err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; ChipLogProgress(DeviceLayer, "Closing BLE GATT connection con %u", *(uint16_t *) conId); // aci_gap_terminate(gconnid, CONNECTION_CLOSE); return err; } uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const { uint16_t retVal = 0; // TODO get MTU from stm32 api retVal = STM32_MTU; return retVal; } CHIP_ERROR BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, PacketBufferHandle data) { uint16_t dataLen = data->DataLength(); ChipLogDetail(DeviceLayer, "Sending notification for CHIPoBLE Client TX (con %u, len %u)", *(uint16_t *) conId, dataLen); APP_MATTER_Send_Notification(dataLen, data->Start()); return CHIP_NO_ERROR; } CHIP_ERROR BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, PacketBufferHandle pBuf) { ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported"); return CHIP_ERROR_NOT_IMPLEMENTED; } void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) { CloseConnection(conId); } void BLEManagerImpl::DriveBLEState(void) { CHIP_ERROR err = CHIP_NO_ERROR; // Perform any initialization actions that must occur after the CHIP task is running. if (!mFlags.Has(Flags::kAsyncInitCompleted)) { mFlags.Set(Flags::kAsyncInitCompleted); ChipLogProgress(DeviceLayer, "kAsyncInitCompleted done"); // If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, // disable CHIPoBLE advertising if the device is fully provisioned. #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED if (ConfigurationMgr().IsFullyProvisioned()) { mFlags.Clear(Flags::kAdvertisingEnabled); ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned"); } #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED } // If the application has enabled CHIPoBLE and BLE advertising... if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kAdvertisingEnabled) #if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION // and no connections are active... && (mNumGAPCons == 0) #endif ) { // Start/re-start BLE advertising if not already advertising, or if the // advertising state of the underlying stack needs to be refreshed. if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded)) { mFlags.Clear(Flags::kAdvertisingRefreshNeeded); err = StartAdvertising(); SuccessOrExit(err); } } // Otherwise, stop advertising if currently active. else if (mFlags.Has(Flags::kAdvertising)) { err = StopAdvertising(); SuccessOrExit(err); } exit: if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err)); mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; } } CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) { ChipBLEDeviceIdentificationInfo mDeviceIdInfo; CHIP_ERROR err; uint8_t index = 0; uint8_t deviceNameLength = 0; uint8_t deviceIdInfoLength = 0; int ret = 0; char deviceName[kMaxDeviceNameLength + 1]; uint8_t advDataBuf[kMaxAdvertisementDataSetSize]; uint8_t scanRespDataBuf[kMaxAdvertisementDataSetSize]; memset(advDataBuf, 0, kMaxAdvertisementDataSetSize); memset(scanRespDataBuf, 0, kMaxAdvertisementDataSetSize); err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo); SuccessOrExit(err); if (!mFlags.Has(Flags::kDeviceNameSet)) { snprintf(deviceName, sizeof(deviceName), "%s%04" PRIX32, CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, (uint32_t) 0); deviceName[kMaxDeviceNameLength] = 0; SuccessOrExit(err); } deviceNameLength = static_cast(strlen(deviceName)); deviceIdInfoLength = sizeof(mDeviceIdInfo); // Check sizes static_assert(sizeof(mDeviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1 <= UINT8_MAX, "Our length won't fit in a uint8_t"); static_assert(2 + CHIP_ADV_SHORT_UUID_LEN + sizeof(mDeviceIdInfo) + 1 <= kMaxAdvertisementDataSetSize, "Advertisement data buffer is not big enough"); // Fill in advertising data index = 0; advDataBuf[index++] = 0x02; // length advDataBuf[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags advDataBuf[index++] = CHIP_ADV_DATA_FLAGS; // AD value advDataBuf[index++] = static_cast(deviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1); // AD length advDataBuf[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type : Service Data advDataBuf[index++] = chipUUID_CHIPoBLE_Service[1]; // AD value advDataBuf[index++] = chipUUID_CHIPoBLE_Service[0]; memcpy(&advDataBuf[index], (void *) &mDeviceIdInfo, deviceIdInfoLength); // AD value index = static_cast(index + deviceIdInfoLength); ChipLogError(DeviceLayer, "state return update adv: %d", ret); // Fill in scan response data index = 0; scanRespDataBuf[index++] = CHIP_ADV_SHORT_UUID_LEN + 1; // AD length scanRespDataBuf[index++] = CHIP_ADV_DATA_TYPE_UUID; // AD type : uuid scanRespDataBuf[index++] = chipUUID_CHIPoBLE_Service[1]; // AD value scanRespDataBuf[index++] = chipUUID_CHIPoBLE_Service[0]; VerifyOrExit(index + (deviceNameLength + 2) <= kMaxAdvertisementDataSetSize, err = CHIP_ERROR_BUFFER_TOO_SMALL); scanRespDataBuf[index++] = static_cast(deviceNameLength + 1); // length scanRespDataBuf[index++] = CHIP_ADV_DATA_TYPE_NAME; // AD type : name memcpy(&scanRespDataBuf[index], deviceName, deviceNameLength); // AD value index = static_cast(index + deviceNameLength); exit: return err; } CHIP_ERROR BLEManagerImpl::StartAdvertising(void) { CHIP_ERROR err; // If already advertising, stop it, before changing values if (mFlags.Has(Flags::kAdvertising)) { APP_BLE_Adv_Cancel(); // ST ble api } else { ChipLogProgress(DeviceLayer, "CHIPoBLE start advertising"); } err = ConfigureAdvertisingData(); SuccessOrExit(err); mFlags.Clear(Flags::kRestartAdvertising); if (mFlags.Has(Flags::kFastAdvertisingEnabled)) { APP_BLE_Adv_Request(APP_BLE_FAST_ADV); } else { APP_BLE_Adv_Request(APP_BLE_LP_ADV); } // Flag updated asynchronously by BLE host callback mFlags.Set(Flags::kAdvertising); if (mFlags.Has(Flags::kFastAdvertisingEnabled)) { StartBleAdvTimeoutTimer(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME); } exit: return err; } CHIP_ERROR BLEManagerImpl::StopAdvertising(void) { CHIP_ERROR err; APP_BLE_Adv_Cancel(); // ST ble api CancelBleAdvTimeoutTimer(); // Transition to the not Advertising state... if (mFlags.Has(Flags::kAdvertising)) { mFlags.Clear(Flags::kAdvertising); mFlags.Set(Flags::kFastAdvertisingEnabled); ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped"); // Post a CHIPoBLEAdvertisingChange(Stopped) event. ChipDeviceEvent advChange; advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange; advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped; err = PlatformMgr().PostEvent(&advChange); } return err; } uint16_t BLEManagerImpl::_NumConnections(void) { uint16_t numCons = 0; for (uint16_t i = 0; i < kMaxConnections; i++) { if (mSubscribedConIds[i] != BLE_CONNECTION_UNINITIALIZED) { numCons++; } } return numCons; } void BLEManagerImpl::DriveBLEState(intptr_t arg) { sInstance.DriveBLEState(); } void BLEManagerImpl::bleConnect(void) { CHIP_ERROR err; ChipLogProgress(DeviceLayer, "BLE GATT connection established "); mNumGAPCons++; mFlags.Set(Flags::kAdvertisingRefreshNeeded); ChipDeviceEvent connectEvent; connectEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished; err = PlatformMgr().PostEvent(&connectEvent); PlatformMgr().ScheduleWork(DriveBLEState, 0); } void BLEManagerImpl::bleDisconnect(uint16_t connid) { CHIP_ERROR err; ChipLogDetail(DeviceLayer, "BLE GATT connection closed (con %u)", connid); ; // Force a refresh of the advertising state. if (mNumGAPCons > 0) { mNumGAPCons--; } // If this was a CHIPoBLE connection, release the associated connection state record // and post an event to deliver a connection error to the CHIPoBLE layer. if (!BLEMgrImpl().IsSubscribed(connid)) { if (UnsetSubscribed(connid)) { ChipDeviceEvent event; event.Type = DeviceEventType::kCHIPoBLEConnectionError; event.CHIPoBLEConnectionError.ConId = connid; PlatformMgr().PostEventOrDie(&event); ChipLogDetail(DeviceLayer, "BLE unuset subscribed (con %u)", connid); } } mFlags.Set(Flags::kAdvertisingRefreshNeeded); ChipDeviceEvent disconnectEvent; disconnectEvent.Type = DeviceEventType::kCHIPoBLEConnectionClosed; err = PlatformMgr().PostEvent(&disconnectEvent); PlatformMgr().ScheduleWork(DriveBLEState, 0); } void BLEManagerImpl::HandleGAPConnect(void) { ChipLogProgress(DeviceLayer, "Gap connect"); sInstance.bleConnect(); } void BLEManagerImpl::HandleGAPDisconnect(uint16_t * connid) { ChipLogProgress(DeviceLayer, "Gap disconnect"); sInstance.bleDisconnect(gconnid); } void BLEManagerImpl::HandleRXCharWrite(BLE_Matter_RX * aMessage) { CHIP_ERROR err = CHIP_NO_ERROR; ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE Client RX characteristic (con %u, len %u)", aMessage->connid, aMessage->Length); // update connid gconnid = aMessage->connid; PacketBufferHandle buf = System::PacketBufferHandle::NewWithData(aMessage->Payload, aMessage->Length, 0, 0); VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY); // Post an event to the Chip queue to deliver the data into the Chip stack. { ChipDeviceEvent event; event.Type = DeviceEventType::kCHIPoBLEWriteReceived; event.CHIPoBLEWriteReceived.ConId = aMessage->connid; event.CHIPoBLEWriteReceived.Data = std::move(buf).UnsafeRelease(); err = PlatformMgr().PostEvent(&event); } exit: if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err)); // TODO: fail connection??? } } void BLEManagerImpl::HandleTXCharCCCDWrite(BLE_Matter_TXCharCCCD * aMessage) { CHIP_ERROR err = CHIP_NO_ERROR; bool notificationsEnabled; ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE TX characteristic CCCD (con %u, len %u)", aMessage->connid, 0); // Determine if the client is enabling or disabling notifications notificationsEnabled = (aMessage->notif != 0); // If the client has requested to enable notifications if (notificationsEnabled) { // Set subcription only the first time if (!BLEMgrImpl().IsSubscribed(aMessage->connid)) // conid { // Record that notifications have been enabled for this connection. err = BLEMgrImpl().SetSubscribed(aMessage->connid); VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR); SuccessOrExit(err); } } else { // If notifications had previously been enabled for this connection, record that they are no longer enabled BLEMgrImpl().UnsetSubscribed(aMessage->connid); } // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on // whether the client is enabling or disabling notifications { ChipDeviceEvent event; event.Type = (notificationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe; event.CHIPoBLESubscribe.ConId = aMessage->connid; err = PlatformMgr().PostEvent(&event); } ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", notificationsEnabled ? "subscribe" : "unsubscribe"); exit: if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err)); // TODO: fail connection??? } } void BLEManagerImpl::HandleAck(uint16_t * connid) { ChipDeviceEvent event; event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm; event.CHIPoBLEIndicateConfirm.ConId = gconnid; PlatformMgr().PostEventOrDie(&event); } CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId) { uint16_t freeIndex = kMaxConnections; for (uint16_t i = 0; i < kMaxConnections; i++) { if (mSubscribedConIds[i] == conId) { return CHIP_NO_ERROR; } else if (mSubscribedConIds[i] == BLE_CONNECTION_UNINITIALIZED && i < freeIndex) { freeIndex = i; } } if (freeIndex < kMaxConnections) { mSubscribedConIds[freeIndex] = conId; return CHIP_NO_ERROR; } else { return CHIP_ERROR_NO_MEMORY; } } bool BLEManagerImpl::UnsetSubscribed(uint16_t conId) { for (uint16_t i = 0; i < kMaxConnections; i++) { if (mSubscribedConIds[i] == conId) { mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED; return true; } } return false; } bool BLEManagerImpl::IsSubscribed(uint16_t conId) { if (conId != BLE_CONNECTION_UNINITIALIZED) { for (uint16_t i = 0; i < kMaxConnections; i++) { if (mSubscribedConIds[i] == conId) { return true; } } } return false; } void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer) { if (BLEMgrImpl().mFlags.Has(Flags::kFastAdvertisingEnabled)) { ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertisement"); BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); } } void BLEManagerImpl::CancelBleAdvTimeoutTimer(void) { if (xTimerStop(sbleAdvTimeoutTimer, 0) == pdFAIL) { ChipLogError(DeviceLayer, "Failed to stop BledAdv timeout timer"); } } void BLEManagerImpl::StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs) { if (xTimerIsTimerActive(sbleAdvTimeoutTimer)) { CancelBleAdvTimeoutTimer(); } // timer is not active, change its period to required value (== restart). // FreeRTOS- Block for a maximum of 100 ticks if the change period command // cannot immediately be sent to the timer command queue. if (xTimerChangePeriod(sbleAdvTimeoutTimer, pdMS_TO_TICKS(aTimeoutInMs), 100) != pdPASS) { ChipLogError(DeviceLayer, "Failed to start BledAdv timeout timer"); } } } // namespace Internal } // namespace DeviceLayer } // namespace chip