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