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_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 : virtual ~PlatformManagerDelegate() {}
78 :
79 : /**
80 : * @brief
81 : * Called by the current Node after completing a boot or reboot process.
82 : */
83 : 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 : 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 : void SetDelegate(PlatformManagerDelegate * delegate) { mDelegate = delegate; }
117 : 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::BLEManagerImpl;
263 : template <class>
264 : friend class Internal::GenericPlatformManagerImpl;
265 : template <class>
266 : friend class Internal::GenericPlatformManagerImpl_CMSISOS;
267 : template <class>
268 : friend class Internal::GenericPlatformManagerImpl_FreeRTOS;
269 : template <class>
270 : friend class Internal::GenericPlatformManagerImpl_POSIX;
271 : template <class>
272 : friend class Internal::GenericPlatformManagerImpl_Zephyr;
273 : template <class>
274 : friend class Internal::GenericConnectivityManagerImpl_Thread;
275 : template <class>
276 : friend class Internal::GenericThreadStackManagerImpl_OpenThread;
277 : template <class>
278 : friend class Internal::GenericThreadStackManagerImpl_OpenThread_LwIP;
279 : template <class>
280 : friend class Internal::GenericConfigurationManagerImpl;
281 : friend class System::PlatformEventing;
282 :
283 : void DispatchEvent(const ChipDeviceEvent * event);
284 : CHIP_ERROR StartChipTimer(System::Clock::Timeout duration);
285 :
286 : protected:
287 : // Construction/destruction limited to subclasses.
288 : PlatformManager() = default;
289 : ~PlatformManager() = default;
290 :
291 : // No copy, move or assignment.
292 : PlatformManager(const PlatformManager &) = delete;
293 : PlatformManager(const PlatformManager &&) = delete;
294 : PlatformManager & operator=(const PlatformManager &) = delete;
295 : };
296 :
297 : /**
298 : * Returns the public interface of the PlatformManager singleton object.
299 : *
300 : * chip applications should use this to access features of the PlatformManager object
301 : * that are common to all platforms.
302 : */
303 : extern PlatformManager & PlatformMgr();
304 :
305 : /**
306 : * Returns the platform-specific implementation of the PlatformManager singleton object.
307 : *
308 : * chip applications can use this to gain access to features of the PlatformManager
309 : * that are specific to the selected platform.
310 : */
311 : extern PlatformManagerImpl & PlatformMgrImpl();
312 :
313 : /**
314 : * @brief
315 : * RAII locking for PlatformManager to simplify management of
316 : * LockChipStack()/UnlockChipStack calls.
317 : */
318 : class StackLock
319 : {
320 : public:
321 : StackLock() { PlatformMgr().LockChipStack(); }
322 :
323 : ~StackLock() { PlatformMgr().UnlockChipStack(); }
324 : };
325 :
326 : /**
327 : * @brief
328 : * RAII unlocking for PlatformManager to simplify management of
329 : * LockChipStack()/UnlockChipStack calls.
330 : */
331 : class StackUnlock
332 : {
333 : public:
334 : StackUnlock() { PlatformMgr().UnlockChipStack(); }
335 : ~StackUnlock() { PlatformMgr().LockChipStack(); }
336 : };
337 :
338 : } // namespace DeviceLayer
339 : } // namespace chip
340 :
341 : /* Include a header file containing the implementation of the ConfigurationManager
342 : * object for the selected platform.
343 : */
344 : #ifdef EXTERNAL_PLATFORMMANAGERIMPL_HEADER
345 : #include EXTERNAL_PLATFORMMANAGERIMPL_HEADER
346 : #elif defined(CHIP_DEVICE_LAYER_TARGET)
347 : #define PLATFORMMANAGERIMPL_HEADER <platform/CHIP_DEVICE_LAYER_TARGET/PlatformManagerImpl.h>
348 : #include PLATFORMMANAGERIMPL_HEADER
349 : #endif // defined(CHIP_DEVICE_LAYER_TARGET)
350 :
351 : namespace chip {
352 : namespace DeviceLayer {
353 :
354 : #if CHIP_STACK_LOCK_TRACKING_ENABLED
355 : inline bool PlatformManager::IsChipStackLockedByCurrentThread() const
356 : {
357 : return static_cast<const ImplClass *>(this)->_IsChipStackLockedByCurrentThread();
358 : }
359 : #endif
360 :
361 0 : inline CHIP_ERROR PlatformManager::InitChipStack()
362 : {
363 : // NOTE: this is NOT thread safe and cannot be as the chip stack lock is prepared by
364 : // InitChipStack itself on many platforms.
365 : //
366 : // In the future, this could be moved into specific platform code (where it can
367 : // be made thread safe). In general however, init twice
368 : // is likely a logic error and we may want to avoid that path anyway. Likely to
369 : // be done once code stabilizes a bit more.
370 0 : if (mInitialized)
371 : {
372 0 : return CHIP_NO_ERROR;
373 : }
374 :
375 0 : CHIP_ERROR err = static_cast<ImplClass *>(this)->_InitChipStack();
376 0 : mInitialized = (err == CHIP_NO_ERROR);
377 0 : return err;
378 : }
379 :
380 13 : inline CHIP_ERROR PlatformManager::AddEventHandler(EventHandlerFunct handler, intptr_t arg)
381 : {
382 13 : return static_cast<ImplClass *>(this)->_AddEventHandler(handler, arg);
383 : }
384 :
385 6 : inline void PlatformManager::RemoveEventHandler(EventHandlerFunct handler, intptr_t arg)
386 : {
387 6 : static_cast<ImplClass *>(this)->_RemoveEventHandler(handler, arg);
388 6 : }
389 :
390 1 : inline void PlatformManager::HandleServerStarted()
391 : {
392 1 : static_cast<ImplClass *>(this)->_HandleServerStarted();
393 1 : }
394 :
395 0 : inline void PlatformManager::HandleServerShuttingDown()
396 : {
397 0 : static_cast<ImplClass *>(this)->_HandleServerShuttingDown();
398 0 : }
399 :
400 0 : inline CHIP_ERROR PlatformManager::ScheduleWork(AsyncWorkFunct workFunct, intptr_t arg)
401 : {
402 0 : return static_cast<ImplClass *>(this)->_ScheduleWork(workFunct, arg);
403 : }
404 :
405 : inline void PlatformManager::RunEventLoop()
406 : {
407 : static_cast<ImplClass *>(this)->_RunEventLoop();
408 : }
409 :
410 : /**
411 : * @brief
412 : * Starts the stack on its own task with an associated event queue
413 : * to dispatch and handle events posted to that task.
414 : *
415 : * This is thread-safe.
416 : * This is *NOT SAFE* to call from within the CHIP event loop since it can grab the stack lock.
417 : */
418 0 : inline CHIP_ERROR PlatformManager::StartEventLoopTask()
419 : {
420 0 : return static_cast<ImplClass *>(this)->_StartEventLoopTask();
421 : }
422 :
423 : /**
424 : * @brief
425 : * This will trigger the event loop to exit and block till it has exited the loop.
426 : * This prevents the processing of any further events in the queue.
427 : *
428 : * Additionally, this stops the CHIP task if the following criteria are met:
429 : * 1. One was created earlier through a call to StartEventLoopTask
430 : * 2. This call isn't being made from that task.
431 : *
432 : * This is safe to call from any task.
433 : * This is safe to call from within the CHIP event loop.
434 : *
435 : */
436 : inline CHIP_ERROR PlatformManager::StopEventLoopTask()
437 : {
438 : return static_cast<ImplClass *>(this)->_StopEventLoopTask();
439 : }
440 :
441 : /**
442 : * @brief
443 : * Shuts down and cleans up the main objects in the CHIP stack.
444 : * This DOES NOT stop the chip thread or event queue from running.
445 : *
446 : */
447 0 : inline void PlatformManager::Shutdown()
448 : {
449 0 : static_cast<ImplClass *>(this)->_Shutdown();
450 0 : mInitialized = false;
451 0 : }
452 :
453 : inline void PlatformManager::LockChipStack()
454 : {
455 : static_cast<ImplClass *>(this)->_LockChipStack();
456 : }
457 :
458 : inline bool PlatformManager::TryLockChipStack()
459 : {
460 : return static_cast<ImplClass *>(this)->_TryLockChipStack();
461 : }
462 :
463 : inline void PlatformManager::UnlockChipStack()
464 : {
465 : static_cast<ImplClass *>(this)->_UnlockChipStack();
466 : }
467 :
468 108 : inline CHIP_ERROR PlatformManager::PostEvent(const ChipDeviceEvent * event)
469 : {
470 108 : return static_cast<ImplClass *>(this)->_PostEvent(event);
471 : }
472 :
473 3 : inline void PlatformManager::PostEventOrDie(const ChipDeviceEvent * event)
474 : {
475 3 : CHIP_ERROR status = static_cast<ImplClass *>(this)->_PostEvent(event);
476 3 : VerifyOrDieWithMsg(status == CHIP_NO_ERROR, DeviceLayer, "Failed to post event %d: %" CHIP_ERROR_FORMAT,
477 : static_cast<int>(event->Type), status.Format());
478 3 : }
479 :
480 7 : inline CHIP_ERROR PlatformManager::ScheduleBackgroundWork(AsyncWorkFunct workFunct, intptr_t arg)
481 : {
482 7 : return static_cast<ImplClass *>(this)->_ScheduleBackgroundWork(workFunct, arg);
483 : }
484 :
485 : inline CHIP_ERROR PlatformManager::PostBackgroundEvent(const ChipDeviceEvent * event)
486 : {
487 : return static_cast<ImplClass *>(this)->_PostBackgroundEvent(event);
488 : }
489 :
490 : inline void PlatformManager::RunBackgroundEventLoop()
491 : {
492 : static_cast<ImplClass *>(this)->_RunBackgroundEventLoop();
493 : }
494 :
495 : inline CHIP_ERROR PlatformManager::StartBackgroundEventLoopTask()
496 : {
497 : return static_cast<ImplClass *>(this)->_StartBackgroundEventLoopTask();
498 : }
499 :
500 : inline CHIP_ERROR PlatformManager::StopBackgroundEventLoopTask()
501 : {
502 : return static_cast<ImplClass *>(this)->_StopBackgroundEventLoopTask();
503 : }
504 :
505 : inline void PlatformManager::DispatchEvent(const ChipDeviceEvent * event)
506 : {
507 : static_cast<ImplClass *>(this)->_DispatchEvent(event);
508 : }
509 :
510 : inline CHIP_ERROR PlatformManager::StartChipTimer(System::Clock::Timeout duration)
511 : {
512 : return static_cast<ImplClass *>(this)->_StartChipTimer(duration);
513 : }
514 :
515 : } // namespace DeviceLayer
516 : } // namespace chip
|