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