/src/openweave-core/src/system/SystemLayer.cpp
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * Copyright (c) 2016-2017 Nest Labs, Inc. |
4 | | * All rights reserved. |
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 | | * This file contains definitions of the nl::Weave::System::Layer |
22 | | * class methods and related data and functions. |
23 | | */ |
24 | | |
25 | | // Include module header |
26 | | #include <SystemLayer/SystemLayer.h> |
27 | | |
28 | | // Include common private header |
29 | | #include "SystemLayerPrivate.h" |
30 | | |
31 | | // Include local headers |
32 | | #include <SystemLayer/SystemClock.h> |
33 | | #include <SystemLayer/SystemTimer.h> |
34 | | |
35 | | // Include additional Weave headers |
36 | | #include <Weave/Support/logging/WeaveLogging.h> |
37 | | |
38 | | #include <Weave/Support/NLDLLUtil.h> |
39 | | #include <Weave/Support/CodeUtils.h> |
40 | | |
41 | | // Include system and language headers |
42 | | #include <stddef.h> |
43 | | |
44 | | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
45 | | #include <unistd.h> |
46 | | #include <fcntl.h> |
47 | | #include <errno.h> |
48 | | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
49 | | |
50 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
51 | | #if !WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS |
52 | | #include <lwip/err.h> |
53 | | #include <lwip/sys.h> |
54 | | #endif // !WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS |
55 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
56 | | |
57 | | #if WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
58 | | #include <pthread.h> |
59 | | |
60 | | // Choose an approximation of PTHREAD_NULL if pthread.h doesn't define one. |
61 | | #ifndef PTHREAD_NULL |
62 | | #define PTHREAD_NULL 0 |
63 | | #endif // PTHREAD_NULL |
64 | | #endif // WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
65 | | |
66 | | namespace nl { |
67 | | namespace Weave { |
68 | | namespace System { |
69 | | |
70 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
71 | | bool LwIPEventHandlerDelegate::IsInitialized() const |
72 | | { |
73 | | return this->mFunction != NULL; |
74 | | } |
75 | | |
76 | | void LwIPEventHandlerDelegate::Init(LwIPEventHandlerFunction aFunction) |
77 | | { |
78 | | this->mFunction = aFunction; |
79 | | this->mNextDelegate = NULL; |
80 | | } |
81 | | |
82 | | void LwIPEventHandlerDelegate::Prepend(const LwIPEventHandlerDelegate*& aDelegateList) |
83 | | { |
84 | | this->mNextDelegate = aDelegateList; |
85 | | aDelegateList = this; |
86 | | } |
87 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
88 | | |
89 | | Layer::Layer() |
90 | 10 | : mLayerState(kLayerState_NotInitialized), |
91 | 10 | mContext(NULL), mPlatformData(NULL) |
92 | 10 | { |
93 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
94 | | if (!sSystemEventHandlerDelegate.IsInitialized()) |
95 | | sSystemEventHandlerDelegate.Init(HandleSystemLayerEvent); |
96 | | |
97 | | this->mEventDelegateList = NULL; |
98 | | this->mTimerList = NULL; |
99 | | this->mTimerComplete = false; |
100 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
101 | | |
102 | 10 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
103 | 10 | this->mWakePipeIn = 0; |
104 | 10 | this->mWakePipeOut = 0; |
105 | | |
106 | 10 | #if WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
107 | 10 | this->mHandleSelectThread = PTHREAD_NULL; |
108 | 10 | #endif // WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
109 | 10 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
110 | 10 | } |
111 | | |
112 | | Error Layer::Init(void* aContext) |
113 | 0 | { |
114 | 0 | Error lReturn; |
115 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
116 | 0 | int lPipeFDs[2]; |
117 | 0 | int lOSReturn, lFlags; |
118 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
119 | |
|
120 | 0 | RegisterSystemLayerErrorFormatter(); |
121 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
122 | 0 | RegisterPOSIXErrorFormatter(); |
123 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
124 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
125 | | RegisterLwIPErrorFormatter(); |
126 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
127 | |
|
128 | 0 | if (this->mLayerState != kLayerState_NotInitialized) |
129 | 0 | return WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE; |
130 | | |
131 | 0 | lReturn = Platform::Layer::WillInit(*this, aContext); |
132 | 0 | SuccessOrExit(lReturn); |
133 | | |
134 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
135 | | this->AddEventHandlerDelegate(sSystemEventHandlerDelegate); |
136 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
137 | | |
138 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
139 | | // Create a Unix pipe to allow an arbitrary thread to wake the thread in the select loop. |
140 | 0 | lOSReturn = ::pipe(lPipeFDs); |
141 | 0 | VerifyOrExit(lOSReturn == 0, lReturn = nl::Weave::System::MapErrorPOSIX(errno)); |
142 | | |
143 | 0 | this->mWakePipeIn = lPipeFDs[0]; |
144 | 0 | this->mWakePipeOut = lPipeFDs[1]; |
145 | | |
146 | | // Enable non-blocking mode for both ends of the pipe. |
147 | 0 | lFlags = ::fcntl(this->mWakePipeIn, F_GETFL, 0); |
148 | 0 | lOSReturn = ::fcntl(this->mWakePipeIn, F_SETFL, lFlags | O_NONBLOCK); |
149 | 0 | VerifyOrExit(lOSReturn == 0, lReturn = nl::Weave::System::MapErrorPOSIX(errno)); |
150 | | |
151 | 0 | lFlags = ::fcntl(this->mWakePipeOut, F_GETFL, 0); |
152 | 0 | lOSReturn = ::fcntl(this->mWakePipeOut, F_SETFL, lFlags | O_NONBLOCK); |
153 | 0 | VerifyOrExit(lOSReturn == 0, lReturn = nl::Weave::System::MapErrorPOSIX(errno)); |
154 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
155 | | |
156 | 0 | this->mLayerState = kLayerState_Initialized; |
157 | 0 | this->mContext = aContext; |
158 | |
|
159 | 0 | exit: |
160 | 0 | Platform::Layer::DidInit(*this, aContext, lReturn); |
161 | 0 | return lReturn; |
162 | 0 | } |
163 | | |
164 | | Error Layer::Shutdown() |
165 | 0 | { |
166 | 0 | Error lReturn; |
167 | 0 | void* lContext; |
168 | |
|
169 | 0 | if (this->mLayerState == kLayerState_NotInitialized) |
170 | 0 | return WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE; |
171 | | |
172 | 0 | lContext = this->mContext; |
173 | 0 | lReturn = Platform::Layer::WillShutdown(*this, lContext); |
174 | 0 | SuccessOrExit(lReturn); |
175 | | |
176 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
177 | 0 | if (this->mWakePipeOut != -1) |
178 | 0 | { |
179 | 0 | ::close(this->mWakePipeOut); |
180 | 0 | this->mWakePipeOut = -1; |
181 | 0 | this->mWakePipeIn = -1; |
182 | 0 | } |
183 | 0 | #endif |
184 | |
|
185 | 0 | for (size_t i = 0; i < Timer::sPool.Size(); ++i) |
186 | 0 | { |
187 | 0 | Timer* lTimer = Timer::sPool.Get(*this, i); |
188 | |
|
189 | 0 | if (lTimer != NULL) |
190 | 0 | { |
191 | 0 | lTimer->Cancel(); |
192 | 0 | } |
193 | 0 | } |
194 | |
|
195 | 0 | this->mContext = NULL; |
196 | 0 | this->mLayerState = kLayerState_NotInitialized; |
197 | |
|
198 | 0 | exit: |
199 | 0 | Platform::Layer::DidShutdown(*this, lContext, lReturn); |
200 | 0 | return lReturn; |
201 | 0 | } |
202 | | |
203 | | /** |
204 | | * This returns any client-specific platform data assigned to the instance, if it has been previously set. |
205 | | * |
206 | | * @return Client-specific platform data, if is has been previously set; otherwise, NULL. |
207 | | */ |
208 | | void* Layer::GetPlatformData() const |
209 | 0 | { |
210 | 0 | return this->mPlatformData; |
211 | 0 | } |
212 | | |
213 | | /** |
214 | | * This sets the specified client-specific platform data to the |
215 | | * instance for later retrieval by the client platform. |
216 | | * |
217 | | * @param[in] aPlatformData The client-specific platform data to set. |
218 | | * |
219 | | */ |
220 | | void Layer::SetPlatformData(void* aPlatformData) |
221 | 0 | { |
222 | 0 | this->mPlatformData = aPlatformData; |
223 | 0 | } |
224 | | |
225 | | Error Layer::NewTimer(Timer*& aTimerPtr) |
226 | 0 | { |
227 | 0 | Timer* lTimer = NULL; |
228 | |
|
229 | 0 | if (this->State() != kLayerState_Initialized) |
230 | 0 | return WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE; |
231 | | |
232 | 0 | lTimer = Timer::sPool.TryCreate(*this); |
233 | 0 | aTimerPtr = lTimer; |
234 | |
|
235 | 0 | if (lTimer == NULL) |
236 | 0 | { |
237 | 0 | WeaveLogError(WeaveSystemLayer, "Timer pool EMPTY"); |
238 | 0 | return WEAVE_SYSTEM_ERROR_NO_MEMORY; |
239 | 0 | } |
240 | | |
241 | 0 | return WEAVE_SYSTEM_NO_ERROR; |
242 | 0 | } |
243 | | |
244 | | /** |
245 | | * @brief |
246 | | * This method starts a one-shot timer. |
247 | | * |
248 | | * @note |
249 | | * Only a single timer is allowed to be started with the same @a aComplete and @a aAppState |
250 | | * arguments. If called with @a aComplete and @a aAppState identical to an existing timer, |
251 | | * the currently-running timer will first be cancelled. |
252 | | * |
253 | | * @param[in] aMilliseconds Expiration time in milliseconds. |
254 | | * @param[in] aComplete A pointer to the function called when timer expires. |
255 | | * @param[in] aAppState A pointer to the application state object used when timer expires. |
256 | | * |
257 | | * @return WEAVE_SYSTEM_NO_ERROR On success. |
258 | | * @return WEAVE_SYSTEM_ERROR_NO_MEMORY If a timer cannot be allocated. |
259 | | * @return Other Value indicating timer failed to start. |
260 | | * |
261 | | */ |
262 | | Error Layer::StartTimer(uint32_t aMilliseconds, TimerCompleteFunct aComplete, void* aAppState) |
263 | 0 | { |
264 | 0 | Error lReturn; |
265 | 0 | Timer* lTimer; |
266 | |
|
267 | 0 | this->CancelTimer(aComplete, aAppState); |
268 | 0 | lReturn = this->NewTimer(lTimer); |
269 | 0 | SuccessOrExit(lReturn); |
270 | | |
271 | 0 | lReturn = lTimer->Start(aMilliseconds, aComplete, aAppState); |
272 | 0 | if (lReturn != WEAVE_SYSTEM_NO_ERROR) |
273 | 0 | { |
274 | 0 | lTimer->Release(); |
275 | 0 | } |
276 | |
|
277 | 0 | exit: |
278 | 0 | return lReturn; |
279 | 0 | } |
280 | | |
281 | | /** |
282 | | * @brief |
283 | | * This method cancels a one-shot timer, started earlier through @p StartTimer(). |
284 | | * |
285 | | * @note |
286 | | * The cancellation could fail silently in two different ways. If the timer specified by the combination of the callback |
287 | | * function and application state object couldn't be found, cancellation could fail. If the timer has fired, but not yet |
288 | | * removed from memory, cancellation could also fail. |
289 | | * |
290 | | * @param[in] aOnComplete A pointer to the callback function used in calling @p StartTimer(). |
291 | | * @param[in] aAppState A pointer to the application state object used in calling @p StartTimer(). |
292 | | * |
293 | | */ |
294 | | void Layer::CancelTimer(Layer::TimerCompleteFunct aOnComplete, void* aAppState) |
295 | 0 | { |
296 | 0 | if (this->State() != kLayerState_Initialized) |
297 | 0 | return; |
298 | | |
299 | 0 | for (size_t i = 0; i < Timer::sPool.Size(); ++i) |
300 | 0 | { |
301 | 0 | Timer* lTimer = Timer::sPool.Get(*this, i); |
302 | |
|
303 | 0 | if (lTimer != NULL && lTimer->OnComplete == aOnComplete && lTimer->AppState == aAppState) |
304 | 0 | { |
305 | 0 | lTimer->Cancel(); |
306 | 0 | break; |
307 | 0 | } |
308 | 0 | } |
309 | 0 | } |
310 | | |
311 | | #if WEAVE_SYSTEM_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
312 | | void Layer::CancelAllMatchingInetTimers(nl::Inet::InetLayer& aInetLayer, void* aOnCompleteInetLayer, void* aAppState) |
313 | | { |
314 | | for (size_t i = 0; i < Timer::sPool.Size(); ++i) |
315 | | { |
316 | | Timer* lTimer = Timer::sPool.Get(*this, i); |
317 | | |
318 | | if (lTimer != NULL && lTimer->mInetLayer == &aInetLayer && lTimer->mOnCompleteInetLayer == aOnCompleteInetLayer && |
319 | | lTimer->mAppStateInetLayer == aAppState) |
320 | | { |
321 | | lTimer->Cancel(); |
322 | | break; |
323 | | } |
324 | | } |
325 | | } |
326 | | #endif // WEAVE_SYSTEM_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
327 | | |
328 | | /** |
329 | | * @brief |
330 | | * Schedules a function with a signature identical to |
331 | | * `TimerCompleteFunct` to be run as soon as possible on the Weave |
332 | | * thread. |
333 | | * |
334 | | * @note |
335 | | * This function could, in principle, be implemented as |
336 | | * `StartTimer(0, aComplete, aAppState)`. The specification for |
337 | | * `SystemTimer` however permits certain optimizations that might |
338 | | * make that implementation impossible. Specifically, `SystemTimer` |
339 | | * API may only be called from the thread owning the particular |
340 | | * `SystemLayer`, whereas the `ScheduleWork` may be called from |
341 | | * any thread. Additionally, whereas the `SystemTimer` API permits |
342 | | * the invocation of the already expired handler in line, |
343 | | * `ScheduleWork` guarantees that the handler function will be |
344 | | * called only after the current Weave event completes. |
345 | | * |
346 | | * @param[in] aComplete A pointer to a callback function to be called |
347 | | * when this timer fires. |
348 | | * |
349 | | * @param[in] aAppState A pointer to an application state object to be |
350 | | * passed to the callback function as argument. |
351 | | * |
352 | | * @retval WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE If the SystemLayer has |
353 | | * not been initialized. |
354 | | * |
355 | | * @retval WEAVE_SYSTEM_ERROR_NO_MEMORY If the SystemLayer cannot |
356 | | * allocate a new timer. |
357 | | * |
358 | | * @retval WEAVE_SYSTEM_NO_ERROR On success. |
359 | | */ |
360 | | Error Layer::ScheduleWork(TimerCompleteFunct aComplete, void* aAppState) |
361 | 0 | { |
362 | 0 | Error lReturn; |
363 | 0 | Timer* lTimer; |
364 | |
|
365 | 0 | lReturn = this->NewTimer(lTimer); |
366 | 0 | SuccessOrExit(lReturn); |
367 | | |
368 | 0 | lReturn = lTimer->ScheduleWork(aComplete, aAppState); |
369 | 0 | if (lReturn != WEAVE_SYSTEM_NO_ERROR) |
370 | 0 | { |
371 | 0 | lTimer->Release(); |
372 | 0 | } |
373 | |
|
374 | 0 | exit: |
375 | 0 | return lReturn; |
376 | 0 | } |
377 | | |
378 | | /** |
379 | | * @brief |
380 | | * Returns a monotonic system time in units of microseconds. |
381 | | * |
382 | | * This function returns an elapsed time in microseconds since an arbitrary, platform-defined |
383 | | * epoch. The value returned is guaranteed to be ever-increasing (i.e. never wrapping) between |
384 | | * reboots of the system. Additionally, the underlying time source is guaranteed to tick |
385 | | * continuously during any system sleep modes that do not entail a restart upon wake. |
386 | | * |
387 | | * Although some platforms may choose to return a value that measures the time since boot for the |
388 | | * system, applications must *not* rely on this. Additionally, the epoch for GetClock_Monotonic() |
389 | | * is *not* required to be the same as that for any of the other GetClock... functions. Therefore |
390 | | * relative time calculations can only be performed on values returned by the same function. |
391 | | * |
392 | | * This function is guaranteed to be thread-safe on any platform that employs threading. |
393 | | * |
394 | | * @returns Elapsed time in microseconds since an arbitrary, platform-defined epoch. |
395 | | */ |
396 | | uint64_t Layer::GetClock_Monotonic(void) |
397 | 0 | { |
398 | | // Current implementation is a simple pass-through to the platform. |
399 | 0 | return Platform::Layer::GetClock_Monotonic(); |
400 | 0 | } |
401 | | |
402 | | /** |
403 | | * @brief |
404 | | * Returns a monotonic system time in units of milliseconds. |
405 | | * |
406 | | * This function returns an elapsed time in milliseconds since an arbitrary, platform-defined |
407 | | * epoch. The value returned is guaranteed to be ever-increasing (i.e. never wrapping) between |
408 | | * reboots of the system. Additionally, the underlying time source is guaranteed to tick |
409 | | * continuously during any system sleep modes that do not entail a restart upon wake. |
410 | | * |
411 | | * Although some platforms may choose to return a value that measures the time since boot for the |
412 | | * system, applications must *not* rely on this. Additionally, the epoch for GetClock_Monotonic() |
413 | | * is *not* required to be the same as that for any of the other GetClock... functions. Therefore |
414 | | * relative time calculations can only be performed on values returned by the same function. |
415 | | * |
416 | | * This function is guaranteed to be thread-safe on any platform that employs threading. |
417 | | * |
418 | | * @returns Elapsed time in milliseconds since an arbitrary, platform-defined epoch. |
419 | | */ |
420 | | uint64_t Layer::GetClock_MonotonicMS(void) |
421 | 0 | { |
422 | | // Current implementation is a simple pass-through to the platform. |
423 | 0 | return Platform::Layer::GetClock_MonotonicMS(); |
424 | 0 | } |
425 | | |
426 | | /** |
427 | | * @brief |
428 | | * Returns a (potentially) high-resolution monotonic system time in units of microseconds. |
429 | | * |
430 | | * This function returns an elapsed time in microseconds since an arbitrary, platform-defined |
431 | | * epoch. The value returned is guaranteed to be ever-increasing (i.e. never wrapping) between |
432 | | * reboots of the system. However, the underlying timer is *not* required to tick continuously |
433 | | * during system deep-sleep states. |
434 | | * |
435 | | * Some platforms may implement GetClock_MonotonicHiRes() using a high-resolution timer capable |
436 | | * of greater precision than GetClock_Monotonic(), and that is not subject to gradual clock |
437 | | * adjustments (slewing). Systems without such a timer may simply return the same value as |
438 | | * GetClock_Monotonic(). |
439 | | * |
440 | | * The epoch for time returned by GetClock_MonotonicHiRes() is not required to be the same that |
441 | | * for any of the other GetClock... functions, including GetClock_Monotonic(). |
442 | | * |
443 | | * This function is guaranteed to be thread-safe on any platform that employs threading. |
444 | | * |
445 | | * @returns Elapsed time in microseconds since an arbitrary, platform-defined epoch. |
446 | | */ |
447 | | uint64_t Layer::GetClock_MonotonicHiRes(void) |
448 | 0 | { |
449 | | // Current implementation is a simple pass-through to the platform. |
450 | 0 | return Platform::Layer::GetClock_MonotonicHiRes(); |
451 | 0 | } |
452 | | |
453 | | /** |
454 | | * @brief |
455 | | * Returns the current real (civil) time in microsecond Unix time format. |
456 | | * |
457 | | * This method returns the local platform's notion of current real time, expressed as a Unix time |
458 | | * value scaled to microseconds. The underlying clock is guaranteed to tick at a rate of least at |
459 | | * whole seconds (values of 1,000,000), but on some platforms may tick faster. |
460 | | * |
461 | | * If the underlying platform is capable of tracking real time, but the system is currently |
462 | | * unsynchronized, GetClock_RealTime() will return the error WEAVE_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED. |
463 | | * |
464 | | * On platforms that are incapable of tracking real time, the GetClock_RealTime() method may be absent, |
465 | | * resulting a link error for any application that references it. Alternatively, such platforms may |
466 | | * supply an implementation of GetClock_RealTime() that always returns the error WEAVE_SYSTEM_ERROR_NOT_SUPPORTED. |
467 | | * |
468 | | * This function is guaranteed to be thread-safe on any platform that employs threading. |
469 | | * |
470 | | * @param[out] curTime The current time, expressed as Unix time scaled to microseconds. |
471 | | * |
472 | | * @retval #WEAVE_SYSTEM_NO_ERROR If the method succeeded. |
473 | | * @retval #WEAVE_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED |
474 | | * If the platform is capable of tracking real time, but is |
475 | | * is currently unsynchronized. |
476 | | * @retval #WEAVE_SYSTEM_ERROR_NOT_SUPPORTED |
477 | | * If the platform is incapable of tracking real time. |
478 | | */ |
479 | | Error Layer::GetClock_RealTime(uint64_t & curTime) |
480 | 0 | { |
481 | | // Current implementation is a simple pass-through to the platform. |
482 | 0 | return Platform::Layer::GetClock_RealTime(curTime); |
483 | 0 | } |
484 | | |
485 | | /** |
486 | | * @brief |
487 | | * Returns the current real (civil) time in millisecond Unix time format. |
488 | | * |
489 | | * This method returns the local platform's notion of current real time, expressed as a Unix time |
490 | | * value scaled to milliseconds. The underlying clock is guaranteed to tick at a rate of least at |
491 | | * whole seconds (values of 1,000,000), but on some platforms may tick faster. |
492 | | * |
493 | | * If the underlying platform is capable of tracking real time, but the system is currently |
494 | | * unsynchronized, GetClock_RealTimeMS() will return the error WEAVE_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED. |
495 | | * |
496 | | * On platforms that are incapable of tracking real time, the GetClock_RealTimeMS() method may be absent, |
497 | | * resulting a link error for any application that references it. Alternatively, such platforms may |
498 | | * supply an implementation of GetClock_RealTimeMS() that always returns the error WEAVE_SYSTEM_ERROR_NOT_SUPPORTED. |
499 | | * |
500 | | * This function is guaranteed to be thread-safe on any platform that employs threading. |
501 | | * |
502 | | * @param[out] curTime The current time, expressed as Unix time scaled to milliseconds. |
503 | | * |
504 | | * @retval #WEAVE_SYSTEM_NO_ERROR If the method succeeded. |
505 | | * @retval #WEAVE_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED |
506 | | * If the platform is capable of tracking real time, but is |
507 | | * is currently unsynchronized. |
508 | | * @retval #WEAVE_SYSTEM_ERROR_NOT_SUPPORTED |
509 | | * If the platform is incapable of tracking real time. |
510 | | */ |
511 | | Error Layer::GetClock_RealTimeMS(uint64_t & curTimeMS) |
512 | 0 | { |
513 | | // Current implementation is a simple pass-through to the platform. |
514 | 0 | return Platform::Layer::GetClock_RealTimeMS(curTimeMS); |
515 | 0 | } |
516 | | |
517 | | /** |
518 | | * @brief |
519 | | * Sets the platform's notion of current real (civil) time. |
520 | | * |
521 | | * Applications can call this function to set the local platform's notion of current real time. The |
522 | | * new current time is expressed as a Unix time value scaled to microseconds. |
523 | | * |
524 | | * Once set, underlying platform clock is guaranteed to track real time with a granularity of at least |
525 | | * whole seconds. |
526 | | * |
527 | | * Some platforms may restrict which applications or processes can set real time. If the caller is |
528 | | * not permitted to change real time, the SetClock_RealTime() function will return the error |
529 | | * WEAVE_SYSTEM_ERROR_ACCESS_DENIED. |
530 | | * |
531 | | * On platforms that are incapable of tracking real time, or do not offer the ability to set real time, |
532 | | * the SetClock_RealTime() function may be absent, resulting a link error for any application that |
533 | | * references it. Alternatively, such platforms may supply an implementation of SetClock_RealTime() |
534 | | * that always returns the error WEAVE_SYSTEM_ERROR_NOT_SUPPORTED. |
535 | | * |
536 | | * This function is guaranteed to be thread-safe on any platform that employs threading. |
537 | | * |
538 | | * @param[in] newCurTime The new current time, expressed as Unix time scaled to microseconds. |
539 | | * |
540 | | * @retval #WEAVE_SYSTEM_NO_ERROR If the method succeeded. |
541 | | * @retval #WEAVE_SYSTEM_ERROR_NOT_SUPPORTED |
542 | | * If the platform is incapable of tracking real time. |
543 | | * @retval #WEAVE_SYSTEM_ERROR_ACCESS_DENIED |
544 | | * If the calling application does not have the privilege to set the |
545 | | * current time. |
546 | | */ |
547 | | Error Layer::SetClock_RealTime(uint64_t newCurTime) |
548 | 0 | { |
549 | | // Current implementation is a simple pass-through to the platform. |
550 | 0 | return Platform::Layer::SetClock_RealTime(newCurTime); |
551 | 0 | } |
552 | | |
553 | | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
554 | | |
555 | | /** |
556 | | * Prepare the sets of file descriptors for @p select() to work with. |
557 | | * |
558 | | * @param[in,out] pollFDs The fd set which is going to be polled |
559 | | * @param[in,out] numPollFDs The number of fds in the fd set |
560 | | * @param[in] timeoutMS A reference to the maximum sleep time. |
561 | | */ |
562 | | void Layer::PrepareSelect(struct pollfd * pollFDs, int& numPollFDs, int& timeoutMS) |
563 | 0 | { |
564 | 0 | if (this->State() != kLayerState_Initialized) |
565 | 0 | return; |
566 | | |
567 | 0 | struct pollfd & event = pollFDs[numPollFDs++]; |
568 | 0 | event.fd = this->mWakePipeIn; |
569 | 0 | event.events = POLLIN; |
570 | 0 | event.revents = 0; |
571 | |
|
572 | 0 | const Timer::Epoch kCurrentEpoch = Timer::GetCurrentEpoch(); |
573 | 0 | Timer::Epoch lAwakenEpoch = kCurrentEpoch + timeoutMS; |
574 | |
|
575 | 0 | for (size_t i = 0; i < Timer::sPool.Size(); i++) |
576 | 0 | { |
577 | 0 | Timer* lTimer = Timer::sPool.Get(*this, i); |
578 | |
|
579 | 0 | if (lTimer != NULL) |
580 | 0 | { |
581 | 0 | if (!Timer::IsEarlierEpoch(kCurrentEpoch, lTimer->mAwakenEpoch)) |
582 | 0 | { |
583 | 0 | lAwakenEpoch = kCurrentEpoch; |
584 | 0 | break; |
585 | 0 | } |
586 | | |
587 | 0 | if (Timer::IsEarlierEpoch(lTimer->mAwakenEpoch, lAwakenEpoch)) |
588 | 0 | lAwakenEpoch = lTimer->mAwakenEpoch; |
589 | 0 | } |
590 | 0 | } |
591 | |
|
592 | 0 | const Timer::Epoch kSleepTime = lAwakenEpoch - kCurrentEpoch; |
593 | 0 | timeoutMS = kSleepTime; |
594 | 0 | } |
595 | | |
596 | | /** |
597 | | * Handle I/O from a select call. This method registers the pending I/O event in each active endpoint and then invokes the |
598 | | * respective I/O handling functions for those endpoints. |
599 | | * |
600 | | * @note |
601 | | * It is important to set the pending I/O fields for all endpoints *before* making any callbacks. This avoids the case where an |
602 | | * endpoint is closed and then re-opened within the callback for another endpoint. When this happens the new endpoint is likely to |
603 | | * be assigned the same file descriptor as the old endpoint. However, any pending I/O for that file descriptor number represents |
604 | | * I/O related to the old incarnation of the endpoint, not the current one. Saving the pending I/O state in each endpoint before |
605 | | * acting on it allows the endpoint code to clear the I/O flags in the event of a close, thus avoiding any confusion. |
606 | | * |
607 | | * @param[in] pollFDs The result of polled FDs |
608 | | * @param[in] numPollFDs The number of fds in the fd set |
609 | | */ |
610 | | void Layer::HandleSelectResult(const struct pollfd * pollFDs, int numPollFDs) |
611 | 0 | { |
612 | 0 | pthread_t lThreadSelf; |
613 | |
|
614 | 0 | if (this->State() != kLayerState_Initialized) |
615 | 0 | return; |
616 | | |
617 | 0 | #if WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
618 | 0 | lThreadSelf = pthread_self(); |
619 | 0 | #endif // WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
620 | |
|
621 | 0 | for (int i = 0; i < numPollFDs; ++i) |
622 | 0 | { |
623 | 0 | const struct pollfd & event = pollFDs[i]; |
624 | | // If we woke because of someone writing to the wake pipe, clear the contents of the pipe before returning. |
625 | 0 | if (event.fd == this->mWakePipeIn && event.revents != 0) |
626 | 0 | { |
627 | 0 | while (true) |
628 | 0 | { |
629 | 0 | uint8_t lBytes[128]; |
630 | 0 | int lTmp = ::read(this->mWakePipeIn, static_cast<void*>(lBytes), sizeof(lBytes)); |
631 | 0 | if (lTmp < static_cast<int>(sizeof(lBytes))) |
632 | 0 | break; |
633 | 0 | } |
634 | 0 | } |
635 | 0 | } |
636 | |
|
637 | 0 | const Timer::Epoch kCurrentEpoch = Timer::GetCurrentEpoch(); |
638 | |
|
639 | 0 | #if WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
640 | 0 | this->mHandleSelectThread = lThreadSelf; |
641 | 0 | #endif // WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
642 | |
|
643 | 0 | for (size_t i = 0; i < Timer::sPool.Size(); i++) |
644 | 0 | { |
645 | 0 | Timer* lTimer = Timer::sPool.Get(*this, i); |
646 | |
|
647 | 0 | if (lTimer != NULL && !Timer::IsEarlierEpoch(kCurrentEpoch, lTimer->mAwakenEpoch)) |
648 | 0 | { |
649 | 0 | lTimer->HandleComplete(); |
650 | 0 | } |
651 | 0 | } |
652 | |
|
653 | 0 | #if WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
654 | 0 | this->mHandleSelectThread = PTHREAD_NULL; |
655 | 0 | #endif // WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
656 | 0 | } |
657 | | |
658 | | /** |
659 | | * Wake up the I/O thread that monitors the file descriptors using select() by writing a single byte to the wake pipe. |
660 | | * |
661 | | * @note |
662 | | * If @p WakeSelect() is being called from within @p HandleSelectResult(), then writing to the wake pipe can be skipped, since |
663 | | * the I/O thread is already awake. |
664 | | * |
665 | | * Furthermore, we don't care if this write fails as the only reasonably likely failure is that the pipe is full, in which |
666 | | * case the select calling thread is going to wake up anyway. |
667 | | */ |
668 | | void Layer::WakeSelect() |
669 | 0 | { |
670 | 0 | if (this->State() != kLayerState_Initialized) |
671 | 0 | return; |
672 | | |
673 | 0 | #if WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
674 | 0 | if (pthread_equal(this->mHandleSelectThread, pthread_self())) |
675 | 0 | { |
676 | 0 | return; |
677 | 0 | } |
678 | 0 | #endif // WEAVE_SYSTEM_CONFIG_POSIX_LOCKING |
679 | | |
680 | | // Write a single byte to the wake pipe to wake up the select call. |
681 | 0 | const uint8_t kByte = 0; |
682 | 0 | const ssize_t kIOResult = ::write(this->mWakePipeOut, &kByte, 1); |
683 | 0 | static_cast<void>(kIOResult); |
684 | 0 | } |
685 | | |
686 | | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
687 | | |
688 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
689 | | LwIPEventHandlerDelegate Layer::sSystemEventHandlerDelegate; |
690 | | |
691 | | /** |
692 | | * This is the dispatch handler for system layer events. |
693 | | * |
694 | | * @param[inout] aTarget A pointer to the Weave System Layer object making the post request. |
695 | | * @param[in] aEventType The type of event to post. |
696 | | * @param[inout] aArgument The argument associated with the event to post. |
697 | | */ |
698 | | Error Layer::HandleSystemLayerEvent(Object& aTarget, EventType aEventType, uintptr_t aArgument) |
699 | | { |
700 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
701 | | ; |
702 | | |
703 | | // Dispatch logic specific to the event type |
704 | | switch (aEventType) |
705 | | { |
706 | | case kEvent_ReleaseObj: |
707 | | aTarget.Release(); |
708 | | break; |
709 | | |
710 | | case kEvent_ScheduleWork: |
711 | | static_cast<Timer&>(aTarget).HandleComplete(); |
712 | | break; |
713 | | |
714 | | default: |
715 | | lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT; |
716 | | break; |
717 | | } |
718 | | |
719 | | return lReturn; |
720 | | } |
721 | | |
722 | | /** |
723 | | * This adds an event handler delegate to the system layer to extend its ability to handle LwIP events. |
724 | | * |
725 | | * @param[in] aDelegate An uninitialied LwIP event handler delegate structure |
726 | | * |
727 | | * @retval WEAVE_SYSTEM_NO_ERROR On success. |
728 | | * @retval WEAVE_SYSTEM_ERROR_BAD_ARGS If the function pointer contained in aDelegate is NULL |
729 | | */ |
730 | | Error Layer::AddEventHandlerDelegate(LwIPEventHandlerDelegate& aDelegate) |
731 | | { |
732 | | Error lReturn; |
733 | | |
734 | | VerifyOrExit(aDelegate.mFunction != NULL, lReturn = WEAVE_SYSTEM_ERROR_BAD_ARGS); |
735 | | aDelegate.Prepend(this->mEventDelegateList); |
736 | | lReturn = WEAVE_SYSTEM_NO_ERROR; |
737 | | |
738 | | exit: |
739 | | return lReturn; |
740 | | } |
741 | | |
742 | | /** |
743 | | * This posts an event / message of the specified type with the provided argument to this instance's platform-specific event queue. |
744 | | * |
745 | | * @param[inout] aTarget A pointer to the Weave System Layer object making the post request. |
746 | | * @param[in] aEventType The type of event to post. |
747 | | * @param[inout] aArgument The argument associated with the event to post. |
748 | | * |
749 | | * @retval WEAVE_SYSTEM_NO_ERROR On success. |
750 | | * @retval WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE If the state of the Layer object is incorrect. |
751 | | * @retval WEAVE_SYSTEM_ERROR_NO_MEMORY If the event queue is already full. |
752 | | * @retval other Platform-specific errors generated indicating the reason for failure. |
753 | | */ |
754 | | Error Layer::PostEvent(Object& aTarget, EventType aEventType, uintptr_t aArgument) |
755 | | { |
756 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
757 | | VerifyOrExit(this->State() == kLayerState_Initialized, lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE); |
758 | | |
759 | | // Sanity check that this instance and the target layer haven't been "crossed". |
760 | | VerifyOrDieWithMsg(aTarget.IsRetained(*this), WeaveSystemLayer, "wrong poster! [target %p != this %p]", |
761 | | &(aTarget.SystemLayer()), this); |
762 | | |
763 | | lReturn = Platform::Layer::PostEvent(*this, this->mContext, aTarget, aEventType, aArgument); |
764 | | if (lReturn != WEAVE_SYSTEM_NO_ERROR) |
765 | | { |
766 | | WeaveLogError(WeaveSystemLayer, "Failed to queue Weave System Layer event (type %d): %s", aEventType, ErrorStr(lReturn)); |
767 | | } |
768 | | SuccessOrExit(lReturn); |
769 | | |
770 | | exit: |
771 | | return lReturn; |
772 | | } |
773 | | |
774 | | /** |
775 | | * This is a syntactic wrapper around a platform-specific hook that effects an event loop, waiting on a queue that services this |
776 | | * instance, pulling events off of that queue, and then dispatching them for handling. |
777 | | * |
778 | | * @return #WEAVE_SYSTEM_NO_ERROR on success; otherwise, a specific error indicating the reason for initialization failure. |
779 | | */ |
780 | | Error Layer::DispatchEvents() |
781 | | { |
782 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
783 | | VerifyOrExit(this->State() == kLayerState_Initialized, lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE); |
784 | | |
785 | | lReturn = Platform::Layer::DispatchEvents(*this, this->mContext); |
786 | | SuccessOrExit(lReturn); |
787 | | |
788 | | exit: |
789 | | return lReturn; |
790 | | } |
791 | | |
792 | | /** |
793 | | * This dispatches the specified event for handling by this instance. |
794 | | * |
795 | | * The unmarshalling of the type and arguments from the event is handled by a platform-specific hook which should then call back |
796 | | * to Layer::HandleEvent for the actual dispatch. |
797 | | * |
798 | | * @param[in] aEvent The platform-specific event object to dispatch for handling. |
799 | | * |
800 | | * @return WEAVE_SYSTEM_NO_ERROR on success; otherwise, a specific error indicating the reason for initialization failure. |
801 | | */ |
802 | | Error Layer::DispatchEvent(Event aEvent) |
803 | | { |
804 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
805 | | VerifyOrExit(this->State() == kLayerState_Initialized, lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE); |
806 | | |
807 | | lReturn = Platform::Layer::DispatchEvent(*this, this->mContext, aEvent); |
808 | | SuccessOrExit(lReturn); |
809 | | |
810 | | exit: |
811 | | return lReturn; |
812 | | } |
813 | | |
814 | | /** |
815 | | * This implements the actual dispatch and handling of a Weave System Layer event. |
816 | | * |
817 | | * @param[inout] aTarget A reference to the layer object to which the event is targeted. |
818 | | * @param[in] aEventType The event / message type to handle. |
819 | | * @param[in] aArgument The argument associated with the event / message. |
820 | | * |
821 | | * @retval WEAVE_SYSTEM_NO_ERROR On success. |
822 | | * @retval WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE If the state of the InetLayer object is incorrect. |
823 | | * @retval WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT If the event type is unrecognized. |
824 | | */ |
825 | | Error Layer::HandleEvent(Object& aTarget, EventType aEventType, uintptr_t aArgument) |
826 | | { |
827 | | const LwIPEventHandlerDelegate* lEventDelegate; |
828 | | Error lReturn; |
829 | | VerifyOrExit(this->State() == kLayerState_Initialized, lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE); |
830 | | |
831 | | // Sanity check that this instance and the target layer haven't been "crossed". |
832 | | VerifyOrDieWithMsg(aTarget.IsRetained(*this), WeaveSystemLayer, "wrong handler! [target %p != this %p]", |
833 | | &(aTarget.SystemLayer()), this); |
834 | | |
835 | | lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT; |
836 | | lEventDelegate = this->mEventDelegateList; |
837 | | |
838 | | // Prevent the target object from being freed while dispatching the event. |
839 | | aTarget.Retain(); |
840 | | |
841 | | while (lReturn == WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT && lEventDelegate != NULL) |
842 | | { |
843 | | lReturn = lEventDelegate->mFunction(aTarget, aEventType, aArgument); |
844 | | lEventDelegate = lEventDelegate->mNextDelegate; |
845 | | } |
846 | | |
847 | | if (lReturn == WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT) |
848 | | { |
849 | | WeaveLogError(WeaveSystemLayer, "Unexpected event type %d", aEventType); |
850 | | } |
851 | | |
852 | | /* |
853 | | Release the reference to the target object. When the object's lifetime finally comes to an end, in most cases this will be |
854 | | the release call that decrements the ref count to zero. |
855 | | */ |
856 | | aTarget.Release(); |
857 | | |
858 | | exit: |
859 | | return lReturn; |
860 | | } |
861 | | |
862 | | /** |
863 | | * Start the platform timer with specified millsecond duration. |
864 | | * |
865 | | * @brief |
866 | | * Calls the Platform specific API to start a platform timer. This API is called by the nl::Weave::System::Timer class when |
867 | | * one or more timers are active and require deferred execution. |
868 | | * |
869 | | * @param[in] aDelayMilliseconds The timer duration in milliseconds. |
870 | | * |
871 | | * @return WEAVE_SYSTEM_NO_ERROR on success, error code otherwise. |
872 | | * |
873 | | */ |
874 | | Error Layer::StartPlatformTimer(uint32_t aDelayMilliseconds) |
875 | | { |
876 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
877 | | VerifyOrExit(this->State() == kLayerState_Initialized, lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE); |
878 | | |
879 | | lReturn = Platform::Layer::StartTimer(*this, this->mContext, aDelayMilliseconds); |
880 | | SuccessOrExit(lReturn); |
881 | | |
882 | | exit: |
883 | | return lReturn; |
884 | | } |
885 | | |
886 | | /** |
887 | | * Handle the platform timer expiration event. |
888 | | * |
889 | | * @brief |
890 | | * Calls nl::Weave::System::Timer::HandleExpiredTimers to handle any expired timers. It is assumed that this API is called |
891 | | * only while on the thread which owns the Weave System Layer object. |
892 | | * |
893 | | * @return WEAVE_SYSTEM_NO_ERROR on success, error code otherwise. |
894 | | * |
895 | | */ |
896 | | Error Layer::HandlePlatformTimer() |
897 | | { |
898 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
899 | | VerifyOrExit(this->State() == kLayerState_Initialized, lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE); |
900 | | |
901 | | lReturn = Timer::HandleExpiredTimers(*this); |
902 | | SuccessOrExit(lReturn); |
903 | | |
904 | | exit: |
905 | | return lReturn; |
906 | | } |
907 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
908 | | |
909 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
910 | | #if !WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS |
911 | | |
912 | | // MARK: Weave System Layer platform- and system-specific functions for LwIP-native eventing. |
913 | | struct LwIPEvent |
914 | | { |
915 | | EventType Type; |
916 | | Object* Target; |
917 | | uintptr_t Argument; |
918 | | }; |
919 | | |
920 | | #endif // !WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS |
921 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
922 | | |
923 | | namespace Platform { |
924 | | namespace Layer { |
925 | | |
926 | | #if !WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_XTOR_FUNCTIONS |
927 | | |
928 | | /** |
929 | | * This is a platform-specific Weave System Layer pre-initialization hook. This may be overridden by assserting the preprocessor |
930 | | * definition, #WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_XTOR_FUNCTIONS. |
931 | | * |
932 | | * @param[inout] aLayer A reference to the Weave System Layer instance being initialized. |
933 | | * |
934 | | * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Init. |
935 | | * |
936 | | * @return #WEAVE_SYSTEM_NO_ERROR on success; otherwise, a specific error indicating the reason for initialization failure. |
937 | | * Returning non-successful status will abort initialization. |
938 | | */ |
939 | | NL_DLL_EXPORT Error WillInit(Layer& aLayer, void* aContext) |
940 | 0 | { |
941 | 0 | static_cast<void>(aLayer); |
942 | 0 | static_cast<void>(aContext); |
943 | |
|
944 | 0 | return WEAVE_SYSTEM_NO_ERROR; |
945 | 0 | } |
946 | | |
947 | | /** |
948 | | * This is a platform-specific Weave System Layer pre-shutdown hook. This may be overridden by assserting the preprocessor |
949 | | * definition, #WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_XTOR_FUNCTIONS. |
950 | | * |
951 | | * @param[inout] aLayer A pointer to the Weave System Layer instance being shutdown. |
952 | | * |
953 | | * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Shutdown. |
954 | | * |
955 | | * @return #WEAVE_SYSTEM_NO_ERROR on success; otherwise, a specific error indicating the reason for shutdown failure. Returning |
956 | | * non-successful status will abort shutdown. |
957 | | */ |
958 | | NL_DLL_EXPORT Error WillShutdown(Layer& aLayer, void* aContext) |
959 | 0 | { |
960 | 0 | static_cast<void>(aLayer); |
961 | 0 | static_cast<void>(aContext); |
962 | |
|
963 | 0 | return WEAVE_SYSTEM_NO_ERROR; |
964 | 0 | } |
965 | | |
966 | | /** |
967 | | * This is a platform-specific Weave System Layer post-initialization hook. This may be overridden by assserting the preprocessor |
968 | | * definition, #WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_XTOR_FUNCTIONS. |
969 | | * |
970 | | * @param[inout] aLayer A reference to the Weave System Layer instance being initialized. |
971 | | * |
972 | | * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Init. |
973 | | * |
974 | | * @param[in] anError The overall status being returned via the Weave System Layer ::Init method. |
975 | | */ |
976 | | NL_DLL_EXPORT void DidInit(Layer& aLayer, void* aContext, Error aStatus) |
977 | 0 | { |
978 | 0 | static_cast<void>(aLayer); |
979 | 0 | static_cast<void>(aContext); |
980 | 0 | static_cast<void>(aStatus); |
981 | 0 | } |
982 | | |
983 | | /** |
984 | | * This is a platform-specific Weave System Layer pre-shutdown hook. This may be overridden by assserting the preprocessor |
985 | | * definition, #WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_XTOR_FUNCTIONS. |
986 | | * |
987 | | * @param[inout] aLayer A reference to the Weave System Layer instance being shutdown. |
988 | | * |
989 | | * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Shutdown. |
990 | | * |
991 | | * @param[in] anError The overall status being returned via the Weave System Layer ::Shutdown method. |
992 | | * |
993 | | * @return #WEAVE_SYSTEM_NO_ERROR on success; otherwise, a specific error indicating the reason for shutdown failure. Returning |
994 | | * non-successful status will abort shutdown. |
995 | | */ |
996 | | NL_DLL_EXPORT void DidShutdown(Layer& aLayer, void* aContext, Error aStatus) |
997 | 0 | { |
998 | 0 | static_cast<void>(aLayer); |
999 | 0 | static_cast<void>(aContext); |
1000 | 0 | static_cast<void>(aStatus); |
1001 | 0 | } |
1002 | | |
1003 | | #endif // !WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_XTOR_FUNCTIONS |
1004 | | |
1005 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
1006 | | #if !WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS |
1007 | | |
1008 | | using nl::Weave::System::LwIPEvent; |
1009 | | |
1010 | | /** |
1011 | | * This is a platform-specific event / message post hook. This may be overridden by assserting the preprocessor definition, |
1012 | | * #WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS. |
1013 | | * |
1014 | | * This posts an event / message of the specified type with the provided argument to this instance's platform-specific event / |
1015 | | * message queue. |
1016 | | * |
1017 | | * @note |
1018 | | * This is an implementation for LwIP. |
1019 | | * |
1020 | | * @param[inout] aLayer A pointer to the layer instance to which the event / message is being posted. |
1021 | | * |
1022 | | * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Init. |
1023 | | * |
1024 | | * @param[inout] aTarget A pointer to the Weave System Layer object making the post request. |
1025 | | * |
1026 | | * @param[in] aType The type of event to post. |
1027 | | * |
1028 | | * @param[inout] anArg The argument associated with the event to post. |
1029 | | * |
1030 | | * @return #WEAVE_SYSTEM_NO_ERROR on success; otherwise, a specific error indicating the reason for initialization failure. |
1031 | | */ |
1032 | | NL_DLL_EXPORT Error PostEvent(Layer& aLayer, void* aContext, Object& aTarget, EventType aType, uintptr_t aArgument) |
1033 | | { |
1034 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
1035 | | sys_mbox_t lSysMbox; |
1036 | | LwIPEvent* ev; |
1037 | | err_t lLwIPError; |
1038 | | |
1039 | | VerifyOrExit(aContext != NULL, lReturn = WEAVE_SYSTEM_ERROR_BAD_ARGS); |
1040 | | lSysMbox = reinterpret_cast<sys_mbox_t>(aContext); |
1041 | | |
1042 | | ev = new LwIPEvent; |
1043 | | VerifyOrExit(ev != NULL, lReturn = WEAVE_SYSTEM_ERROR_NO_MEMORY); |
1044 | | |
1045 | | ev->Type = aType; |
1046 | | ev->Target = &aTarget; |
1047 | | ev->Argument = aArgument; |
1048 | | |
1049 | | lLwIPError = sys_mbox_trypost(&lSysMbox, ev); |
1050 | | VerifyOrExit(lLwIPError == ERR_OK, delete ev; lReturn = nl::Weave::System::MapErrorLwIP(lLwIPError)); |
1051 | | |
1052 | | exit: |
1053 | | return lReturn; |
1054 | | } |
1055 | | |
1056 | | /** |
1057 | | * This is a platform-specific event / message dispatch hook. This may be overridden by assserting the preprocessor definition, |
1058 | | * #WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS. |
1059 | | * |
1060 | | * This effects an event loop, waiting on a queue that services this instance, pulling events off of that queue, and then |
1061 | | * dispatching them for handling. |
1062 | | * |
1063 | | * @note |
1064 | | * This is an implementation for LwIP. |
1065 | | * |
1066 | | * @param[inout] aLayer A reference to the layer instance for which events / messages are being dispatched. |
1067 | | * |
1068 | | * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Init. |
1069 | | * |
1070 | | * @retval #WEAVE_SYSTEM_ERROR_BAD_ARGS If #aLayer or #aContext is NULL. |
1071 | | * @retval #WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE If the state of the Weave System Layer object is unexpected. |
1072 | | * @retval #WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT If an event type is unrecognized. |
1073 | | * @retval #WEAVE_SYSTEM_NO_ERROR On success. |
1074 | | */ |
1075 | | NL_DLL_EXPORT Error DispatchEvents(Layer& aLayer, void* aContext) |
1076 | | { |
1077 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
1078 | | err_t lLwIPError; |
1079 | | sys_mbox_t lSysMbox; |
1080 | | void* lVoidPointer; |
1081 | | const LwIPEvent* lEvent; |
1082 | | |
1083 | | // Sanity check the context / queue. |
1084 | | VerifyOrExit(aContext != NULL, lReturn = WEAVE_SYSTEM_ERROR_BAD_ARGS); |
1085 | | lSysMbox = reinterpret_cast<sys_mbox_t>(aContext); |
1086 | | |
1087 | | while (true) |
1088 | | { |
1089 | | lLwIPError = sys_arch_mbox_tryfetch(&lSysMbox, &lVoidPointer); |
1090 | | VerifyOrExit(lLwIPError == ERR_OK, lReturn = nl::Weave::System::MapErrorLwIP(lLwIPError)); |
1091 | | |
1092 | | lEvent = static_cast<const LwIPEvent*>(lVoidPointer); |
1093 | | VerifyOrExit(lEvent != NULL && lEvent->Target != NULL, lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT); |
1094 | | |
1095 | | lReturn = aLayer.HandleEvent(*lEvent->Target, lEvent->Type, lEvent->Argument); |
1096 | | delete lEvent; |
1097 | | |
1098 | | SuccessOrExit(lReturn); |
1099 | | } |
1100 | | |
1101 | | exit: |
1102 | | return lReturn; |
1103 | | } |
1104 | | |
1105 | | /** |
1106 | | * This is a platform-specific event / message dispatch hook. This may be overridden by assserting the preprocessor definition, |
1107 | | * #WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS. |
1108 | | * |
1109 | | * This dispatches the specified event for handling, unmarshalling the type and arguments from the event for hand off to Weave |
1110 | | * System Layer::HandleEvent for the actual dispatch. |
1111 | | * |
1112 | | * @note |
1113 | | * This is an implementation for LwIP. |
1114 | | * |
1115 | | * @param[inout] aLayer A reference to the layer instance for which events / messages are being dispatched. |
1116 | | * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Init. |
1117 | | * @param[in] anEvent The platform-specific event object to dispatch for handling. |
1118 | | * |
1119 | | * @retval #WEAVE_SYSTEM_ERROR_BAD_ARGS If #aLayer or the event target is NULL. |
1120 | | * @retval #WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT If the event type is unrecognized. |
1121 | | * @retval #WEAVE_SYSTEM_ERROR_UNEXPECTED_STATE If the state of the Weave System Layer object is unexpected. |
1122 | | * @retval #WEAVE_SYSTEM_NO_ERROR On success. |
1123 | | */ |
1124 | | NL_DLL_EXPORT Error DispatchEvent(Layer& aLayer, void* aContext, Event aEvent) |
1125 | | { |
1126 | | const EventType type = aEvent->Type; |
1127 | | Object* target = aEvent->Target; |
1128 | | const uint32_t data = aEvent->Argument; |
1129 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
1130 | | |
1131 | | // Sanity check the target object. |
1132 | | VerifyOrExit(target != NULL, lReturn = WEAVE_SYSTEM_ERROR_BAD_ARGS); |
1133 | | |
1134 | | // Handle the event. |
1135 | | lReturn = aLayer.HandleEvent(*target, type, data); |
1136 | | SuccessOrExit(lReturn); |
1137 | | |
1138 | | exit: |
1139 | | return lReturn; |
1140 | | } |
1141 | | |
1142 | | /** |
1143 | | * This is a platform-specific event / message dispatch hook. This may be overridden by assserting the preprocessor definition, |
1144 | | * #WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS. |
1145 | | * |
1146 | | * @note |
1147 | | * This is an implementation for LwIP. |
1148 | | * |
1149 | | * @param[inout] aLayer A reference to the layer instance for which events / messages are being dispatched. |
1150 | | * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Init. |
1151 | | * @param[in] aMilliseconds The number of milliseconds to set for the timer. |
1152 | | * |
1153 | | * @retval #WEAVE_SYSTEM_NO_ERROR Always succeeds unless overridden. |
1154 | | */ |
1155 | | NL_DLL_EXPORT Error StartTimer(Layer& aLayer, void* aContext, uint32_t aMilliseconds) |
1156 | | { |
1157 | | Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
1158 | | |
1159 | | // At the moment there is no need to do anything for standalone weave + LWIP. |
1160 | | // the Task will periodically call HandleTimer which will process any expired |
1161 | | // timers. |
1162 | | static_cast<void>(aLayer); |
1163 | | static_cast<void>(aContext); |
1164 | | static_cast<void>(aMilliseconds); |
1165 | | |
1166 | | return lReturn; |
1167 | | } |
1168 | | |
1169 | | #endif // !WEAVE_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS |
1170 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
1171 | | |
1172 | | } // namespace Layer |
1173 | | } // namespace Platform |
1174 | | } // namespace System |
1175 | | } // namespace Weave |
1176 | | } // namespace nl |