Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2020 Project CHIP Authors 4 : * Copyright (c) 2018 Nest Labs, Inc. 5 : * 6 : * Licensed under the Apache License, Version 2.0 (the "License"); 7 : * you may not use this file except in compliance with the License. 8 : * You may obtain a copy of the License at 9 : * 10 : * http://www.apache.org/licenses/LICENSE-2.0 11 : * 12 : * Unless required by applicable law or agreed to in writing, software 13 : * distributed under the License is distributed on an "AS IS" BASIS, 14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 : * See the License for the specific language governing permissions and 16 : * limitations under the License. 17 : */ 18 : 19 : /** 20 : * @file 21 : * Defines the public interface for the Device Layer PlatformManager object. 22 : */ 23 : 24 : #pragma once 25 : 26 : #include <platform/AttributeList.h> 27 : #include <platform/CHIPDeviceConfig.h> 28 : #include <platform/CHIPDeviceEvent.h> 29 : #include <system/PlatformEventSupport.h> 30 : #include <system/SystemLayer.h> 31 : 32 : namespace chip { 33 : 34 : namespace Dnssd { 35 : class DiscoveryImplPlatform; 36 : } 37 : 38 : namespace DeviceLayer { 39 : 40 : static constexpr size_t kMaxCalendarTypes = 12; 41 : 42 : class PlatformManagerImpl; 43 : class ConnectivityManagerImpl; 44 : class ConfigurationManagerImpl; 45 : class DeviceControlServer; 46 : class TraitManager; 47 : class ThreadStackManagerImpl; 48 : 49 : namespace Internal { 50 : class BLEManagerImpl; 51 : template <class> 52 : class GenericConfigurationManagerImpl; 53 : template <class> 54 : class GenericPlatformManagerImpl; 55 : template <class> 56 : class GenericPlatformManagerImpl_FreeRTOS; 57 : template <class> 58 : class GenericPlatformManagerImpl_POSIX; 59 : template <class> 60 : class GenericPlatformManagerImpl_Zephyr; 61 : template <class> 62 : class GenericConnectivityManagerImpl_Thread; 63 : template <class> 64 : class GenericThreadStackManagerImpl_OpenThread; 65 : template <class> 66 : class GenericThreadStackManagerImpl_OpenThread_LwIP; 67 : } // namespace Internal 68 : 69 : /** 70 : * Defines the delegate class of Platform Manager to notify platform updates. 71 : */ 72 : class PlatformManagerDelegate 73 : { 74 : public: 75 : virtual ~PlatformManagerDelegate() {} 76 : 77 : /** 78 : * @brief 79 : * Called by the current Node after completing a boot or reboot process. 80 : */ 81 : virtual void OnStartUp(uint32_t softwareVersion) {} 82 : 83 : /** 84 : * @brief 85 : * Called by the current Node prior to any orderly shutdown sequence on a 86 : * best-effort basis. 87 : */ 88 : virtual void OnShutDown() {} 89 : }; 90 : 91 : /** 92 : * Provides features for initializing and interacting with the chip network 93 : * stack on a chip-enabled device. 94 : */ 95 : class PlatformManager 96 : { 97 : using ImplClass = ::chip::DeviceLayer::PlatformManagerImpl; 98 : 99 : public: 100 : // ===== Members that define the public interface of the PlatformManager 101 : 102 : typedef void (*EventHandlerFunct)(const ChipDeviceEvent * event, intptr_t arg); 103 : 104 : /** 105 : * InitChipStack() initializes the PlatformManager. After calling that, a 106 : * consumer is allowed to call either StartEventLoopTask or RunEventLoop to 107 : * process pending work. Calling both is not allowed: it must be one or the 108 : * other. 109 : */ 110 : CHIP_ERROR InitChipStack(); 111 : 112 : CHIP_ERROR AddEventHandler(EventHandlerFunct handler, intptr_t arg = 0); 113 : void RemoveEventHandler(EventHandlerFunct handler, intptr_t arg = 0); 114 : void SetDelegate(PlatformManagerDelegate * delegate) { mDelegate = delegate; } 115 : PlatformManagerDelegate * GetDelegate() const { return mDelegate; } 116 : 117 : /** 118 : * Should be called after initializing all layers of the Matter stack to 119 : * run all needed post-startup actions. 120 : */ 121 : void HandleServerStarted(); 122 : 123 : /** 124 : * Should be called before shutting down the Matter stack or restarting the 125 : * application to run all needed pre-shutdown actions. 126 : */ 127 : void HandleServerShuttingDown(); 128 : 129 : /** 130 : * ScheduleWork can be called after InitChipStack has been called. Calls 131 : * that happen before either StartEventLoopTask or RunEventLoop will queue 132 : * the work up but that work will NOT run until one of those functions is 133 : * called. 134 : * 135 : * ScheduleWork can be called safely on any thread without locking the 136 : * stack. When called from a thread that is not doing the stack work item 137 : * processing, the callback function may be called (on the work item 138 : * processing thread) before ScheduleWork returns. 139 : */ 140 : CHIP_ERROR ScheduleWork(AsyncWorkFunct workFunct, intptr_t arg = 0); 141 : 142 : /** 143 : * Process work items until StopEventLoopTask is called. RunEventLoop will 144 : * not return until work item processing is stopped. Once it returns it 145 : * guarantees that no more work items will be processed unless there's 146 : * another call to RunEventLoop. 147 : * 148 : * Consumers that call RunEventLoop must not call StartEventLoopTask. 149 : * 150 : * Consumers that call RunEventLoop must ensure that RunEventLoop returns 151 : * before calling Shutdown. 152 : */ 153 : void RunEventLoop(); 154 : 155 : /** 156 : * Process work items until StopEventLoopTask is called. 157 : * 158 : * StartEventLoopTask processes items asynchronously. It can return before 159 : * any items are processed, or after some items have been processed, or 160 : * while an item is being processed, or even after StopEventLoopTask() has 161 : * been called (e.g. if ScheduleWork() was called before StartEventLoopTask 162 : * was called, with a work item that calls StopEventLoopTask). 163 : * 164 : * Consumers that call StartEventLoopTask must not call RunEventLoop. 165 : * 166 : * Consumers that call StartEventLoopTask must ensure that they call 167 : * StopEventLoopTask before calling Shutdown. 168 : */ 169 : CHIP_ERROR StartEventLoopTask(); 170 : 171 : /** 172 : * Stop processing of work items by the event loop. 173 : * 174 : * If called from outside work item processing, StopEventLoopTask guarantees 175 : * that any currently-executing work item completes execution and no more 176 : * work items will run after StopEventLoopTask returns. This is generally 177 : * how StopEventLoopTask is used in conjunction with StartEventLoopTask. 178 : * 179 : * If called from inside work item processing, StopEventLoopTask makes no 180 : * guarantees about exactly when work item processing will stop. What it 181 : * does guarantee is that if it is used this way in conjunction with 182 : * RunEventLoop then all work item processing will stop before RunEventLoop 183 : * returns. 184 : */ 185 : CHIP_ERROR StopEventLoopTask(); 186 : 187 : void LockChipStack(); 188 : bool TryLockChipStack(); 189 : void UnlockChipStack(); 190 : void Shutdown(); 191 : 192 : #if CHIP_STACK_LOCK_TRACKING_ENABLED 193 : bool IsChipStackLockedByCurrentThread() const; 194 : #endif 195 : 196 : /* 197 : * PostEvent can be called safely on any thread without locking the stack. 198 : * When called from a thread that is not doing the stack work item 199 : * processing, the event might get dispatched (on the work item processing 200 : * thread) before PostEvent returns. 201 : */ 202 : [[nodiscard]] CHIP_ERROR PostEvent(const ChipDeviceEvent * event); 203 : void PostEventOrDie(const ChipDeviceEvent * event); 204 : 205 : /** 206 : * Generally this function has the same semantics as ScheduleWork 207 : * except it applies to background processing. 208 : * 209 : * Delegates to PostBackgroundEvent (which will delegate to PostEvent if 210 : * CHIP_DEVICE_CONFIG_ENABLE_BG_EVENT_PROCESSING is not true). 211 : */ 212 : CHIP_ERROR ScheduleBackgroundWork(AsyncWorkFunct workFunct, intptr_t arg = 0); 213 : 214 : /** 215 : * Generally this function has the same semantics as PostEvent 216 : * except it applies to background processing. 217 : * 218 : * If CHIP_DEVICE_CONFIG_ENABLE_BG_EVENT_PROCESSING is not true, will delegate 219 : * to PostEvent. 220 : * 221 : * Only accepts events of type kCallWorkFunct or kNoOp. 222 : * 223 : * Returns CHIP_ERROR_INVALID_ARGUMENT if the event type is not acceptable. 224 : * Returns CHIP_ERROR_NO_MEMORY if resources are exhausted. 225 : */ 226 : CHIP_ERROR PostBackgroundEvent(const ChipDeviceEvent * event); 227 : 228 : /** 229 : * Generally this function has the same semantics as RunEventLoop 230 : * except it applies to background processing. 231 : */ 232 : void RunBackgroundEventLoop(); 233 : 234 : /** 235 : * Generally this function has the same semantics as StartEventLoopTask 236 : * except it applies to background processing. 237 : */ 238 : CHIP_ERROR StartBackgroundEventLoopTask(); 239 : 240 : /** 241 : * Generally this function has the same semantics as StopEventLoopTask 242 : * except it applies to background processing. 243 : */ 244 : CHIP_ERROR StopBackgroundEventLoopTask(); 245 : 246 : private: 247 : bool mInitialized = false; 248 : PlatformManagerDelegate * mDelegate = nullptr; 249 : 250 : // ===== Members for internal use by the following friends. 251 : 252 : friend class PlatformManagerImpl; 253 : friend class ConnectivityManagerImpl; 254 : friend class ConfigurationManagerImpl; 255 : friend class DeviceControlServer; 256 : friend class Dnssd::DiscoveryImplPlatform; 257 : friend class FailSafeContext; 258 : friend class TraitManager; 259 : friend class ThreadStackManagerImpl; 260 : friend class Internal::BLEManagerImpl; 261 : template <class> 262 : friend class Internal::GenericPlatformManagerImpl; 263 : template <class> 264 : friend class Internal::GenericPlatformManagerImpl_FreeRTOS; 265 : template <class> 266 : friend class Internal::GenericPlatformManagerImpl_POSIX; 267 : template <class> 268 : friend class Internal::GenericPlatformManagerImpl_Zephyr; 269 : template <class> 270 : friend class Internal::GenericConnectivityManagerImpl_Thread; 271 : template <class> 272 : friend class Internal::GenericThreadStackManagerImpl_OpenThread; 273 : template <class> 274 : friend class Internal::GenericThreadStackManagerImpl_OpenThread_LwIP; 275 : template <class> 276 : friend class Internal::GenericConfigurationManagerImpl; 277 : friend class System::PlatformEventing; 278 : 279 : void DispatchEvent(const ChipDeviceEvent * event); 280 : CHIP_ERROR StartChipTimer(System::Clock::Timeout duration); 281 : 282 : protected: 283 : // Construction/destruction limited to subclasses. 284 : PlatformManager() = default; 285 : ~PlatformManager() = default; 286 : 287 : // No copy, move or assignment. 288 : PlatformManager(const PlatformManager &) = delete; 289 : PlatformManager(const PlatformManager &&) = delete; 290 : PlatformManager & operator=(const PlatformManager &) = delete; 291 : }; 292 : 293 : /** 294 : * Returns the public interface of the PlatformManager singleton object. 295 : * 296 : * chip applications should use this to access features of the PlatformManager object 297 : * that are common to all platforms. 298 : */ 299 : extern PlatformManager & PlatformMgr(); 300 : 301 : /** 302 : * Returns the platform-specific implementation of the PlatformManager singleton object. 303 : * 304 : * chip applications can use this to gain access to features of the PlatformManager 305 : * that are specific to the selected platform. 306 : */ 307 : extern PlatformManagerImpl & PlatformMgrImpl(); 308 : 309 : /** 310 : * @brief 311 : * RAII locking for PlatformManager to simplify management of 312 : * LockChipStack()/UnlockChipStack calls. 313 : */ 314 : class StackLock 315 : { 316 : public: 317 : StackLock() { PlatformMgr().LockChipStack(); } 318 : 319 : ~StackLock() { PlatformMgr().UnlockChipStack(); } 320 : }; 321 : 322 : /** 323 : * @brief 324 : * RAII unlocking for PlatformManager to simplify management of 325 : * LockChipStack()/UnlockChipStack calls. 326 : */ 327 : class StackUnlock 328 : { 329 : public: 330 : StackUnlock() { PlatformMgr().UnlockChipStack(); } 331 : ~StackUnlock() { PlatformMgr().LockChipStack(); } 332 : }; 333 : 334 : } // namespace DeviceLayer 335 : } // namespace chip 336 : 337 : /* Include a header file containing the implementation of the ConfigurationManager 338 : * object for the selected platform. 339 : */ 340 : #ifdef EXTERNAL_PLATFORMMANAGERIMPL_HEADER 341 : #include EXTERNAL_PLATFORMMANAGERIMPL_HEADER 342 : #elif defined(CHIP_DEVICE_LAYER_TARGET) 343 : #define PLATFORMMANAGERIMPL_HEADER <platform/CHIP_DEVICE_LAYER_TARGET/PlatformManagerImpl.h> 344 : #include PLATFORMMANAGERIMPL_HEADER 345 : #endif // defined(CHIP_DEVICE_LAYER_TARGET) 346 : 347 : namespace chip { 348 : namespace DeviceLayer { 349 : 350 : #if CHIP_STACK_LOCK_TRACKING_ENABLED 351 : inline bool PlatformManager::IsChipStackLockedByCurrentThread() const 352 : { 353 : return static_cast<const ImplClass *>(this)->_IsChipStackLockedByCurrentThread(); 354 : } 355 : #endif 356 : 357 0 : inline CHIP_ERROR PlatformManager::InitChipStack() 358 : { 359 : // NOTE: this is NOT thread safe and cannot be as the chip stack lock is prepared by 360 : // InitChipStack itself on many platforms. 361 : // 362 : // In the future, this could be moved into specific platform code (where it can 363 : // be made thread safe). In general however, init twice 364 : // is likely a logic error and we may want to avoid that path anyway. Likely to 365 : // be done once code stabilizes a bit more. 366 0 : if (mInitialized) 367 : { 368 0 : return CHIP_NO_ERROR; 369 : } 370 : 371 0 : CHIP_ERROR err = static_cast<ImplClass *>(this)->_InitChipStack(); 372 0 : mInitialized = (err == CHIP_NO_ERROR); 373 0 : return err; 374 : } 375 : 376 16 : inline CHIP_ERROR PlatformManager::AddEventHandler(EventHandlerFunct handler, intptr_t arg) 377 : { 378 16 : return static_cast<ImplClass *>(this)->_AddEventHandler(handler, arg); 379 : } 380 : 381 8 : inline void PlatformManager::RemoveEventHandler(EventHandlerFunct handler, intptr_t arg) 382 : { 383 8 : static_cast<ImplClass *>(this)->_RemoveEventHandler(handler, arg); 384 8 : } 385 : 386 1 : inline void PlatformManager::HandleServerStarted() 387 : { 388 1 : static_cast<ImplClass *>(this)->_HandleServerStarted(); 389 1 : } 390 : 391 0 : inline void PlatformManager::HandleServerShuttingDown() 392 : { 393 0 : static_cast<ImplClass *>(this)->_HandleServerShuttingDown(); 394 0 : } 395 : 396 0 : inline CHIP_ERROR PlatformManager::ScheduleWork(AsyncWorkFunct workFunct, intptr_t arg) 397 : { 398 0 : return static_cast<ImplClass *>(this)->_ScheduleWork(workFunct, arg); 399 : } 400 : 401 : inline void PlatformManager::RunEventLoop() 402 : { 403 : static_cast<ImplClass *>(this)->_RunEventLoop(); 404 : } 405 : 406 : /** 407 : * @brief 408 : * Starts the stack on its own task with an associated event queue 409 : * to dispatch and handle events posted to that task. 410 : * 411 : * This is thread-safe. 412 : * This is *NOT SAFE* to call from within the CHIP event loop since it can grab the stack lock. 413 : */ 414 0 : inline CHIP_ERROR PlatformManager::StartEventLoopTask() 415 : { 416 0 : return static_cast<ImplClass *>(this)->_StartEventLoopTask(); 417 : } 418 : 419 : /** 420 : * @brief 421 : * This will trigger the event loop to exit and block till it has exited the loop. 422 : * This prevents the processing of any further events in the queue. 423 : * 424 : * Additionally, this stops the CHIP task if the following criteria are met: 425 : * 1. One was created earlier through a call to StartEventLoopTask 426 : * 2. This call isn't being made from that task. 427 : * 428 : * This is safe to call from any task. 429 : * This is safe to call from within the CHIP event loop. 430 : * 431 : */ 432 : inline CHIP_ERROR PlatformManager::StopEventLoopTask() 433 : { 434 : return static_cast<ImplClass *>(this)->_StopEventLoopTask(); 435 : } 436 : 437 : /** 438 : * @brief 439 : * Shuts down and cleans up the main objects in the CHIP stack. 440 : * This DOES NOT stop the chip thread or event queue from running. 441 : * 442 : */ 443 0 : inline void PlatformManager::Shutdown() 444 : { 445 0 : static_cast<ImplClass *>(this)->_Shutdown(); 446 0 : mInitialized = false; 447 0 : } 448 : 449 : inline void PlatformManager::LockChipStack() 450 : { 451 : static_cast<ImplClass *>(this)->_LockChipStack(); 452 : } 453 : 454 : inline bool PlatformManager::TryLockChipStack() 455 : { 456 : return static_cast<ImplClass *>(this)->_TryLockChipStack(); 457 : } 458 : 459 : inline void PlatformManager::UnlockChipStack() 460 : { 461 : static_cast<ImplClass *>(this)->_UnlockChipStack(); 462 : } 463 : 464 1 : inline CHIP_ERROR PlatformManager::PostEvent(const ChipDeviceEvent * event) 465 : { 466 1 : return static_cast<ImplClass *>(this)->_PostEvent(event); 467 : } 468 : 469 1 : inline void PlatformManager::PostEventOrDie(const ChipDeviceEvent * event) 470 : { 471 1 : CHIP_ERROR status = static_cast<ImplClass *>(this)->_PostEvent(event); 472 1 : VerifyOrDieWithMsg(status == CHIP_NO_ERROR, DeviceLayer, "Failed to post event %d: %" CHIP_ERROR_FORMAT, 473 : static_cast<int>(event->Type), status.Format()); 474 1 : } 475 : 476 7 : inline CHIP_ERROR PlatformManager::ScheduleBackgroundWork(AsyncWorkFunct workFunct, intptr_t arg) 477 : { 478 7 : return static_cast<ImplClass *>(this)->_ScheduleBackgroundWork(workFunct, arg); 479 : } 480 : 481 : inline CHIP_ERROR PlatformManager::PostBackgroundEvent(const ChipDeviceEvent * event) 482 : { 483 : return static_cast<ImplClass *>(this)->_PostBackgroundEvent(event); 484 : } 485 : 486 : inline void PlatformManager::RunBackgroundEventLoop() 487 : { 488 : static_cast<ImplClass *>(this)->_RunBackgroundEventLoop(); 489 : } 490 : 491 : inline CHIP_ERROR PlatformManager::StartBackgroundEventLoopTask() 492 : { 493 : return static_cast<ImplClass *>(this)->_StartBackgroundEventLoopTask(); 494 : } 495 : 496 : inline CHIP_ERROR PlatformManager::StopBackgroundEventLoopTask() 497 : { 498 : return static_cast<ImplClass *>(this)->_StopBackgroundEventLoopTask(); 499 : } 500 : 501 : inline void PlatformManager::DispatchEvent(const ChipDeviceEvent * event) 502 : { 503 : static_cast<ImplClass *>(this)->_DispatchEvent(event); 504 : } 505 : 506 : inline CHIP_ERROR PlatformManager::StartChipTimer(System::Clock::Timeout duration) 507 : { 508 : return static_cast<ImplClass *>(this)->_StartChipTimer(duration); 509 : } 510 : 511 : } // namespace DeviceLayer 512 : } // namespace chip