~aleteoryx/muditaos

6e12e5834fbcb1b93cded4cace4253b99b38d685 — Kuba 4 years ago 17417f8
[EGD-7738] Fix modem reset

Fixed modem reset procedur so now it will not stuck in cellular
init on factory fresh phone. Also removed T3/T4 board recognition.
31 files changed, 290 insertions(+), 216 deletions(-)

M module-apps/application-desktop/ApplicationDesktop.cpp
M module-apps/application-desktop/CMakeLists.txt
M module-apps/application-desktop/include/application-desktop/ApplicationDesktop.hpp
M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/application-settings/include/application-settings/ApplicationSettings.hpp
M module-bsp/board/linux/cellular/linux_cellular.cpp
M module-bsp/board/linux/cellular/linux_cellular.hpp
M module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.cpp
M module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.hpp
M module-bsp/board/rt1051/bsp/magnetometer/magnetometer.cpp
M module-bsp/bsp/cellular/bsp_cellular.hpp
M module-bsp/bsp/common.cpp
M module-bsp/bsp/common.hpp
M module-bsp/bsp/magnetometer/magnetometer.hpp
M module-cellular/modem/mux/CellularMux.cpp
M module-cellular/modem/mux/CellularMux.h
M module-services/service-cellular/CMakeLists.txt
M module-services/service-cellular/NetworkSettings.cpp
M module-services/service-cellular/ServiceCellular.cpp
M module-services/service-cellular/include/service-cellular/State.hpp
M module-services/service-cellular/service-cellular/ServiceCellular.hpp
A module-services/service-cellular/src/ModemResetHandler.cpp
A module-services/service-cellular/src/ModemResetHandler.hpp
M module-services/service-cellular/src/ServiceCellularPriv.cpp
M module-services/service-cellular/src/ServiceCellularPriv.hpp
M module-services/service-cellular/src/State.cpp
M module-services/service-evtmgr/api/EventManagerServiceAPI.cpp
M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp
M module-services/service-evtmgr/service-evtmgr/EventManagerServiceAPI.hpp
M products/PurePhone/services/evtmgr/EventManager.cpp
M source/MessageType.hpp
M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +0 -18
@@ 78,12 78,6 @@ namespace app
            switchWindow(app::window::name::logo_window, std::move(data));
            return actionHandled();
        });

        connect(typeid(cellular::msg::notification::ModemStateChanged), [this](sys::Message *request) {
            auto msg = static_cast<cellular::msg::notification::ModemStateChanged *>(request);
            handle(msg);
            return sys::MessageNone{};
        });
    }

    // Invoked upon receiving data message


@@ 126,14 120,6 @@ namespace app
        }
    }

    void ApplicationDesktop::handle(cellular::msg::notification::ModemStateChanged *msg)
    {
        assert(msg);
        if (msg->state == cellular::api::ModemState::Fatal) {
            switchWindow(app::window::name::desktop_reboot);
        }
    }

    // Invoked during initialization
    sys::ReturnCodes ApplicationDesktop::InitHandler()
    {


@@ 173,10 159,6 @@ namespace app
        windowsFactory.attach(charging_battery, [](ApplicationCommon *app, const std::string newname) {
            return std::make_unique<gui::ChargingBatteryWindow>(app);
        });
        windowsFactory.attach(desktop_reboot, [](ApplicationCommon *app, const std::string newname) {
            auto presenter = std::make_unique<gui::PowerOffPresenter>(app);
            return std::make_unique<gui::RebootWindow>(app, std::move(presenter));
        });
        windowsFactory.attach(desktop_mmi_pull, [](ApplicationCommon *app, const std::string newname) {
            return std::make_unique<gui::MmiPullWindow>(app, desktop_mmi_pull);
        });

M module-apps/application-desktop/CMakeLists.txt => module-apps/application-desktop/CMakeLists.txt +0 -2
@@ 42,8 42,6 @@ target_sources(application-desktop
		windows/MmiPullWindow.hpp
		windows/MmiPushWindow.cpp
		windows/MmiPushWindow.hpp
		windows/Reboot.cpp
		windows/Reboot.hpp
	PUBLIC
		include/application-desktop/ApplicationDesktop.hpp
		include/application-desktop/Constants.hpp

M module-apps/application-desktop/include/application-desktop/ApplicationDesktop.hpp => module-apps/application-desktop/include/application-desktop/ApplicationDesktop.hpp +0 -6
@@ 11,11 11,6 @@
#include <service-desktop/DesktopMessages.hpp>
#include <Service/Message.hpp>

namespace cellular::msg::notification
{
    class ModemStateChanged;
}

namespace gui
{
    class NotificationsModel;


@@ 42,7 37,6 @@ namespace app
        void destroyUserInterface() override;
        // if there is modem notification and there is no default SIM selected, then we need to select if when unlock is
        // done
        void handle(cellular::msg::notification::ModemStateChanged *msg);
        void handleNotificationsChanged(std::unique_ptr<gui::SwitchData> notificationsParams) override;

        void setOsUpdateVersion(const std::string &value);

M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +0 -2
@@ 145,8 145,6 @@ namespace app
    // Invoked during initialization
    auto ApplicationSettings::InitHandler() -> sys::ReturnCodes
    {
        board = EventManagerServiceAPI::GetBoard(this);

        auto ret = Application::InitHandler();
        if (ret != sys::ReturnCodes::Success) {
            return ret;

M module-apps/application-settings/include/application-settings/ApplicationSettings.hpp => module-apps/application-settings/include/application-settings/ApplicationSettings.hpp +1 -1
@@ 180,7 180,7 @@ namespace app
        std::shared_ptr<SoundsPlayer> soundsPlayer;
        Store::GSM::SIM selectedSim   = Store::GSM::get()->selected;
        std::string selectedSimNumber = {};
        bsp::Board board              = bsp::Board::none;

        bool operatorsOn              = false;
        bool voLteStateOn             = false;
        bool notificationsWhenLocked  = true;

M module-bsp/board/linux/cellular/linux_cellular.cpp => module-bsp/board/linux/cellular/linux_cellular.cpp +4 -0
@@ 211,6 211,10 @@ namespace bsp
    {
        return bsp::cellular::antenna::lowBand;
    }
    bsp::Board LinuxCellular::getBoard()
    {
        return bsp::Board::Linux;
    }

    namespace cellular
    {

M module-bsp/board/linux/cellular/linux_cellular.hpp => module-bsp/board/linux/cellular/linux_cellular.hpp +2 -0
@@ 50,6 50,8 @@ namespace bsp
        void selectAntenna(bsp::cellular::antenna antenna) override final;
        bsp::cellular::antenna getAntenna() override final;

        bsp::Board getBoard() final;

      private:
        static constexpr speed_t baud_bits[] = {0,
                                                B9600,

M module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.cpp => module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.cpp +4 -0
@@ 657,6 657,10 @@ namespace bsp
        LOG_PRINTF("}\n");
#endif
    }
    bsp::Board RT1051Cellular::getBoard()
    {
        return bsp::Board::RT1051;
    }

    namespace cellular
    {

M module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.hpp => module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.hpp +2 -0
@@ 50,6 50,8 @@ namespace bsp
        void selectAntenna(bsp::cellular::antenna antenna) override final;
        bsp::cellular::antenna getAntenna() override final;

        bsp::Board getBoard() final;

        static MessageBufferHandle_t uartRxBuffer;
        static lpuart_edma_handle_t uartDmaHandle;
        static bool RestartReceivingManually;

M module-bsp/board/rt1051/bsp/magnetometer/magnetometer.cpp => module-bsp/board/rt1051/bsp/magnetometer/magnetometer.cpp +0 -8
@@ 349,14 349,6 @@ namespace bsp
            return xHigherPriorityTaskWoken;
        }

        bsp::Board GetBoard(void)
        {
            if (isPresent()) {
                return bsp::Board::T4;
            }
            return bsp::Board::T3;
        }

        void enableIRQ()
        {
            gpio->EnableInterrupt(1 << static_cast<uint32_t>(BoardDefinitions::MAGNETOMETER_IRQ));

M module-bsp/bsp/cellular/bsp_cellular.hpp => module-bsp/bsp/cellular/bsp_cellular.hpp +5 -0
@@ 1,6 1,8 @@
#ifndef PUREPHONE_BSP_CELLULAR_HPP
#define PUREPHONE_BSP_CELLULAR_HPP

#include <bsp/common.hpp>

#include <optional>
#include <stdint.h>
#include <stddef.h>


@@ 20,6 22,7 @@ namespace bsp
            lowBand,
            highBand
        };

    }
    class Cellular
    {


@@ 59,6 62,8 @@ namespace bsp
        virtual void selectAntenna(bsp::cellular::antenna antenna) = 0;
        virtual bsp::cellular::antenna getAntenna()                = 0;

        virtual bsp::Board getBoard() = 0;

        [[nodiscard]] auto getCellularDevice() const noexcept -> std::shared_ptr<devices::Device>;
        [[nodiscard]] auto getLastCommunicationTimestamp() const noexcept -> TickType_t;
        [[nodiscard]] auto isCellularInSleepMode() const noexcept -> bool;

M module-bsp/bsp/common.cpp => module-bsp/bsp/common.cpp +2 -5
@@ 4,11 4,8 @@ namespace bsp{
   	const char *c_str(const Board &board)
    {
            switch (board) {
            case Board::T3:
                return "T3";
                break;
            case Board::T4:
                return "T4";
            case Board::RT1051:
                return "RT1051";
                break;
            case Board::Linux:
                return "Linux";

M module-bsp/bsp/common.hpp => module-bsp/bsp/common.hpp +1 -2
@@ 25,8 25,7 @@ namespace bsp
    };

    enum class Board{
    	T3,
    	T4,
        RT1051,
    	Linux,
    	none
    };

M module-bsp/bsp/magnetometer/magnetometer.hpp => module-bsp/bsp/magnetometer/magnetometer.hpp +0 -2
@@ 24,8 24,6 @@ namespace bsp

        bool isPresent(void);

        bsp::Board GetBoard(void);

        /// unit: 4 LSB/Gauss
        struct Measurements
        {

M module-cellular/modem/mux/CellularMux.cpp => module-cellular/modem/mux/CellularMux.cpp +6 -2
@@ 298,8 298,7 @@ CellularMux::ConfState CellularMux::audioConfProcedure()
            return ConfState::Failure;
        }
        else {
            cellular->restart();
            LOG_DEBUG("GSM module first run, performing reset...");
            LOG_DEBUG("GSM module first run, performing reboot.");
            return ConfState::ModemNeedsReset;
        }
    }


@@ 839,3 838,8 @@ bool CellularMux::checkATCommandPrompt(const std::vector<std::string> &response,
{
    return searchATCommandResponse(response, ">", 0, level);
}

bsp::Board CellularMux::getBoard()
{
    return cellular->getBoard();
}

M module-cellular/modem/mux/CellularMux.h => module-cellular/modem/mux/CellularMux.h +2 -0
@@ 338,6 338,8 @@ class CellularMux
    void selectAntenna(bsp::cellular::antenna antenna);
    [[nodiscard]] bsp::cellular::antenna getAntenna();

    bsp::Board getBoard();

    void informModemHostWakeup();
    bool isModemActive();
    void turnOnModem();

M module-services/service-cellular/CMakeLists.txt => module-services/service-cellular/CMakeLists.txt +1 -0
@@ 12,6 12,7 @@ set(SOURCES
    src/SMSSendHandler.cpp
    src/ImeiGetHandler.cpp
    src/TerhetingHandler.cpp
    src/ModemResetHandler.cpp

    CellularCall.cpp
    CellularServiceAPI.cpp

M module-services/service-cellular/NetworkSettings.cpp => module-services/service-cellular/NetworkSettings.cpp +0 -2
@@ 323,8 323,6 @@ at::Result::Code NetworkSettings::setVoLTEState(VoLTEState state)
        qmbn.setAutoSelect(at::response::qmbncfg::MBNAutoSelect::On);
    }
    LOG_DEBUG("Modem soft reboot");
    cellularService.resetCellularModule(ServiceCellular::ResetType::SoftReset);

    return at::Result::Code::OK;
}


M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +66 -109
@@ 218,7 218,7 @@ void ServiceCellular::CallStateTimerHandler()

sys::ReturnCodes ServiceCellular::InitHandler()
{
    board = EventManagerServiceAPI::GetBoard(this);
    board = cmux->getBoard();

    settings = std::make_unique<settings::Settings>();
    settings->init(::service::ServiceProxy(shared_from_this()));


@@ 365,11 365,15 @@ void ServiceCellular::registerMessageHandlers()
        auto vstate = networkSettings.getVoLTEConfigurationState();
        if ((vstate != VoLTEState::On) && volteOn) {
            LOG_DEBUG("VoLTE On");
            networkSettings.setVoLTEState(VoLTEState::On);
            if (networkSettings.setVoLTEState(VoLTEState::On) == at::Result::Code::OK) {
                priv->modemResetHandler->performSoftReset();
            }
        }
        else if (!volteOn) {
            LOG_DEBUG("VoLTE Off");
            networkSettings.setVoLTEState(VoLTEState::Off);
            if (networkSettings.setVoLTEState(VoLTEState::Off) == at::Result::Code::OK) {
                priv->modemResetHandler->performSoftReset();
            }
        }
        return std::make_shared<CellularResponseMessage>(true);
    });


@@ 573,37 577,6 @@ void ServiceCellular::registerMessageHandlers()
    handle_CellularGetChannelMessage();
}

bool ServiceCellular::resetCellularModule(ResetType type)
{
    LOG_DEBUG("Cellular modem reset. Type %d", static_cast<int>(type));

    auto channel = cmux->get(CellularMux::Channel::Commands);
    if (!channel) {
        LOG_ERROR("Bad channel");
        return false;
    }

    switch (type) {
    case ResetType::SoftReset:
        if (auto response = channel->cmd(at::AT::CFUN_RESET); response.code == at::Result::Code::OK) {
            isAfterForceReboot = true;
            return true;
        }
        LOG_ERROR("Cellular modem reset failed.");
        return false;
    case ResetType::PowerCycle:
        cmux->turnOffModem();
        cmux->turnOnModem();
        isAfterForceReboot = true;
        return true;
    case ResetType::HardReset:
        cmux->resetModem();
        isAfterForceReboot = true;
        return true;
    }
    return false;
}

void ServiceCellular::change_state(cellular::StateChange *msg)
{
    assert(msg);


@@ 637,6 610,9 @@ void ServiceCellular::change_state(cellular::StateChange *msg)
    case State::ST::AudioConfigurationProcedure:
        handle_audio_conf_procedure();
        break;
    case State::ST::CellularPrivInit:
        handle_cellular_priv_init();
        break;
    case State::ST::CellularConfProcedure:
        handle_start_conf_procedure();
        break;


@@ 694,12 670,9 @@ bool ServiceCellular::handle_power_up_request()
{
    cmux->selectAntenna(bsp::cellular::antenna::lowBand);
    switch (board) {
    case bsp::Board::T4:
    case bsp::Board::RT1051:
        priv->state->set(State::ST::StatusCheck);
        break;
    case bsp::Board::T3:
        priv->state->set(State::ST::PowerUpProcedure);
        break;
    case bsp::Board::Linux:
        priv->state->set(State::ST::PowerUpProcedure);
        break;


@@ 713,33 686,13 @@ bool ServiceCellular::handle_power_up_request()
bool ServiceCellular::handle_power_up_procedure()
{
    switch (board) {
    case bsp::Board::T4: {
        LOG_DEBUG("T4 - cold start");
    case bsp::Board::RT1051: {
        LOG_DEBUG("RT1051 - cold start");
        cmux->turnOnModem();
        // wait for status pin change to change state
        break;
    }
    case bsp::Board::T3: {
        // check baud once to determine if it's already turned on
        auto ret = cmux->baudDetectOnce();
        if (ret == CellularMux::ConfState::Success) {
            // it's on aka hot start.
            LOG_DEBUG("T3 - hot start");
            priv->state->set(State::ST::CellularConfProcedure);
            break;
        }
        else {
            // it's off aka cold start
            LOG_DEBUG("T3 - cold start");
            cmux->turnOnModem();
            // if it's T3, then wait for status pin to become active, to align its starting position with T4
            vTaskDelay(pdMS_TO_TICKS(8000));
            priv->state->set(State::ST::PowerUpInProgress);
            break;
        }
    }
    case bsp::Board::Linux: {
        // it is basically the same as T3
        // check baud once to determine if it's already turned on
        auto ret = cmux->baudDetectOnce();
        if (ret == CellularMux::ConfState::Success) {


@@ 753,7 706,7 @@ bool ServiceCellular::handle_power_up_procedure()
            LOG_DEBUG("Linux - cold start");
            LOG_WARN("Press PWR_KEY for 2 sec on modem eval board!");
            vTaskDelay(pdMS_TO_TICKS(2000)); // give some 2 secs more for user input
            // if it's Linux (T3), then wait for status pin to become active, to align its starting position with T4
            // if it's Linux, then wait for status pin to become active, to align its starting position with RT1051
            vTaskDelay(pdMS_TO_TICKS(8000));
            priv->state->set(State::ST::PowerUpInProgress);
            break;


@@ 770,10 723,9 @@ bool ServiceCellular::handle_power_up_procedure()

bool ServiceCellular::handle_power_up_in_progress_procedure(void)
{
    if (isAfterForceReboot) {
    if (priv->modemResetHandler->isResetInProgress()) {
        constexpr auto msModemUartInitTime = 12000;
        vTaskDelay(pdMS_TO_TICKS(msModemUartInitTime));
        isAfterForceReboot = false;
    }

    priv->state->set(State::ST::BaudDetect);


@@ 802,12 754,11 @@ bool ServiceCellular::handle_power_down_started()
bool ServiceCellular::handle_power_down_waiting()
{
    switch (board) {
    case bsp::Board::T4:
    case bsp::Board::RT1051:
        // wait for pin status become inactive (handled elsewhere)
        break;
    case bsp::Board::Linux:
    case bsp::Board::T3:
        // if it's T3, then wait for status pin to become inactive, to align with T4
        // if it's Linux, then wait for status pin to become inactive, to align with RT1051
        vTaskDelay(pdMS_TO_TICKS(17000)); // according to docs this shouldn't be needed, but better be safe than Quectel
        priv->state->set(State::ST::PowerDown);
        break;


@@ 821,12 772,11 @@ bool ServiceCellular::handle_power_down_waiting()
bool ServiceCellular::handle_power_down()
{
    LOG_DEBUG("Powered Down");

    cmux->closeChannels();
    cmux.reset();
    cmux = std::make_unique<CellularMux>(PortSpeed_e::PS460800, this);

    if (isAfterForceReboot) {
        priv->state->set(State::ST::PowerUpInProgress);
    if (priv->modemResetHandler->isResetInProgress()) {
        priv->state->set(State::ST::Idle);
    }
    return true;
}


@@ 846,6 796,11 @@ bool ServiceCellular::handle_start_conf_procedure()
bool ServiceCellular::handle_audio_conf_procedure()
{
    auto audioRet = cmux->audioConfProcedure();
    if (audioRet == CellularMux::ConfState::ModemNeedsReset) {
        priv->modemResetHandler->performReboot();
        return false;
    }

    if (audioRet == CellularMux::ConfState::Success) {
        auto cmd = at::factory(at::AT::IPR) + std::to_string(ATPortSpeeds_text[cmux->getStartParams().PortSpeed]);
        LOG_DEBUG("Setting baudrate %i baud", ATPortSpeeds_text[cmux->getStartParams().PortSpeed]);


@@ 860,40 815,14 @@ bool ServiceCellular::handle_audio_conf_procedure()
        if (cmux->startMultiplexer() == CellularMux::ConfState::Success) {

            LOG_DEBUG("[ServiceCellular] Modem is fully operational");

            priv->simCard->setChannel(cmux->get(CellularMux::Channel::Commands));
            priv->networkTime->setChannel(cmux->get(CellularMux::Channel::Commands));
            priv->simContacts->setChannel(cmux->get(CellularMux::Channel::Commands));
            priv->imeiGetHandler->setChannel(cmux->get(CellularMux::Channel::Commands));
            // open channel - notifications
            DLCChannel *notificationsChannel = cmux->get(CellularMux::Channel::Notifications);
            if (notificationsChannel != nullptr) {
                LOG_DEBUG("Setting up notifications callback");
                notificationsChannel->setCallback(notificationCallback);
            }
            auto flightMode =
                settings->getValue(settings::Cellular::offlineMode, settings::SettingsScope::Global) == "1" ? true
                                                                                                            : false;
            connectionManager->setFlightMode(flightMode);
            auto interval = 0;
            if (utils::toNumeric(
                    settings->getValue(settings::Offline::connectionFrequency, settings::SettingsScope::Global),
                    interval)) {
                connectionManager->setInterval(std::chrono::minutes{interval});
            }
            if (!connectionManager->onPhoneModeChange(phoneModeObserver->getCurrentPhoneMode())) {
                priv->state->set(State::ST::Failed);
                LOG_ERROR("Failed to handle phone mode");
                return false;
            }

            if (!priv->tetheringHandler->configure()) {
                resetCellularModule(ResetType::SoftReset);
                priv->state->set(State::ST::Idle);
                return true;
            }

            priv->state->set(State::ST::APNConfProcedure);
            priv->state->set(State::ST::CellularPrivInit);
            return true;
        }
        else {


@@ 911,6 840,35 @@ bool ServiceCellular::handle_audio_conf_procedure()
    return true;
}

bool ServiceCellular::handle_cellular_priv_init()
{
    auto channel = cmux->get(CellularMux::Channel::Commands);
    priv->simCard->setChannel(channel);
    priv->networkTime->setChannel(channel);
    priv->simContacts->setChannel(channel);
    priv->imeiGetHandler->setChannel(channel);

    if (!priv->tetheringHandler->configure()) {
        priv->modemResetHandler->performHardReset();
        return true;
    }

    auto flightMode =
        settings->getValue(settings::Cellular::offlineMode, settings::SettingsScope::Global) == "1" ? true : false;
    connectionManager->setFlightMode(flightMode);
    auto interval = 0;
    if (utils::toNumeric(settings->getValue(settings::Offline::connectionFrequency, settings::SettingsScope::Global),
                         interval)) {
        connectionManager->setInterval(std::chrono::minutes{interval});
    }
    if (!connectionManager->onPhoneModeChange(phoneModeObserver->getCurrentPhoneMode())) {
        priv->state->set(State::ST::Failed);
        LOG_ERROR("Failed to handle phone mode");
        return false;
    }
    priv->state->set(State::ST::APNConfProcedure);
    return true;
}
auto ServiceCellular::handle(db::query::SMSSearchByTypeResult *response) -> bool
{
    if (response->getResults().empty()) {


@@ 1271,8 1229,8 @@ bool ServiceCellular::handle_sim_sanity_check()
        priv->state->set(State::ST::ModemOn);
    }
    else {
        LOG_ERROR("Sanity check failure - user will be promped about full shutdown");
        priv->state->set(State::ST::ModemFatalFailure);
        LOG_ERROR("Sanity check failure - modem has to be rebooted");
        priv->modemResetHandler->performHardReset();
    }
    return ret;
}


@@ 1409,6 1367,7 @@ bool ServiceCellular::handle_fatal_failure()

bool ServiceCellular::handle_ready()
{

    LOG_DEBUG("%s", priv->state->c_str());
    sleepTimer.start();
    return true;


@@ 1483,7 1442,7 @@ bool ServiceCellular::handle_status_check(void)
    if (modemActive) {
        // modem is already turned on, call configutarion procedure
        LOG_INFO("Modem is already turned on.");
        LOG_DEBUG("T4 - hot start");
        LOG_DEBUG("RT1051 - hot start");
        priv->state->set(State::ST::PowerUpInProgress);
    }
    else {


@@ 2002,23 1961,21 @@ auto ServiceCellular::handleEVMStatusMessage(sys::Message *msg) -> std::shared_p
{
    using namespace bsp::cellular::status;
    auto message = static_cast<sevm::StatusStateMessage *>(msg);
    if (board == bsp::Board::T4) {
        auto status_pin = message->state;
        if (priv->modemResetHandler->handleStatusPinEvent(status_pin == value::ACTIVE)) {
            return std::make_shared<CellularResponseMessage>(true);
        }

        if (status_pin == value::ACTIVE) {
            if (priv->state->get() == State::ST::PowerUpProcedure) {
                priv->state->set(State::ST::PowerUpInProgress); // and go to baud detect as usual
            }
            else {
                // asynchronous power toggle should fall back to PowerDown regardless the state
                priv->state->set(State::ST::PowerDown);
            }
        }
        else if (status_pin == value::INACTIVE) {
            if (isAfterForceReboot == true || priv->state->get() == State::ST::PowerDownWaiting) {
        if (status_pin == value::INACTIVE) {
            if (priv->state->get() == State::ST::PowerDownWaiting) {
                priv->state->set(State::ST::PowerDown);
            }
        }
    }
    return std::make_shared<CellularResponseMessage>(true);
}



@@ 2113,7 2070,7 @@ auto ServiceCellular::handleCallAbortedNotification(sys::Message *msg) -> std::s
auto ServiceCellular::handlePowerUpProcedureCompleteNotification(sys::Message *msg)
    -> std::shared_ptr<sys::ResponseMessage>
{
    if (board == bsp::Board::T3 || board == bsp::Board::Linux) {
    if (board == bsp::Board::Linux) {
        priv->state->set(State::ST::CellularConfProcedure);
    }
    return std::make_shared<CellularResponseMessage>(true);

M module-services/service-cellular/include/service-cellular/State.hpp => module-services/service-cellular/include/service-cellular/State.hpp +3 -2
@@ 24,10 24,11 @@ namespace cellular::service
            BaudDetect,                  /// baud detection procedure
            CellularConfProcedure,       /// configuration procedure
            AudioConfigurationProcedure, /// audio configuration for modem (could be in ModemConfiguration)
            CellularPrivInit,            /// init cellular internal modules
            APNConfProcedure,            /// Configure APN set by user, check if modem have similar
            SanityCheck,                 /// prior to ModemOn last sanity checks for one time configurations etc
            ModemOn,   /// modem ready - indicates that modem is fully configured, ( **SIM is not yet configured** )
            URCReady,  /// State indicates that URC handling is enabled
            ModemOn,  /// modem ready - indicates that modem is fully configured, ( **SIM is not yet configured** )
            URCReady, /// State indicates that URC handling is enabled
            ModemFatalFailure, /// modem full shutdown need
            Failed,
            Ready,            /// Service is fully initialized

M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +2 -9
@@ 141,15 141,6 @@ class ServiceCellular : public sys::Service

    ussd::State ussdState = ussd::State::none;

    enum class ResetType
    {
        SoftReset,  //<! AT CFUN reset
        PowerCycle, //<! PWRKEY pin toggle
        HardReset   //<! RESET_N pin
    };

    bool resetCellularModule(ResetType type);
    bool isAfterForceReboot           = false;
    bool nextPowerStateChangeAwaiting = false;

    /// one point of state change handling


@@ 181,6 172,8 @@ class ServiceCellular : public sys::Service
    bool handle_start_conf_procedure();
    /// configure modem audio parameters
    bool handle_audio_conf_procedure();
    /// init cellular internal modules
    bool handle_cellular_priv_init();
    /// modem on event is used in desktop to follow up sim selection
    bool handle_modem_on();
    /// URCReady event is set when serwice is ready to handle URC notifications

A module-services/service-cellular/src/ModemResetHandler.cpp => module-services/service-cellular/src/ModemResetHandler.cpp +90 -0
@@ 0,0 1,90 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ModemResetHandler.hpp"

#include <module-utils/log/Logger.hpp>

namespace cellular::service
{
    auto ModemResetHandler::performSoftReset() -> bool
    {
        if (procedureInProgress != ProcedureInProgress::None) {
            LOG_ERROR("Modem reset procedure is already in progress! Skip request.");
            return false;
        }

        procedureInProgress = ProcedureInProgress::SoftReset;
        onCellularStateSet(State::ST::PowerDownWaiting);
        return onSoftReset();
    }

    auto ModemResetHandler::performHardReset() -> bool
    {
        if (procedureInProgress != ProcedureInProgress::None) {
            LOG_ERROR("Modem reset procedure is already in progress! Skip request.");
            return false;
        }

        procedureInProgress = ProcedureInProgress::HardReset;
        onCellularStateSet(State::ST::PowerDownWaiting);
        onHardReset();
        return false;
    }

    auto ModemResetHandler::performReboot() -> bool
    {
        if (procedureInProgress != ProcedureInProgress::None) {
            LOG_ERROR("Modem reset procedure is already in progress! Skip request.");
            return false;
        }

        procedureInProgress = ProcedureInProgress::Reboot;
        onCellularStateSet(State::ST::PowerDownWaiting);
        onTurnModemOff();
        return false;
    }

    auto ModemResetHandler::handleStatusPinEvent(bool isActive) -> bool
    {
        if (isActive) {
            return handleSwitchToActive();
        }
        return handleSwitchToInactive();
    }

    auto ModemResetHandler::isResetInProgress() -> bool
    {
        return procedureInProgress != ProcedureInProgress::None;
    }
    auto ModemResetHandler::handleSwitchToInactive() -> bool
    {
        switch (procedureInProgress) {
        case ProcedureInProgress::None:
            return false;
        case ProcedureInProgress::SoftReset:
        case ProcedureInProgress::HardReset:
            onCellularStateSet(State::ST::PowerDown);
            return true;
        case ProcedureInProgress::Reboot:
            auto constexpr delay50ms = 50;
            vTaskDelay(delay50ms);
            onTurnModemOn();
            onCellularStateSet(State::ST::PowerDown);
            return true;
        }
        return false;
    }

    auto ModemResetHandler::handleSwitchToActive() -> bool
    {
        if (procedureInProgress == ProcedureInProgress::None) {

            return false;
        }

        procedureInProgress = ProcedureInProgress::None;
        onCellularStateSet(State::ST::StatusCheck);
        return true;
    }
} // namespace cellular::service

A module-services/service-cellular/src/ModemResetHandler.hpp => module-services/service-cellular/src/ModemResetHandler.hpp +66 -0
@@ 0,0 1,66 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <service-cellular/State.hpp>

#include <functional>

namespace cellular::service
{

    class ModemResetHandler
    {

      public:
        /**
         * It performs modem reset via AT command
         * @return true on success, false on fail
         */
        auto performSoftReset() -> bool;
        /**
         * It performs modem reset via modem's Reset pin
         * @return
         */
        auto performHardReset() -> bool;
        /**
         * It performs power cycle modem's via PWR_KEY pin
         * @return
         */
        auto performReboot() -> bool;
        /**
         * It handles STATUS pin changed event when any reset procedure is in progress, other case it's doing nothing.
         * @param isActive STATUS pin value. True when STATUS is active, false when it's inactive
         * @return true when event is handled, false when not
         */
        auto handleStatusPinEvent(bool isActive) -> bool;
        /**
         * It checks if any reset procedure is in progress.
         * @return true when any reset procedure is in progress, false when not
         */
        auto isResetInProgress() -> bool;
        /**
         * User defined callbacks
         */
        std::function<void(cellular::service::State::ST)> onCellularStateSet;
        std::function<void()> onTurnModemOn;
        std::function<void()> onTurnModemOff;
        std::function<bool()> onSoftReset;
        std::function<void()> onHardReset;

      private:
        enum class ProcedureInProgress
        {
            None,
            SoftReset,
            HardReset,
            Reboot
        };

        ProcedureInProgress procedureInProgress = ProcedureInProgress::None;

        auto handleSwitchToInactive() -> bool;
        auto handleSwitchToActive() -> bool;
    };
} // namespace cellular::service

M module-services/service-cellular/src/ServiceCellularPriv.cpp => module-services/service-cellular/src/ServiceCellularPriv.cpp +26 -2
@@ 29,12 29,14 @@ namespace cellular::internal
    ServiceCellularPriv::ServiceCellularPriv(ServiceCellular *owner)
        : owner{owner}, simCard{std::make_unique<SimCard>()}, state{std::make_unique<State>(owner)},
          networkTime{std::make_unique<NetworkTime>()}, simContacts{std::make_unique<SimContacts>()},
          imeiGetHandler{std::make_unique<service::ImeiGetHandler>()}, tetheringHandler{
                                                                           std::make_unique<TetheringHandler>()}
          imeiGetHandler{std::make_unique<service::ImeiGetHandler>()},
          tetheringHandler{std::make_unique<TetheringHandler>()}, modemResetHandler{
                                                                      std::make_unique<ModemResetHandler>()}
    {
        initSimCard();
        initSMSSendHandler();
        initTetheringHandler();
        initModemResetHandler();
    }

    void ServiceCellularPriv::initSimCard()


@@ 361,4 363,26 @@ namespace cellular::internal
        tetheringHandler->onReadMessages = [this]() -> bool { return owner->receiveAllMessages(); };
    }

    void ServiceCellularPriv::initModemResetHandler()
    {
        modemResetHandler->onCellularStateSet = [this](cellular::service::State::ST newState) { state->set(newState); };

        modemResetHandler->onTurnModemOn = [this]() { owner->cmux->turnOnModem(); };

        modemResetHandler->onTurnModemOff = [this]() { owner->cmux->turnOffModem(); };

        modemResetHandler->onHardReset = [this]() { owner->cmux->resetModem(); };

        modemResetHandler->onSoftReset = [this]() -> bool {
            auto channel = owner->cmux->get(CellularMux::Channel::Commands);
            if (channel == nullptr) {
                return false;
            }
            auto response = channel->cmd(at::AT::CFUN_RESET);
            if (response) {
                return true;
            }
            return false;
        };
    }
} // namespace cellular::internal

M module-services/service-cellular/src/ServiceCellularPriv.hpp => module-services/service-cellular/src/ServiceCellularPriv.hpp +5 -0
@@ 12,14 12,17 @@
#include "SimContacts.hpp"
#include "ImeiGetHandler.hpp"
#include "TetheringHandler.hpp"
#include "ModemResetHandler.hpp"

namespace cellular::internal
{
    using service::ModemResetHandler;
    using service::NetworkTime;
    using service::SimCard;
    using service::SimContacts;
    using service::State;
    using service::TetheringHandler;

    class ServiceCellularPriv
    {
        ServiceCellular *owner;


@@ 31,6 34,7 @@ namespace cellular::internal
        std::unique_ptr<SimContacts> simContacts;
        std::unique_ptr<service::ImeiGetHandler> imeiGetHandler;
        std::unique_ptr<TetheringHandler> tetheringHandler;
        std::unique_ptr<ModemResetHandler> modemResetHandler;
        State::PowerState nextPowerState = State::PowerState::Off;
        std::uint8_t multiPartSMSUID     = 0;



@@ 50,6 54,7 @@ namespace cellular::internal
        void initSimCard();
        void initSMSSendHandler();
        void initTetheringHandler();
        void initModemResetHandler();
        /** Send SMS action used by the SMSSendHandler
         * \param record SMS record to send
         */

M module-services/service-cellular/src/State.cpp => module-services/service-cellular/src/State.cpp +2 -0
@@ 27,6 27,8 @@ namespace cellular::service
            return "BaudDetect";
        case ST::AudioConfigurationProcedure:
            return "AudioConfigurationProcedure";
        case ST::CellularPrivInit:
            return "CellularPrivInit";
        case ST::APNConfProcedure:
            return "APNConfProcedure";
        case ST::ModemOn:

M module-services/service-evtmgr/api/EventManagerServiceAPI.cpp => module-services/service-evtmgr/api/EventManagerServiceAPI.cpp +0 -16
@@ 17,22 17,6 @@ namespace sys
    class Service;
} // namespace sys

bsp::Board EventManagerServiceAPI::GetBoard(sys::Service *serv)
{
    constexpr uint32_t timeout = 1000;

    std::shared_ptr<sys::DataMessage> msg = std::make_shared<sys::DataMessage>(MessageType::EVMGetBoard);
    auto ret                              = serv->bus.sendUnicastSync(msg, service::name::evt_manager, timeout);

    sevm::EVMBoardResponseMessage *response = dynamic_cast<sevm::EVMBoardResponseMessage *>(ret.second.get());

    if (response != nullptr) {
        if (ret.first == sys::ReturnCodes::Success) {
            return response->board;
        }
    }
    return bsp::Board::none;
}

void EventManagerServiceAPI::vibrationPulseOnce(sys::Service *serv)
{

M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp => module-services/service-evtmgr/service-evtmgr/EVMessages.hpp +0 -14
@@ 79,20 79,6 @@ namespace sevm
        uint32_t dbID                  = 0;
    };

    class EVMBoardResponseMessage : public sys::ResponseMessage
    {
      public:
        EVMBoardResponseMessage(bool retCode,
                                std::string retdata    = std::string(),
                                MessageType responseTo = MessageType::MessageTypeUninitialized)
            : sys::ResponseMessage(sys::ReturnCodes::Success, responseTo), retCode(retCode){};
        EVMBoardResponseMessage(bool retCode, MessageType responseTo)
            : sys::ResponseMessage(sys::ReturnCodes::Success, responseTo), retCode(retCode){};

        bool retCode;
        bsp::Board board = bsp::Board::none;
    };

    class StatusStateMessage : public sys::DataMessage
    {
      public:

M module-services/service-evtmgr/service-evtmgr/EventManagerServiceAPI.hpp => module-services/service-evtmgr/service-evtmgr/EventManagerServiceAPI.hpp +0 -3
@@ 16,9 16,6 @@ namespace sys

namespace EventManagerServiceAPI
{
    /// Gets board version
    bsp::Board GetBoard(sys::Service *serv);

    /// Call single vibrator pulse
    void vibrationPulseOnce(sys::Service *serv);


M products/PurePhone/services/evtmgr/EventManager.cpp => products/PurePhone/services/evtmgr/EventManager.cpp +0 -10
@@ 150,16 150,6 @@ sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sy
        bus.sendUnicast(std::move(msg), ServiceCellular::serviceName);
        handled = true;
    }
    else if (msgl->messageType == MessageType::EVMGetBoard) {
        using namespace bsp;

        auto msg   = std::make_shared<sevm::EVMBoardResponseMessage>(true);
        auto board = magnetometer::GetBoard();
        msg->board = board;
        LOG_INFO("Board discovered: %s", c_str(board));

        return msg;
    }

    if (handled) {
        return std::make_shared<sys::ResponseMessage>();

M source/MessageType.hpp => source/MessageType.hpp +0 -1
@@ 98,7 98,6 @@ enum class MessageType
    EVMTimeUpdated,   ///< This message is send on every time update.

    // cellular messages
    EVMGetBoard,
    EVMModemStatus,
    EVMRingIndicator,