/* * * Copyright (c) 2020 Project CHIP Authors * Copyright (c) 2019 Nest Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file * Provides an implementation of the PlatformManager object. */ /* this file behaves like a config.h, comes first */ #include #include #include #include #include #include #include namespace chip { namespace DeviceLayer { PlatformManagerImpl PlatformManagerImpl::sInstance; CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) { CHIP_ERROR err = CHIP_NO_ERROR; wiced_result_t result; // Initialize the configuration system. err = PersistedStorage::KeyValueStoreMgrImpl().Init(); SuccessOrExit(err); /* Create the thread object. */ mThread = wiced_rtos_create_thread(); VerifyOrExit(mThread != nullptr, err = CHIP_ERROR_NO_MEMORY); /* Initialize the event flags. */ ReturnErrorOnFailure(mEventFlags.Init()); /* Initialize the event queue. */ mEventQueue = wiced_rtos_create_queue(); VerifyOrExit(mEventQueue != nullptr, err = CHIP_ERROR_NO_MEMORY); result = wiced_rtos_init_queue(mEventQueue, "EventQueue", sizeof(ChipDeviceEvent), CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE); VerifyOrExit(result == WICED_SUCCESS, err = CHIP_ERROR_NO_MEMORY); /* Initialize the timer. */ result = wiced_init_timer(&mTimer, TimerCallback, 0, WICED_MILLI_SECONDS_TIMER); VerifyOrExit(result == WICED_SUCCESS, err = CHIP_ERROR_INTERNAL); /* Initialize the mutex. */ mMutex = wiced_rtos_create_mutex(); VerifyOrExit(mMutex != nullptr, err = CHIP_ERROR_NO_MEMORY); result = wiced_rtos_init_mutex(mMutex); VerifyOrExit(result == WICED_SUCCESS, err = CHIP_ERROR_INTERNAL); ReturnErrorOnFailure(chip::Crypto::add_entropy_source(GetEntropy, NULL, 16)); ReturnErrorOnFailure(GenericPlatformManagerImpl::_InitChipStack()); exit: return err; } void PlatformManagerImpl::_RunEventLoop(void) { ChipLogDetail(DeviceLayer, "Free RAM sizes: %lu\n", wiced_memory_get_free_bytes()); while (true) { uint32_t flags_set = 0; if (mEventFlags.WaitAnyForever(flags_set) != CHIP_NO_ERROR) { continue; } if (flags_set & kTimerEventFlag) { HandleTimerEvent(); } if (flags_set & kPostEventFlag) { HandlePostEvent(); } } } CHIP_ERROR PlatformManagerImpl::_StartEventLoopTask(void) { CHIP_ERROR err = CHIP_NO_ERROR; wiced_result_t result; result = wiced_rtos_init_thread(mThread, CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY, CHIP_DEVICE_CONFIG_CHIP_TASK_NAME, EventLoopTaskMain, CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE, this); VerifyOrExit(result == WICED_SUCCESS, err = CHIP_ERROR_NO_MEMORY); exit: return err; } CHIP_ERROR PlatformManagerImpl::_StopEventLoopTask() { return CHIP_NO_ERROR; } void PlatformManagerImpl::_LockChipStack(void) { const wiced_result_t result = wiced_rtos_lock_mutex(mMutex); VerifyOrReturn(result == WICED_SUCCESS, ChipLogError(DeviceLayer, "%s %x", __func__, result)); } void PlatformManagerImpl::_UnlockChipStack(void) { const wiced_result_t result = wiced_rtos_unlock_mutex(mMutex); VerifyOrReturn(result == WICED_SUCCESS || result == WICED_NOT_OWNED, ChipLogError(DeviceLayer, "%s %x", __func__, result)); } CHIP_ERROR PlatformManagerImpl::_PostEvent(const ChipDeviceEvent * event) { const wiced_result_t result = wiced_rtos_push_to_queue(mEventQueue, const_cast(event), WICED_NO_WAIT); if (WICED_SUCCESS != result) { ChipLogError(DeviceLayer, "wiced_rtos_push_to_queue %u", result); return CHIP_ERROR_INTERNAL; } mEventFlags.Set(kPostEventFlag); return CHIP_NO_ERROR; } CHIP_ERROR PlatformManagerImpl::_StartChipTimer(System::Clock::Timeout durationMS) { if (durationMS.count() == 0) { TimerCallback(0); } else { const wiced_result_t result = wiced_start_timer(&mTimer, durationMS.count()); if (WICED_SUCCESS != result) { ChipLogError(DeviceLayer, "wiced_start_timer 0x%02x", result); return CHIP_ERROR_INTERNAL; } } return CHIP_NO_ERROR; } void PlatformManagerImpl::_Shutdown() {} void PlatformManagerImpl::HandleTimerEvent(void) { const CHIP_ERROR err = static_cast(DeviceLayer::SystemLayer()).HandlePlatformTimer(); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "HandlePlatformTimer %ld", err.AsInteger()); } } void PlatformManagerImpl::HandlePostEvent(void) { wiced_result_t result; ChipDeviceEvent event; /* Check the event queue. */ if (wiced_rtos_is_queue_empty(mEventQueue)) { return; } /* Pop one event from the event queue. */ result = wiced_rtos_pop_from_queue(mEventQueue, &event, WICED_WAIT_FOREVER); if (WICED_SUCCESS != result) { ChipLogError(DeviceLayer, "wiced_rtos_pop_from_queue %u", result); return; } /* Process this event. */ DispatchEvent(&event); /* Set another application thread event if the event queue is not empty. */ if (!wiced_rtos_is_queue_empty(mEventQueue)) { mEventFlags.Set(kPostEventFlag); } } void PlatformManagerImpl::EventLoopTaskMain(uint32_t arg) { ChipLogDetail(DeviceLayer, "CHIP task running"); reinterpret_cast(arg)->RunEventLoop(); } void PlatformManagerImpl::TimerCallback(WICED_TIMER_PARAM_TYPE params) { PlatformMgrImpl().mEventFlags.Set(kTimerEventFlag); } int PlatformManagerImpl::GetEntropy(void * data, unsigned char * output, size_t len, size_t * olen) { const wiced_result_t result = wiced_hal_platform_random_get(output, len, olen); if (result != WICED_SUCCESS) { return -1; } return 0; } } // namespace DeviceLayer } // namespace chip