// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "service-evtmgr/EVMessages.hpp" #include "service-evtmgr/KbdMessage.hpp" #include "service-evtmgr/ServiceEventManagerName.hpp" #include "service-evtmgr/WorkerEventCommon.hpp" #include "battery/BatteryController.hpp" #include #include #include #include #include #include #include #include #include "task.h" #include #include #include #include WorkerEventCommon::WorkerEventCommon(sys::Service *service) : sys::Worker(service, stackDepthBytes), service(service), keyInput{hal::key_input::AbstractKeyInput::Factory::create()} {} bool WorkerEventCommon::handleMessage(std::uint32_t queueID) { #if DEBUG_HEAP_ALLOCATIONS == 1 LOG_INFO("Free space: %zu", usermemGetFreeHeapSize()); #endif auto &queue = queues[queueID]; // service queue if (queueID == static_cast(WorkerEventQueues::queueService)) { sys::WorkerCommand wcmd; if (!queue->Dequeue(&wcmd, 0)) { return false; } wcmd.command = 1; // place some code here to handle messages from service } if (queueID == static_cast(WorkerEventQueues::queueKeyboardIRQ)) { std::uint8_t notification; if (!queue->Dequeue(¬ification, 0)) { return false; } for (const auto &key : keyInput->getKeyEvents(notification)) { processKeyEvent(key.event, key.code); } } if (queueID == static_cast(WorkerEventQueues::queueBatteryController)) { sevm::battery::BatteryController::Events event; if (!queue->Dequeue(&event, 0)) { return false; } batteryController->handleNotification(event); } if (queueID == static_cast(WorkerEventQueues::queueRTC)) { std::uint8_t notification; if (!queue->Dequeue(¬ification, 0)) { return false; } std::time_t timestamp; bsp::rtc::getCurrentTimestamp(×tamp); bsp::rtc::setMinuteAlarm(timestamp); /// Poll battery controller to recalculate state and possibly send update requests to /// appmgr/sysmgr batteryController->poll(); auto message = std::make_shared(MessageType::EVMMinuteUpdated); message->timestamp = timestamp; service->bus.sendUnicast(std::move(message), service::name::evt_manager); } return true; } void WorkerEventCommon::addProductQueues(std::list &queueList) {} void WorkerEventCommon::initProductHardware() {} void WorkerEventCommon::deinitProductHardware() {} bool WorkerEventCommon::initEventQueues() { constexpr auto elementSize = sizeof(std::uint8_t); std::list queuesList; queuesList.emplace_back(keyboardQueueName, elementSize, keyboardQueueSize); queuesList.emplace_back(batteryQueueName, elementSize, batteryQueueSize); queuesList.emplace_back(rtcQueueName, elementSize, rtcQueueSize); addProductQueues(queuesList); return Worker::init(queuesList); } bool WorkerEventCommon::initCommonHardwareComponents(EventManagerParams params) { keyInput->init(queues[static_cast(WorkerEventQueues::queueKeyboardIRQ)]->GetQueueHandle()); const auto queueBatteryHandle = queues[static_cast(WorkerEventQueues::queueBatteryController)]->GetQueueHandle(); batteryController = std::make_shared(service, queueBatteryHandle, params); std::time_t timestamp; bsp::rtc::init(queues[static_cast(WorkerEventQueues::queueRTC)]->GetQueueHandle()); bsp::rtc::getCurrentTimestamp(×tamp); bsp::rtc::setMinuteAlarm(timestamp); cpuSentinel = std::make_shared("WorkerEvent", service, [this](bsp::CpuFrequencyMHz newFrequency) { updateResourcesAfterCpuFrequencyChange(newFrequency); }); auto sentinelRegistrationMsg = std::make_shared(cpuSentinel); service->bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager); initProductHardware(); return true; } void WorkerEventCommon::init(std::shared_ptr settings, EventManagerParams params) { initEventQueues(); initCommonHardwareComponents(params); } bool WorkerEventCommon::deinit() { Worker::deinit(); keyInput->deinit(); return true; } void WorkerEventCommon::sendKeyUnicast(RawKey const &key) { auto message = std::make_shared(); message->key = key; service->bus.sendUnicast(std::move(message), service::name::evt_manager); } void WorkerEventCommon::processKeyEvent(bsp::KeyEvents event, bsp::KeyCodes code) { switch (event) { case bsp::KeyEvents::Pressed: { auto const tick = xTaskGetTickCount(); if (lastState == bsp::KeyEvents::Pressed) { LOG_WARN("Generating release %s", c_str(lastPressed)); sendKeyUnicast({RawKey::State::Released, lastPressed, 0, tick}); } sendKeyUnicast({RawKey::State::Pressed, code, tick, 0}); lastState = bsp::KeyEvents::Pressed; lastPressed = code; break; } case bsp::KeyEvents::Released: if (lastState != bsp::KeyEvents::Pressed || lastPressed != code) { return; } sendKeyUnicast({RawKey::State::Released, code, 0, xTaskGetTickCount()}); lastState = bsp::KeyEvents::Released; lastPressed = code; break; case bsp::KeyEvents::Moved: sendKeyUnicast({RawKey::State::Moved, code}); break; } } void WorkerEventCommon::updateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency) { bsp::eink_frontlight::updateClockFrequency(newFrequency); bsp::vibrator::updateClockFrequency(newFrequency); }