~aleteoryx/muditaos

7cc452503e95b269eedb1b1545d351e10d830426 — Przemyslaw Brudny 4 years ago 5398907 + c49fcdf
Merge remote-tracking branch 'origin/stable'

# Conflicts:
#	products/BellHybrid/apps/application-bell-settings/models/TimeUnitsModel.cpp
75 files changed, 676 insertions(+), 335 deletions(-)

M Target_RT1051.cmake
M board/rt1051/crashdump/crashcatcher_impl.cpp
M board/rt1051/crashdump/crashdumpwriter_vfs.cpp
M image/assets/lang/Deutsch.json
M image/assets/lang/English.json
M image/assets/lang/Espanol.json
M image/assets/lang/Francais.json
M image/assets/lang/Polski.json
M module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp
M module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp
M module-bsp/board/rt1051/bsp/eMMC/fsl_mmc.c
M module-bsp/board/rt1051/bsp/eMMC/fsl_mmc.h
M module-bsp/board/rt1051/bsp/eMMC/fsl_sdmmc_common.h
M module-db/Interface/ThreadRecord.cpp
M module-gui/gui/widgets/ListView.cpp
M module-gui/gui/widgets/ListView.hpp
M module-gui/gui/widgets/ListViewWithArrows.cpp
M module-gui/gui/widgets/ListViewWithArrows.hpp
R module-os/board/rt1051/{_exit.c => _exit.cpp}
A module-os/board/rt1051/include/exit_backtrace.h
M module-os/board/rt1051/port.c
M module-platform/rt1051/src/disk_emmc.cpp
M module-services/service-desktop/endpoints/filesystem/FileContext.cpp
M module-services/service-desktop/endpoints/filesystem/FileOperations.cpp
M module-services/service-desktop/endpoints/include/endpoints/filesystem/FileContext.hpp
M module-services/service-desktop/endpoints/include/endpoints/filesystem/FileOperations.hpp
M module-services/service-desktop/parser/ParserFSM.cpp
M module-services/service-desktop/parser/ParserFSM.hpp
M module-services/service-evtmgr/EventManager.cpp
M module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp
M module-sys/SystemManager/SystemManagerCommon.cpp
M module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp
M module-utils/log/CMakeLists.txt
M module-utils/log/Logger.cpp
A module-utils/log/logdump/CMakeLists.txt
A module-utils/log/logdump/include/logdump/logdump.h
A module-utils/log/logdump/logdump.cpp
M products/BellHybrid/BellHybridMain.cpp
M products/BellHybrid/CMakeLists.txt
M products/BellHybrid/EinkSentinelBell.cpp
M products/BellHybrid/apps/Application.cpp
M products/BellHybrid/apps/CMakeLists.txt
M products/BellHybrid/apps/application-bell-bedtime/ApplicationBellBedtime.cpp
M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp
M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.hpp
M products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp
M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp
M products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.cpp
M products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingSettingsWindow.hpp
M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp
M products/BellHybrid/apps/application-bell-settings/CMakeLists.txt
M products/BellHybrid/apps/application-bell-settings/data/BellSettingsStyle.hpp
R products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/windows/{advanced => }/BellSettingsTimeUnitsWindow.hpp
M products/BellHybrid/apps/application-bell-settings/models/TimeUnitsModel.cpp
R products/BellHybrid/apps/application-bell-settings/windows/{advanced => }/BellSettingsTimeUnitsWindow.cpp
M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsWindow.cpp
M products/BellHybrid/apps/application-bell-settings/windows/advanced/BellSettingsAdvancedWindow.cpp
M products/BellHybrid/apps/common/CMakeLists.txt
M products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp
A products/BellHybrid/apps/common/include/common/options/BellOptionsNavigation.hpp
M products/BellHybrid/apps/common/src/options/BellOptionWindow.cpp
A products/BellHybrid/apps/common/src/options/BellOptionsNavigation.cpp
M products/BellHybrid/apps/common/src/options/BellShortOptionWindow.cpp
M products/BellHybrid/apps/include/Application.hpp
R products/BellHybrid/{config.h => config/ProductConfig.in.hpp}
M products/BellHybrid/services/appmgr/include/appmgr/IdleHandler.hpp
M products/BellHybrid/services/evtmgr/EventManager.cpp
M products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp
M products/BellHybrid/services/time/AlarmOperations.cpp
M products/PurePhone/CMakeLists.txt
M products/PurePhone/PurePhoneMain.cpp
M products/PurePhone/services/evtmgr/include/evtmgr/EventManager.hpp
M products/PurePhone/test/test-settings/test-service-db-settings-api.cpp
M third-party/CrashDebug/CrashCatcher/CrashCatcherPriv.h
M third-party/CrashDebug/CrashCatcher/CrashCatcher_armv7m.S
M Target_RT1051.cmake => Target_RT1051.cmake +1 -1
@@ 59,7 59,7 @@ add_compile_options(

set(TARGET_SOURCES

        ${CMAKE_CURRENT_LIST_DIR}/module-os/board/rt1051/_exit.c
        ${CMAKE_CURRENT_LIST_DIR}/module-os/board/rt1051/_exit.cpp
        CACHE INTERNAL ""
)


M board/rt1051/crashdump/crashcatcher_impl.cpp => board/rt1051/crashdump/crashcatcher_impl.cpp +6 -3
@@ 7,6 7,7 @@

#include <log/log.hpp>
#include <date/date.h>
#include <exit_backtrace.h>
#include "crashdumpwriter_vfs.hpp"
#include "consoledump.hpp"



@@ 23,9 24,11 @@ const CrashCatcherMemoryRegion *CrashCatcher_GetMemoryRegions(void)
     */
    static const CrashCatcherMemoryRegion regions[] = {
        // SRAM_OC
        {0x20200000, 0x20210000, CRASH_CATCHER_BYTE},
        {0x20200000, 0x20210000, CRASH_CATCHER_WORD},
        // SRAM_DTC
        {0x20000000, 0x20070000, CRASH_CATCHER_BYTE},
        {0x20000000, 0x20070000, CRASH_CATCHER_WORD},
        // intentionally skip text section
        // intentionally skip the heap section
        // end tag
        {0xFFFFFFFF, 0xFFFFFFFF, CRASH_CATCHER_BYTE},
    };


@@ 57,6 60,6 @@ void CrashCatcher_DumpMemory(const void *pvMemory, CrashCatcherElementSizes elem
CrashCatcherReturnCodes CrashCatcher_DumpEnd(void)
{
    cwrite.saveDump();
    abort();
    _exit_backtrace(-1, false);
    return CRASH_CATCHER_EXIT;
}

M board/rt1051/crashdump/crashdumpwriter_vfs.cpp => board/rt1051/crashdump/crashdumpwriter_vfs.cpp +8 -7
@@ 8,6 8,7 @@
#include <fcntl.h>
#include "purefs/vfs_subsystem.hpp"
#include <purefs/filesystem_paths.hpp>
#include <exit_backtrace.h>

#include <filesystem>
#include <stdint.h>


@@ 23,12 24,12 @@ namespace crashdump
        LOG_INFO("Crash dump %s preparing ...", crashDumpFilePath.c_str());
        if (!rotator.rotateFile(crashDumpFilePath)) {
            LOG_FATAL("Failed to rotate crash dumps errno: %i", errno);
            std::abort();
            _exit_backtrace(-1, false);
        }
        file = std::fopen(crashDumpFilePath.c_str(), "w");
        if (!file) {
            LOG_FATAL("Failed to open crash dump file errno %i", errno);
            std::abort();
            _exit_backtrace(-1, false);
        }
    }



@@ 44,23 45,23 @@ namespace crashdump
    {
        if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
            LOG_FATAL("Unable to write crash dump errno: %i", errno);
            std::abort();
            _exit_backtrace(-1, false);
        }
    }

    void CrashDumpWriterVFS::writeHalfWords(const uint16_t *buff, std::size_t size)
    {
        if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
            LOG_FATAL("Unable to write crash dump");
            std::abort();
            LOG_FATAL("Unable to write crash dump errno: %i", errno);
            _exit_backtrace(-1, false);
        }
    }

    void CrashDumpWriterVFS::writeWords(const uint32_t *buff, std::size_t size)
    {
        if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
            LOG_FATAL("Unable to write crash dump");
            std::abort();
            LOG_FATAL("Unable to write crash dump errno: %i", errno);
            _exit_backtrace(-1, false);
        }
    }


M image/assets/lang/Deutsch.json => image/assets/lang/Deutsch.json +1 -1
@@ 635,7 635,7 @@
  "app_bell_settings_bedtime_settings_volume": "<text>Lautstärke</text>",
  "app_bell_settings_advanced": "Erweitert",
  "app_bell_settings_turn_off": "Ausschalten",
  "app_bell_settings_advanced_time_units": "Zeit und Einheiten",
  "app_bell_settings_time_units": "Zeit und Einheiten",
  "app_bell_settings_advanced_language": "Sprache",
  "app_bell_settings_advanced_about": "Über",
  "app_bell_settings_advanced_about_product": "Mudita Harmony",

M image/assets/lang/English.json => image/assets/lang/English.json +1 -1
@@ 608,7 608,7 @@
  "app_bell_onboarding_info_deep_click_correction": "<text font='gt_pressura' weight='light' size='38'>Be more gentle,<br></br>try </text><text font='gt_pressura' weight='regular' size='38'>light click </text><text font='gt_pressura' weight='light' size='38'>this time</text>",
  "app_bell_onboarding_finalize": "Well done!",
  "app_bell_settings_advanced": "Advanced",
  "app_bell_settings_advanced_time_units": "Time & units",
  "app_bell_settings_time_units": "Time & units",
  "app_bell_settings_advanced_temp_scale": "Temperature scale",
  "app_bell_settings_advanced_language": "Language",
  "app_bell_settings_advanced_about": "About",

M image/assets/lang/Espanol.json => image/assets/lang/Espanol.json +1 -1
@@ 634,7 634,7 @@
  "app_bell_settings_bedtime_settings_volume": "Volumen",
  "app_bell_settings_advanced": "Avanzados",
  "app_bell_settings_turn_off": "Apagar",
  "app_bell_settings_advanced_time_units": "Hora y unidades",
  "app_bell_settings_time_units": "Hora y unidades",
  "app_bell_settings_advanced_language": "Idioma",
  "app_bell_settings_advanced_about": "Información",
  "app_bell_settings_advanced_about_product": "Mudita Harmony",

M image/assets/lang/Francais.json => image/assets/lang/Francais.json +1 -1
@@ 604,7 604,7 @@
  "app_bell_settings_bedtime_settings_volume": "Volume",
  "app_bell_settings_advanced": "Avancé",
  "app_bell_settings_turn_off": "Éteindre",
  "app_bell_settings_advanced_time_units": "Temps et unités",
  "app_bell_settings_time_units": "Temps et unités",
  "app_bell_settings_advanced_language": "Langue",
  "app_bell_settings_advanced_about": "À propos",
  "app_bell_settings_advanced_about_product": "Mudita Harmony",

M image/assets/lang/Polski.json => image/assets/lang/Polski.json +1 -1
@@ 627,7 627,7 @@
  "app_bell_onboarding_info_deep_click_warning": "<text font='gt_pressura' weight='light' size='38'>Głęboko </text><text font='gt_pressura' weight='regular' size='38'>wciśnięty</text>",
  "app_bell_onboarding_info_deep_click_correction": "<text font='gt_pressura' weight='light' size='38'>Bądź bardziej delikatny, <br></br>spróbuj </text><text font='gt_pressura' weight='regular' size='38'>tym razem </text><text font='gt_pressura' weight='light' size='38'>lekko kliknąć</text>",
  "app_bell_settings_advanced": "Zaawansowane",
  "app_bell_settings_advanced_time_units": "Czas i jednostki",
  "app_bell_settings_time_units": "Czas i jednostki",
  "app_bell_settings_advanced_temp_scale": "Skala temperatury",
  "app_bell_settings_alarm_settings": "Alarm",
  "app_bell_settings_alarm_settings_title": "Ustawienia alarmu",

M module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp => module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp +5 -3
@@ 36,13 36,15 @@ namespace gui
        fmt->setEdges(RectangleEdge::Bottom);

        focusChangedCallback = [&](Item &) {
            if (focus && editMode != EditMode::Browse) {
                setFocusItem(timeSetSpinner);
            if (focus) {
                setTimeFormat(this->timeFormat);
                if (editMode != EditMode::Browse) {
                    setFocusItem(timeSetSpinner);
                }
            }
            else {
                setFocusItem(nullptr);
            }
            setTimeFormat(this->timeFormat);
            return true;
        };


M module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp => module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp +4 -4
@@ 10,10 10,10 @@ namespace bsp
        PowerProfile bellPowerProfile;

        bellPowerProfile.frequencyShiftLowerThreshold      = 50;
        bellPowerProfile.frequencyShiftUpperThreshold      = 90;
        bellPowerProfile.maxBelowThresholdCount            = 10;
        bellPowerProfile.maxBelowThresholdInRowCount       = 5;
        bellPowerProfile.maxAboveThresholdCount            = 3;
        bellPowerProfile.frequencyShiftUpperThreshold      = 80;
        bellPowerProfile.maxBelowThresholdCount            = 5;
        bellPowerProfile.maxBelowThresholdInRowCount       = 1;
        bellPowerProfile.maxAboveThresholdCount            = 2;
        bellPowerProfile.minimalFrequency                  = CpuFrequencyHz::Level_0;
        bellPowerProfile.frequencyIncreaseIntermediateStep = true;


M module-bsp/board/rt1051/bsp/eMMC/fsl_mmc.c => module-bsp/board/rt1051/bsp/eMMC/fsl_mmc.c +2 -25
@@ 1865,11 1865,7 @@ static status_t MMC_Write(
    }

    /* Wait for the card's buffer to be not full to write to improve the write performance. */
    error = MMC_PollingCardStatusBusy(card);
    if(kStatus_Success != error)
    {
        return error;
    }
    while ((GET_SDMMCHOST_STATUS(card->host.base) & CARD_DATA0_STATUS_MASK) != CARD_DATA0_NOT_BUSY) {}

    /* Wait for the card write process complete */
    if (kStatus_Success != MMC_WaitWriteComplete(card)) {


@@ 2268,11 2264,7 @@ status_t MMC_EraseGroups(mmc_card_t *card, uint32_t startGroup, uint32_t endGrou
    }

    /* Wait for the card's buffer to be not full to write to improve the write performance. */
    status_t error = MMC_PollingCardStatusBusy(card);
    if(kStatus_Success != error)
    {
        return error;
    }
    while ((GET_SDMMCHOST_STATUS(card->host.base) & CARD_DATA0_STATUS_MASK) != CARD_DATA0_NOT_BUSY) {}

    if (kStatus_Success != MMC_WaitWriteComplete(card)) {
        return kStatus_SDMMC_WaitWriteCompleteFailed;


@@ 2639,18 2631,3 @@ status_t MMC_StopBoot(mmc_card_t *card, uint32_t bootMode)

    return kStatus_Success;
}

status_t MMC_PollingCardStatusBusy(mmc_card_t *card)
{
    int retries = 0;
    const int maxRetries = 10000;
    do {
        if ((GET_SDMMCHOST_STATUS(card->host.base) & CARD_DATA0_STATUS_MASK) == CARD_DATA0_NOT_BUSY) {
            return kStatus_Success;
        }
        // yeld 
        SDMMCHOST_Delay(0);
    } while (retries++ < maxRetries);
    
    return kStatus_SDMMC_PollingCardIdleFailed;
}

M module-bsp/board/rt1051/bsp/eMMC/fsl_mmc.h => module-bsp/board/rt1051/bsp/eMMC/fsl_mmc.h +0 -12
@@ 356,18 356,6 @@ extern "C"
     */
    status_t MMC_SetMaxEraseUnitSize(mmc_card_t *card);

    /*!
     * @brief Polling card idle status.
     *
     * This function can be used to poll the status from busy to idle.
     *
     * @param card Card descriptor.
     *
     * @retval kStatus_SDMMC_TransferFailed Command tranfer failed.
     * @retval kStatus_Success Operate successfully.
     */
    status_t MMC_PollingCardStatusBusy(mmc_card_t *card);

/* @} */
#if defined(__cplusplus)
}

M module-bsp/board/rt1051/bsp/eMMC/fsl_sdmmc_common.h => module-bsp/board/rt1051/bsp/eMMC/fsl_sdmmc_common.h +0 -1
@@ 124,7 124,6 @@ enum _sdmmc_status
    kStatus_SDMMC_CardDetectFailed         = MAKE_STATUS(kStatusGroup_SDMMC, 39U), /*!<  card detect failed */
    kStatus_SDMMC_PartitioningFailed       = MAKE_STATUS(kStatusGroup_SDMMC, 40U), /*!<  Partitioning failed */
    kStatus_SDMMC_PartitioningNotSupported = MAKE_STATUS(kStatusGroup_SDMMC, 41U), /*!<  Partitioning not supported */
    kStatus_SDMMC_PollingCardIdleFailed    = MAKE_STATUS(kStatusGroup_SDMMC, 42U), /*!< polling card idle status failed */
};

/*! @brief card operation voltage */

M module-db/Interface/ThreadRecord.cpp => module-db/Interface/ThreadRecord.cpp +1 -1
@@ 196,7 196,7 @@ std::unique_ptr<db::QueryResult> ThreadRecordInterface::markAsReadQuery(const st
    auto ret              = false;

    if (record.isValid()) {
        LOG_FATAL("query-read %d", static_cast<int>(localQuery->read));
        LOG_DEBUG("query-read %d", static_cast<int>(localQuery->read));
        record.unreadMsgCount = localQuery->read == db::query::MarkAsRead::Read::True ? 0 : 1;
        ret                   = Update(record);
    }

M module-gui/gui/widgets/ListView.cpp => module-gui/gui/widgets/ListView.cpp +2 -4
@@ 148,6 148,8 @@ namespace gui
            }
        };

        inputCallback = [&](Item &item, const InputEvent &event) { return body->onInput(event); };

        focusChangedCallback = [this]([[maybe_unused]] Item &item) -> bool {
            if (focus) {
                setFocus();


@@ 261,8 263,4 @@ namespace gui
        return Size(request_w, request_h);
    }

    bool ListView::onInput(const InputEvent &inputEvent)
    {
        return body->onInput(inputEvent);
    }
} /* namespace gui */

M module-gui/gui/widgets/ListView.hpp => module-gui/gui/widgets/ListView.hpp +0 -1
@@ 55,7 55,6 @@ namespace gui
        void setAlignment(const Alignment &value) override;

        // virtual methods from Item
        bool onInput(const InputEvent &inputEvent) override;
        bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
        auto handleRequestResize(const Item *, Length request_w, Length request_h) -> Size override;
    };

M module-gui/gui/widgets/ListViewWithArrows.cpp => module-gui/gui/widgets/ListViewWithArrows.cpp +2 -5
@@ 33,6 33,8 @@ namespace gui
            }
        };

        inputCallback = [&](Item &item, const InputEvent &event) { return body->onInput(event); };

        focusChangedCallback = [this]([[maybe_unused]] Item &item) -> bool {
            if (focus) {
                setFocus();


@@ 213,9 215,4 @@ namespace gui
        return true;
    }

    bool ListViewWithArrows::onInput(const InputEvent &inputEvent)
    {
        return body->onInput(inputEvent);
    }

} /* namespace gui */

M module-gui/gui/widgets/ListViewWithArrows.hpp => module-gui/gui/widgets/ListViewWithArrows.hpp +0 -1
@@ 36,7 36,6 @@ namespace gui
        void applySizeRestrictions(unsigned int w, unsigned int h, unsigned int outerLayoutsH, int outerLayoutsMargin);

        void setAlignment(const Alignment &value) override;
        bool onInput(const InputEvent &inputEvent) override;
        bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
    };


R module-os/board/rt1051/_exit.c => module-os/board/rt1051/_exit.cpp +33 -3
@@ 33,13 33,28 @@
#include <FreeRTOS.h>
#include <MIMXRT1051.h>
#include <log/log.hpp>
#include <logdump/logdump.h>
#include <task.h>
#include <macros.h>
#include <stdbool.h>
#include <string.h>
#include <exit_backtrace.h>
#include <purefs/vfs_subsystem.hpp>

void __attribute__((noreturn, used)) _exit(int code)

static void __attribute__((noreturn)) stop_system(void)
{
    LOG_INFO("_exit %d", code);
    haltIfDebugging();
    if (dumpLogs() != 1) {
        LOG_ERROR("Cannot dump logs");
    }
    
    const auto err = purefs::subsystem::unmount_all();
    if(err) {
        LOG_WARN("Unable unmount all filesystems with error: %i.", err);
    } else {
        LOG_INFO("Filesystems unmounted successfully...");
    }
    LOG_INFO("Restarting the system...");
    vTaskEndScheduler();
    NVIC_SystemReset();
    // waiting for system reset


@@ 49,3 64,18 @@ void __attribute__((noreturn, used)) _exit(int code)
#endif
    };
}

void __attribute__((noreturn, used)) _exit_backtrace(int code, bool bt_dump)
{
    LOG_INFO("_exit %d", code);
    if( bt_dump ) {
        _StackTrace_Dump_And_Abort();
    }
    stop_system();
};


void __attribute__((noreturn, used)) _exit(int code)
{
     _exit_backtrace(code, code!=0);
}

A module-os/board/rt1051/include/exit_backtrace.h => module-os/board/rt1051/include/exit_backtrace.h +56 -0
@@ 0,0 1,56 @@
// 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 <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif


/** This is a extension for standard function @see exit which stop the system
 * and optionaly takes a backtrace
 * @param[in] code Standard terminate exit code
 * @param[in] bt_dump If true backtrace will be created
 * @note Function never returns
 */
void __attribute__((noreturn, used)) _exit_backtrace(int code, bool bt_dump);


/** This is a standard function @see exit which stop the system
 * and optionaly takes a backtrace
 * @param[in] code Standard terminate exit code
 * @note Function never returns and dump backtrace when code is not equal EXIT_SUCCESS
 */
void __attribute__((noreturn, used)) _exit(int code);


/** This is internal backtrce function
 * @note In never shouldn't to be called directly in the user code
 */
static inline void __attribute__((always_inline)) _StackTrace_Dump_stage_1(void)
{
    // Redirect to the save stacktrace syscall (1)
    __asm volatile("svc #1\n");
}

/** This is internal backtrce function
 * @note In never shouldn't to be called directly in the user code
 */
extern void _StackTrace_Dump_stage_2(void);


/** This function save a backtrace on the disk and stop the system by abort
 */
static inline void __attribute__((always_inline)) _StackTrace_Dump_And_Abort(void)
{
    _StackTrace_Dump_stage_1();
    _StackTrace_Dump_stage_2();
}

#ifdef __cplusplus
}
#endif



M module-os/board/rt1051/port.c => module-os/board/rt1051/port.c +10 -1
@@ 192,7 192,16 @@ volatile uint32_t ulDummy = 0;
void vPortSVCHandler( void )
{
	__asm volatile (
					"	ldr	r3, pxCurrentTCBConst2		\n" /* Restore the context. */
                    "   tst lr, #0x04                   \n" /* Extract SVC number from the opcode */
                    "   ite eq                          \n"
                    "   mrseq r0, MSP                   \n"
                    "   mrsne r0, PSP                   \n"
                    "   ldr r0, [r0, #24]               \n"
                    "   sub r0, r0, #2                  \n"
                    "   ldrb r0, [r0]                   \n"
                    "   cmp r0, #0                      \n" /* Check if SVC #0 */
                    "   bne _StackTrace_Dump_svc_1       \n" /* Nono zero value go to the dump backtrace */
					"	ldr	r3, pxCurrentTCBConst2		\n" /* On SVC #0 Restore the context and start OS. */
					"	ldr r1, [r3]					\n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
					"	ldr r0, [r1]					\n" /* The first item in pxCurrentTCB is the task top of stack. */
					"	ldmia r0!, {r4-r11, r14}		\n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */

M module-platform/rt1051/src/disk_emmc.cpp => module-platform/rt1051/src/disk_emmc.cpp +2 -3
@@ 105,9 105,8 @@ namespace purefs::blkdev
            return statusBlkDevFail;
        }
        // Wait for the card's buffer to become empty
        auto error = MMC_PollingCardStatusBusy(mmcCard.get());
        if (kStatus_Success != error) {
            return error;
        while ((GET_SDMMCHOST_STATUS(mmcCard->host.base) & CARD_DATA0_STATUS_MASK) != CARD_DATA0_NOT_BUSY) {
            taskYIELD();
        }
        if (pmState == pm_state::suspend) {
            driverUSDHC->Enable();

M module-services/service-desktop/endpoints/filesystem/FileContext.cpp => module-services/service-desktop/endpoints/filesystem/FileContext.cpp +32 -26
@@ 4,11 4,11 @@
#include <endpoints/filesystem/FileContext.hpp>
#include <log/log.hpp>
#include <utility>
#include <fstream>

FileContext::FileContext(const std::filesystem::path &path,
                         std::size_t size,
                         std::size_t chunkSize,
                         const std::string &openMode,
                         std::size_t offset)
    : path(path), size(size), offset(offset), chunkSize(chunkSize)
{


@@ 16,28 16,18 @@ FileContext::FileContext(const std::filesystem::path &path,
        throw std::invalid_argument("Invalid FileContext arguments");
    }

    file = std::fopen(path.c_str(), openMode.c_str());
    if (!file) {
        throw std::runtime_error("File open error");
    }

    constexpr size_t streamBufferSize = 64 * 1024;
    streamBuffer                      = std::make_unique<char[]>(streamBufferSize);
    setvbuf(file, streamBuffer.get(), _IOFBF, streamBufferSize);

    runningCrc32Digest.reset();
}

FileContext::~FileContext()
{
    std::fclose(file);
}

FileReadContext::FileReadContext(const std::filesystem::path &path,
                                 std::size_t size,
                                 std::size_t chunkSize,
                                 std::size_t offset)
    : FileContext(path, size, chunkSize, "rb", offset)
    : FileContext(path, size, chunkSize, offset)
{}

FileReadContext::~FileReadContext()


@@ 48,7 38,7 @@ FileWriteContext::FileWriteContext(const std::filesystem::path &path,
                                   std::size_t chunkSize,
                                   std::string crc32Digest,
                                   std::size_t offset)
    : FileContext(path, size, chunkSize, "wb", offset), crc32Digest(std::move(crc32Digest))
    : FileContext(path, size, chunkSize, offset), crc32Digest(std::move(crc32Digest))
{}

FileWriteContext::~FileWriteContext()


@@ 93,23 83,30 @@ auto FileReadContext::read() -> std::vector<std::uint8_t>
{
    LOG_DEBUG("Getting file data");

    std::fseek(file, offset, SEEK_SET);
    std::ifstream file(path, std::ios::binary);

    if (!file.is_open() || file.fail()) {
        LOG_ERROR("File %s open error", path.c_str());
        throw std::runtime_error("File open error");
    }

    file.seekg(offset);

    auto dataLeft = std::min(static_cast<std::size_t>(chunkSize), (size - offset));

    std::vector<std::uint8_t> buffer(dataLeft);

    auto dataRead = std::fread(buffer.data(), sizeof(int8_t), dataLeft, file);
    file.read(reinterpret_cast<char *>(buffer.data()), dataLeft);

    if (dataRead != dataLeft) {
    if (file.bad()) {
        LOG_ERROR("File %s read error", path.c_str());
        throw std::runtime_error("File read error");
    }

    runningCrc32Digest.add(buffer.data(), dataRead);
    runningCrc32Digest.add(buffer.data(), dataLeft);

    LOG_DEBUG("Read %u bytes", static_cast<unsigned int>(dataRead));
    advanceFileOffset(dataRead);
    LOG_DEBUG("Read %u bytes", static_cast<unsigned int>(dataLeft));
    advanceFileOffset(dataLeft);

    if (reachedEOF()) {
        LOG_INFO("Reached EOF");


@@ 122,22 119,30 @@ auto FileWriteContext::write(const std::vector<std::uint8_t> &data) -> void
{
    LOG_DEBUG("Sending file data");

    std::fseek(file, offset, SEEK_SET);
    std::ofstream file(path, std::ios::binary | std::ios::app);

    if (!file.is_open() || file.fail()) {
        LOG_ERROR("File %s open error", path.c_str());
        throw std::runtime_error("File open error");
    }

    file.seekp(offset);

    auto dataLeft = std::min(static_cast<std::size_t>(chunkSize), (size - offset));

    auto dataWritten = std::fwrite(reinterpret_cast<const char *>(data.data()), sizeof(int8_t), dataLeft, file);
    file.write(reinterpret_cast<const char *>(data.data()), dataLeft);
    file.flush();

    if (dataWritten != dataLeft) {
    if (file.bad()) {
        LOG_ERROR("File %s write error", path.c_str());
        throw std::runtime_error("File write error");
    }

    runningCrc32Digest.add(data.data(), dataWritten);
    runningCrc32Digest.add(data.data(), dataLeft);

    LOG_DEBUG("Written %u bytes", static_cast<unsigned int>(dataWritten));
    LOG_DEBUG("Written %u bytes", static_cast<unsigned int>(dataLeft));

    advanceFileOffset(dataWritten);
    advanceFileOffset(dataLeft);

    if (reachedEOF()) {
        LOG_INFO("Reached EOF of %s", path.c_str());


@@ 152,5 157,6 @@ auto FileWriteContext::crc32Matches() const -> bool

auto FileWriteContext::removeFile() -> void
{
    std::filesystem::remove(path);
    std::error_code ec;
    std::filesystem::remove(path, ec);
}

M module-services/service-desktop/endpoints/filesystem/FileOperations.cpp => module-services/service-desktop/endpoints/filesystem/FileOperations.cpp +12 -6
@@ 14,7 14,7 @@ FileOperations &FileOperations::instance()
auto FileOperations::createReceiveIDForFile(const std::filesystem::path &file) -> std::pair<transfer_id, std::size_t>
{
    cancelTimedOutReadTransfer();
    const auto rxID = ++runningXfrId;
    const auto rxID = ++runningRxId;
    const auto size = std::filesystem::file_size(file);

    if (size == 0) {


@@ 31,11 31,11 @@ auto FileOperations::createReceiveIDForFile(const std::filesystem::path &file) -

void FileOperations::cancelTimedOutReadTransfer()
{
    if (!runningXfrId) {
    if (runningRxId == 0) {
        return;
    }

    auto timedOutXfer       = runningXfrId - 1;
    auto timedOutXfer       = runningRxId.load();
    const auto fileCtxEntry = readTransfers.find(timedOutXfer);

    if (fileCtxEntry == readTransfers.end()) {


@@ 43,17 43,19 @@ void FileOperations::cancelTimedOutReadTransfer()
        return;
    }

    fileCtxEntry->second.reset();

    LOG_DEBUG("Canceling timed out rxID %u", static_cast<unsigned>(timedOutXfer));
    readTransfers.erase(timedOutXfer);
}

void FileOperations::cancelTimedOutWriteTransfer()
{
    if (!runningXfrId) {
    if (runningTxId == 0) {
        return;
    }

    auto timedOutXfer       = runningXfrId - 1;
    auto timedOutXfer       = runningTxId.load();
    const auto fileCtxEntry = writeTransfers.find(timedOutXfer);

    if (fileCtxEntry == writeTransfers.end()) {


@@ 61,6 63,10 @@ void FileOperations::cancelTimedOutWriteTransfer()
        return;
    }

    fileCtxEntry->second->removeFile();

    fileCtxEntry->second.reset();

    LOG_DEBUG("Canceling timed out rxID %u", static_cast<unsigned>(timedOutXfer));
    writeTransfers.erase(timedOutXfer);
}


@@ 165,7 171,7 @@ auto FileOperations::createTransmitIDForFile(const std::filesystem::path &file,
                                             const std::string &Crc32) -> transfer_id
{
    cancelTimedOutWriteTransfer();
    const auto txID = ++runningXfrId;
    const auto txID = ++runningTxId;

    LOG_DEBUG("Creating txID %u", static_cast<unsigned>(txID));


M module-services/service-desktop/endpoints/include/endpoints/filesystem/FileContext.hpp => module-services/service-desktop/endpoints/include/endpoints/filesystem/FileContext.hpp +0 -3
@@ 19,7 19,6 @@ class FileContext
    explicit FileContext(const std::filesystem::path &path,
                         std::size_t size,
                         std::size_t chunkSize,
                         const std::string &openMode,
                         std::size_t offset = 0);

    virtual ~FileContext();


@@ 40,8 39,6 @@ class FileContext

  protected:
    std::filesystem::path path{};
    std::FILE *file{};
    std::unique_ptr<char[]> streamBuffer;
    std::size_t size{};
    std::size_t offset{};
    std::size_t chunkSize{};

M module-services/service-desktop/endpoints/include/endpoints/filesystem/FileOperations.hpp => module-services/service-desktop/endpoints/include/endpoints/filesystem/FileOperations.hpp +2 -1
@@ 23,7 23,8 @@ class FileOperations
    std::map<transfer_id, std::unique_ptr<FileReadContext>> readTransfers;
    std::map<transfer_id, std::unique_ptr<FileWriteContext>> writeTransfers;

    std::atomic<transfer_id> runningXfrId{0};
    std::atomic<transfer_id> runningRxId{0};
    std::atomic<transfer_id> runningTxId{0};

    auto createFileReadContextFor(const std::filesystem::path &file, std::size_t fileSize, transfer_id xfrId) -> void;


M module-services/service-desktop/parser/ParserFSM.cpp => module-services/service-desktop/parser/ParserFSM.cpp +37 -8
@@ 7,20 7,33 @@
#include <memory>
#include <string>

#include <Timers/TimerFactory.hpp>
#include "MessageHandler.hpp"
#include <endpoints/EndpointFactory.hpp>
#include <endpoints/message/Common.hpp>

namespace
{
    constexpr auto receiveMsgTimerDelayMs = std::chrono::milliseconds{1000 * 5};
    constexpr auto parserTimerName        = "parserTimer";

} // namespace

namespace sdesktop::endpoints
{

    StateMachine::StateMachine(sys::Service *OwnerService) : OwnerServicePtr(OwnerService)
    StateMachine::StateMachine(sys::Service *OwnerService)
        : OwnerServicePtr(OwnerService),
          parserTimer{sys::TimerFactory::createSingleShotTimer(
              OwnerService, parserTimerName, receiveMsgTimerDelayMs, [this](sys::Timer & /*timer*/) { resetParser(); })}
    {}

    void StateMachine::processMessage(std::string &&msg)
    {
        receivedMsg = std::move(msg);

        restartTimer();

        switch (state) {
        case State::NoMsg:
            parseHeader();


@@ 37,6 50,21 @@ namespace sdesktop::endpoints
        }
    }

    void StateMachine::resetParser()
    {
        payload.clear();
        header.clear();
        payloadLength = 0;

        setState(State::NoMsg);
        LOG_DEBUG("Parser state reset");
    }

    void StateMachine::restartTimer()
    {
        parserTimer.restart(receiveMsgTimerDelayMs);
    }

    void StateMachine::parseHeader()
    {
        payload.clear();


@@ 51,7 79,7 @@ namespace sdesktop::endpoints

        if (receivedMsg.size() < message::size_header) // header divided in few parts
        {
            state = State::ReceivedPartialHeader;
            setState(State::ReceivedPartialHeader);
            header.append(receivedMsg); // append to whole header string
            return;
        }


@@ 61,7 89,7 @@ namespace sdesktop::endpoints
        if (payloadLength == 0) // failed to obtain payload length from msg
        {
            LOG_ERROR("Damaged header!");
            state = State::NoMsg;
            setState(State::NoMsg);
            return;
        }



@@ 109,7 137,7 @@ namespace sdesktop::endpoints
        else // message divided in 2 or more packets
        {
            payload = receivedMsg.substr(0, std::string::npos); // take rest of the message
            state   = State::ReceivedPartialPayload;
            setState(State::ReceivedPartialPayload);
        }
    }



@@ 139,20 167,21 @@ namespace sdesktop::endpoints
    {
        if (payload.empty()) {
            LOG_ERROR("Empty payload!");
            state = State::NoMsg;
            setState(State::NoMsg);
            return;
        }

        messageHandler->parseMessage(payload);

        if (!messageHandler->isValid() || messageHandler->isJSONNull()) {
            LOG_DEBUG("Error parsing JSON");
            state = State::NoMsg;
            LOG_ERROR("Error parsing JSON");
            setState(State::NoMsg);
            return;
        }

        messageHandler->processMessage();
        state = State::NoMsg;
        setState(State::NoMsg);
        parserTimer.stop();
    }

    void StateMachine::setMessageHandler(std::unique_ptr<MessageHandler> handler)

M module-services/service-desktop/parser/ParserFSM.hpp => module-services/service-desktop/parser/ParserFSM.hpp +6 -1
@@ 5,8 5,10 @@

#include "MessageHandler.hpp"

#include <json11.hpp>
#include <Timers/TimerHandle.hpp>

#include <json11.hpp>
#include <magic_enum.hpp>
#include <string>

namespace sdesktop::endpoints


@@ 44,8 46,11 @@ namespace sdesktop::endpoints
        unsigned long payloadLength   = 0;
        sys::Service *OwnerServicePtr = nullptr;
        std::unique_ptr<MessageHandler> messageHandler;
        sys::TimerHandle parserTimer;

        void parseHeader();
        void resetParser();
        void restartTimer();
        void parsePartialHeader();
        void parseNewMessage();
        void parsePartialMessage();

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +6 -7
@@ 62,13 62,13 @@ EventManagerSentinel::~EventManagerSentinel()
    cpuSentinel->ReleaseMinimumFrequency();
}

EventManagerCommon::EventManagerCommon(const std::string &name)
EventManagerCommon::EventManagerCommon(LogDumpFunction logDumpFunction, const std::string &name)
    : sys::Service(name, "", stackDepth), loggerTimer{sys::TimerFactory::createPeriodicTimer(
                                              this,
                                              loggerTimerName,
                                              std::chrono::milliseconds{loggerDelayMs},
                                              [this](sys::Timer & /*timer*/) { dumpLogsToFile(); })},
      settings(std::make_shared<settings::Settings>())
      logDumpFunction(logDumpFunction), settings(std::make_shared<settings::Settings>())
{
    LOG_INFO("[%s] Initializing", name.c_str());
    alarmTimestamp = 0;


@@ 301,12 301,11 @@ void EventManagerCommon::handleKeyEvent(sys::Message *msg)

int EventManagerCommon::dumpLogsToFile()
{
    const auto logPath = purefs::dir::getLogsPath() / LOG_FILE_NAME;
    const auto ts      = cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks());

    LOG_DEBUG("Log flush timestamp: %d", static_cast<unsigned>(ts));
    if (logDumpFunction) {
        return logDumpFunction();
    }

    return Log::Logger::get().dumpToFile(std::move(logPath));
    return 0;
}

void EventManagerCommon::handleMinuteUpdate(time_t timestamp)

M module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp => module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp +30 -26
@@ 35,6 35,29 @@ class EventManagerSentinel

class EventManagerCommon : public sys::Service
{
  public:
    using LogDumpFunction = std::function<int()>;

    explicit EventManagerCommon(LogDumpFunction logDumpFunction, const std::string &name = service::name::evt_manager);
    ~EventManagerCommon() override;

    sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;

    // Invoked during initialization
    sys::ReturnCodes InitHandler() final;

    sys::ReturnCodes DeinitHandler() override;

    void ProcessCloseReason(sys::CloseReason closeReason) override;

    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;

    /**
     * @brief Sends request to application manager to switch from current application to specific window in application
     * with specified name .
     */
    static bool messageSetApplication(sys::Service *sender, const std::string &applicationName);

  private:
    static constexpr auto stackDepth = 4096;
    void handleMinuteUpdate(time_t timestamp);


@@ 45,6 68,13 @@ class EventManagerCommon : public sys::Service

    sys::TimerHandle loggerTimer;

    LogDumpFunction logDumpFunction;

    /// @return: < 0 - error occured during log flush
    /// @return:   0 - log flush did not happen
    /// @return:   1 - log flush successflul
    int dumpLogsToFile();

  protected:
    std::function<void(const time_t)> onMinuteTick;
    virtual void handleKeyEvent(sys::Message *msg);


@@ 61,30 91,4 @@ class EventManagerCommon : public sys::Service
    uint32_t alarmTimestamp;
    // ID of alarm waiting to trigger
    uint32_t alarmID;

  public:
    explicit EventManagerCommon(const std::string &name = service::name::evt_manager);
    ~EventManagerCommon();

    sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;

    // Invoked during initialization
    sys::ReturnCodes InitHandler() final;

    sys::ReturnCodes DeinitHandler() override;

    void ProcessCloseReason(sys::CloseReason closeReason) override;

    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;

    /// @return: < 0 - An error occurred during log flush
    /// @return:   0 - Log file reached max size
    /// @return:   1 - Logs flushed successflully
    int dumpLogsToFile();

    /**
     * @brief Sends request to application manager to switch from current application to specific window in application
     * with specified name .
     */
    static bool messageSetApplication(sys::Service *sender, const std::string &applicationName);
};

M module-sys/SystemManager/SystemManagerCommon.cpp => module-sys/SystemManager/SystemManagerCommon.cpp +49 -22
@@ 101,6 101,47 @@ namespace sys
        LOG_DEBUG("%s", (GetName() + ":destructor").c_str());
    }

    void SystemManagerCommon::LogPowerOffReason()
    {
        // Power off system
        switch (state) {
        case SystemManagerCommon::State::Reboot:
            LOG_INFO("  --->  REBOOT <--- ");
            break;
        case SystemManagerCommon::State::ShutdownReady:
            LOG_INFO("  ---> SHUTDOWN <--- ");
            break;
        case SystemManagerCommon::State::RebootToUpdate:
            LOG_INFO("  ---> REBOOT TO UPDATER <--- ");
            break;
        case SystemManagerCommon::State::Running:
        case SystemManagerCommon::State::Suspend:
        case SystemManagerCommon::State::Shutdown:
            LOG_FATAL("State changed after reset/shutdown was requested to: %s! this is terrible failure!",
                      c_str(state));
            break;
        }
    }

    void SystemManagerCommon::PowerOff()
    {
        switch (state) {
        case State::Reboot:
            powerManager->Reboot();
            break;
        case State::ShutdownReady:
            powerManager->PowerOff();
            break;
        case State::RebootToUpdate:
            powerManager->RebootToUpdate(updateReason);
            break;
        case SystemManagerCommon::State::Running:
        case SystemManagerCommon::State::Suspend:
        case SystemManagerCommon::State::Shutdown:
            exit(1);
        }
    }

    void SystemManagerCommon::Run()
    {
        initialize();


@@ 132,34 173,19 @@ namespace sys
        }

        DestroySystemService(service::name::evt_manager, this);

        CloseService();

        EndScheduler();
        // it should be called before systemDeinit to make sure this log is dumped to the file
        LogPowerOffReason();

        if (systemDeinit) {
            systemDeinit();
        }

        EndScheduler();

        // Power off system
        switch (state) {
        case State::Reboot:
            LOG_INFO("  --->  REBOOT <--- ");
            powerManager->Reboot();
            break;
        case State::ShutdownReady:
            LOG_INFO("  ---> SHUTDOWN <--- ");
            powerManager->PowerOff();
            break;
        case State::RebootToUpdate:
            LOG_INFO("  ---> REBOOT TO UPDATER <--- ");
            powerManager->RebootToUpdate(updateReason);
            break;
        default:
            LOG_FATAL("State changed after reset/shutdown was requested to: %s! this is terrible failure!",
                      c_str(state));
            exit(1);
        }
        PowerOff();
    }

    void SystemManagerCommon::initialize()


@@ 323,11 349,12 @@ namespace sys
        auto resp = std::static_pointer_cast<ResponseMessage>(ret.second);

        if (ret.first != ReturnCodes::Success) {
            LOG_ERROR("Service to close: %s did not respond", name.c_str());
            LOG_ERROR("Service to close: %s did not respond, error code %d", name.c_str(), static_cast<int>(ret.first));
            return false;
        }
        else if (resp->retCode != ReturnCodes::Success) {
            LOG_ERROR("Service %s noticed failure at close", name.c_str());
            LOG_ERROR(
                "Service %s noticed failure at close, error code %d", name.c_str(), static_cast<int>(resp->retCode));
            return false;
        }
        return true;

M module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp => module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp +4 -0
@@ 148,6 148,10 @@ namespace sys

        void Run() override;

        void LogPowerOffReason();

        void PowerOff();

        void StartSystemServices();

        static bool RunService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout = 5000);

M module-utils/log/CMakeLists.txt => module-utils/log/CMakeLists.txt +1 -1
@@ 2,6 2,7 @@ add_library(log STATIC)

add_subdirectory(api)
add_subdirectory(board)
add_subdirectory(logdump)

target_sources(log
    PRIVATE


@@ 16,7 17,6 @@ target_include_directories(log PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(log
    PRIVATE
        utility
        purefs-paths
    PUBLIC
        module-os
        log-api

M module-utils/log/Logger.cpp => module-utils/log/Logger.cpp +7 -1
@@ 136,7 136,13 @@ namespace Log
    /// @return:   1 - log flush successflul
    auto Logger::dumpToFile(std::filesystem::path logPath) -> int
    {
        auto firstDump = !std::filesystem::exists(logPath);
        std::error_code errorCode;
        auto firstDump = !std::filesystem::exists(logPath, errorCode);
        if (errorCode) {
            LOG_ERROR("Failed to check if file %s exists, error: %d", logPath.c_str(), errorCode.value());
            return -EIO;
        }

        if (const bool maxSizeExceeded = !firstDump && std::filesystem::file_size(logPath) > maxFileSize;
            maxSizeExceeded) {
            LOG_DEBUG("Max log file size exceeded. Rotating log files...");

A module-utils/log/logdump/CMakeLists.txt => module-utils/log/logdump/CMakeLists.txt +19 -0
@@ 0,0 1,19 @@
add_library(logdump STATIC)

target_sources(logdump
    PRIVATE
        logdump.cpp
    PUBLIC
        include/logdump/logdump.h
)

target_include_directories(logdump
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
)

target_link_libraries(logdump
    PRIVATE
        purefs-paths
        log
)

A module-utils/log/logdump/include/logdump/logdump.h => module-utils/log/logdump/include/logdump/logdump.h +17 -0
@@ 0,0 1,17 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#ifdef __cplusplus
extern "C"
{
#endif
    /// @return: < 0 - error occurred during log flush
    /// @return:   0 - log flush did not happen
    /// @return:   1 - log flush successful
    int dumpLogs();

#ifdef __cplusplus
}
#endif

A module-utils/log/logdump/logdump.cpp => module-utils/log/logdump/logdump.cpp +11 -0
@@ 0,0 1,11 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <logdump/logdump.h>
#include <purefs/filesystem_paths.hpp>
#include <Logger.hpp>

int dumpLogs()
{
    return Log::Logger::get().dumpToFile(purefs::dir::getLogsPath() / LOG_FILE_NAME);
}

M products/BellHybrid/BellHybridMain.cpp => products/BellHybrid/BellHybridMain.cpp +7 -3
@@ 31,13 31,14 @@

#include <Application.hpp>
#include <ApplicationLauncher.hpp>
#include <Logger.hpp>
#include <log/log.hpp>
#include <logdump/logdump.h>
#include <Logger.hpp>
#include <product/version.hpp>
#include <sys/SystemManager.hpp>
#include <time/AlarmOperations.hpp>
#include <SystemWatchdog/SystemWatchdog.hpp>
#include <thread.hpp>
#include <time/AlarmOperations.hpp>

#include <memory>
#include <vector>


@@ 66,7 67,7 @@ int main()
    }

    std::vector<std::unique_ptr<sys::BaseServiceCreator>> systemServices;
    systemServices.emplace_back(sys::CreatorFor<EventManager>());
    systemServices.emplace_back(sys::CreatorFor<EventManager>([]() { return dumpLogs(); }));
    systemServices.emplace_back(sys::CreatorFor<ServiceDB>());
    systemServices.emplace_back(sys::CreatorFor<service::Audio>());
    systemServices.emplace_back(sys::CreatorFor<ServiceDesktop>());


@@ 116,6 117,9 @@ int main()
        [&platform] {
            try {
                LOG_DEBUG("System deinit");
                if (dumpLogs() != 1) {
                    LOG_ERROR("Cannot dump logs");
                }
                platform->deinit();
            }
            catch (const std::runtime_error &e) {

M products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +5 -0
@@ 17,6 17,7 @@ target_compile_options(BellHybrid

target_sources(BellHybrid
    PRIVATE
        ${TARGET_SOURCES}
        BellHybridMain.cpp
        PlatformFactory.cpp
        EinkSentinelBell.cpp


@@ 51,6 52,7 @@ target_link_libraries(BellHybrid
        bell::audio
        bell::evtmgr
        log
        logdump
        messagetype
        module-bsp
        module-vfs


@@ 101,3 103,6 @@ add_subdirectory(apps)
add_subdirectory(keymap)
add_subdirectory(services)
add_subdirectory(sys)

option(CONFIG_ENABLE_TEMP "Enable displaying temperature" OFF)
configure_file(config/ProductConfig.in.hpp ${CMAKE_BINARY_DIR}/ProductConfig.hpp  @ONLY)

M products/BellHybrid/EinkSentinelBell.cpp => products/BellHybrid/EinkSentinelBell.cpp +1 -1
@@ 9,7 9,7 @@ namespace service::eink
{
    namespace
    {
        constexpr auto RedrawEinkCpuFrequency = bsp::CpuFrequencyHz::Level_5;
        constexpr auto RedrawEinkCpuFrequency = bsp::CpuFrequencyHz::Level_4;
    } // namespace

    EinkSentinel::EinkSentinel(std::string name, sys::Service *service) : sys::CpuSentinel(name, service)

M products/BellHybrid/apps/Application.cpp => products/BellHybrid/apps/Application.cpp +8 -0
@@ 5,6 5,7 @@

#include <common/models/AlarmModel.hpp>

#include <audio/AudioMessage.hpp>
#include <appmgr/messages/IdleTimerMessage.hpp>
#include <common/BellPowerOffPresenter.hpp>
#include <common/popups/presenter/AlarmActivatedPresenter.hpp>


@@ 116,6 117,13 @@ namespace app
    void Application::onStop()
    {
        stopIdleTimer();
        stopAllAudio();
    }

    void Application::stopAllAudio()
    {
        auto msg = std::make_shared<service::AudioStopRequest>();
        this->bus.sendUnicast(msg, service::audioServiceName);
    }

    void Application::startIdleTimer()

M products/BellHybrid/apps/CMakeLists.txt => products/BellHybrid/apps/CMakeLists.txt +1 -0
@@ 18,6 18,7 @@ target_link_libraries(app
        bell::app-common
        bell::appmgr
        bell::alarms
        bell::audio
)

add_subdirectory(application-bell-main)

M products/BellHybrid/apps/application-bell-bedtime/ApplicationBellBedtime.cpp => products/BellHybrid/apps/application-bell-bedtime/ApplicationBellBedtime.cpp +2 -1
@@ 33,7 33,8 @@ namespace app
    void ApplicationBellBedtime::createUserInterface()
    {
        windowsFactory.attach(gui::name::window::main_window, [](ApplicationCommon *app, const std::string &) {
            auto bedtimeModel = std::make_unique<bell_bedtime::BedtimeModel>(app);
            auto audioModel   = std::make_unique<AudioModel>(app);
            auto bedtimeModel = std::make_unique<bell_bedtime::BedtimeModel>(app, std::move(audioModel));
            auto provider     = std::make_shared<bell_bedtime::BedtimeListItemProvider>(std::move(bedtimeModel));
            auto presenter    = std::make_unique<bell_bedtime::BellBedtimeWindowPresenter>(provider);
            return std::make_unique<gui::BellBedtimeWindow>(app, std::move(presenter));

M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp => products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp +10 -0
@@ 107,6 107,7 @@ namespace app::home_screen
    }
    void HomeScreenPresenter::handleAlarmModelReady()
    {
        setStartupAlarmState();
        getView()->setAlarmTime(alarmModel->getAlarmTime());
        stateController->handleAlarmModelReady();
    }


@@ 145,4 146,13 @@ namespace app::home_screen
    {
        return latchPressed;
    }

    void HomeScreenPresenter::setStartupAlarmState()
    {
        static auto isStartup = true;
        if (isStartup) {
            alarmModel->activate(!latchPressed);
            isStartup = false;
        }
    }
} // namespace app::home_screen

M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.hpp => products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.hpp +2 -0
@@ 149,6 149,8 @@ namespace app::home_screen
        std::unique_ptr<ProgressTimerWithSnoozeTimer> snoozeTimer;
        bool latchPressed = false;

        void setStartupAlarmState();

        static constexpr auto timerName = "HS_timer";
        static constexpr auto snoozeTick = std::chrono::seconds(1);
    };

M products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp => products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp +4 -6
@@ 45,9 45,9 @@ namespace app::home_screen
                return alarmModel.getAlarmStatus() == alarms::AlarmStatus::Ringing;
            };

            auto switchToMenu         = [](AbstractView &view) { view.switchToMenu(); };
            auto makeAlarmEditable    = [](AbstractView &view) { view.setAlarmEdit(true); };
            auto makeAlarmNonEditable = [](AbstractView &view) { view.setAlarmEdit(false); };
            auto switchToMenu          = [](AbstractView &view) { view.switchToMenu(); };
            auto makeAlarmEditable     = [](AbstractView &view) { view.setAlarmEdit(true); };
            auto makeAlarmNonEditable  = [](AbstractView &view) { view.setAlarmEdit(false); };
            auto switchToBatteryStatus = [](AbstractView &view) { view.switchToBatteryStatus(); };
            auto updateBottomStats =
                [](AbstractView &view, AbstractBatteryModel &batteryModel, AbstractTemperatureModel &temperatureModel) {


@@ 83,7 83,6 @@ namespace app::home_screen
                alarmModel.setDefaultAlarmTime();
                view.setAlarmTime(alarmModel.getAlarmTime());
            };
            auto isDeepPress = [](AbstractPresenter &presenter) -> bool { return presenter.isStartupDeepPress(); };
        } // namespace Helpers

        namespace Events


@@ 289,7 288,6 @@ namespace app::home_screen

                                             "Deactivated"_s + sml::on_entry<_> / Deactivated::entry,
                                             "Deactivated"_s + event<Events::Reset> = "Init"_s,
                                             "Deactivated"_s [Helpers::isDeepPress] = "DeactivatedWait"_s,
                                             "Deactivated"_s + event<Events::LightPress>/ Helpers::switchToMenu,
                                             "Deactivated"_s + event<Events::RotateLeftPress> / Helpers::makeAlarmEditable = "DeactivatedEdit"_s,
                                             "Deactivated"_s + event<Events::RotateRightPress> / Helpers::makeAlarmEditable = "DeactivatedEdit"_s,


@@ 363,7 361,7 @@ namespace app::home_screen
                                             "AlarmRinging"_s + sml::on_exit<_> / AlarmRinging::exit,
                                             "AlarmRinging"_s + event<Events::Reset> = "Init"_s,
                                             "AlarmRinging"_s + event<Events::Timer> [Helpers::isSnoozeAllowed] / Helpers::snooze = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::Timer> [!Helpers::isSnoozeAllowed] / Helpers::setDefaultAlarmTime  = "ActivatedWait"_s,
                                             "AlarmRinging"_s + event<Events::Timer> [!Helpers::isSnoozeAllowed] = "ActivatedWait"_s,
                                             "AlarmRinging"_s + event<Events::LightPress> = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::RotateLeftPress> = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::RotateRightPress> = "AlarmSnoozedWait"_s,

M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp => products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp +15 -3
@@ 5,6 5,7 @@
#include "data/BellMainStyle.hpp"
#include "widgets/SnoozeTimer.hpp"
#include "BellBatteryStatusWindow.hpp"
#include "ProductConfig.hpp"

#include <application-bell-main/ApplicationBellMain.hpp>
#include <apps-common/widgets/BellBaseLayout.hpp>


@@ 18,7 19,6 @@
#include <time/time_constants.hpp>
#include <widgets/AlarmSetSpinner.hpp>
#include <widgets/TimeSetFmtSpinner.hpp>
#include <widgets/TimeSetSpinner.hpp>

#include <chrono>



@@ 117,11 117,12 @@ namespace gui
        bottomBox = new HBox(body->lastBox, 0, 0, 0, 0);
        bottomBox->setMinimumSize(style::bell_base_layout::outer_layouts_w, style::bell_base_layout::outer_layouts_h);
        bottomBox->setEdges(RectangleEdge::None);
        bottomBox->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));

        battery = new BellBattery(bottomBox, 0, 0, 0, 0);
        battery->setMinimumSize(battery::battery_widget_w, battery::battery_widget_h);
        battery->setEdges(RectangleEdge::None);
        battery->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        battery->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
        battery->setVisible(false);

        bottomText = new TextFixedSize(bottomBox, 0, 0, 0, 0);


@@ 187,19 188,25 @@ namespace gui

    void BellHomeScreenWindow::setTemperature(utils::temperature::Temperature newTemp)
    {
#if CONFIG_ENABLE_TEMP == 1
        bottomText->setFont(bellMainStyle::mainWindow::bottomDescription::font_normal);
        bottomText->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        bottomText->setText(utils::temperature::tempToStrDec(newTemp));
        bottomBox->resizeItems();
#else
        bottomText->setVisible(false);
        bottomBox->resizeItems();
#endif
    }

    void BellHomeScreenWindow::setBottomDescription(const UTF8 &desc)
    {
        battery->setVisible(false);
        bottomBox->resizeItems();
        bottomText->setVisible(true);
        bottomText->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        bottomText->setFont(bellMainStyle::mainWindow::bottomDescription::font_small);
        bottomText->setRichText(desc);
        bottomBox->resizeItems();
    }

    void BellHomeScreenWindow::setBatteryLevelState(const Store::Battery &batteryContext)


@@ 209,7 216,12 @@ namespace gui
            bottomText->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        }
        else {
#if CONFIG_ENABLE_TEMP == 1
            bottomText->setAlignment(Alignment(Alignment::Horizontal::Right, Alignment::Vertical::Center));
            battery->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
#else
            battery->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
#endif
        }
        bottomBox->resizeItems();
    }

M products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.cpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.cpp +3 -2
@@ 29,12 29,13 @@ namespace app::meditation

    std::string IntervalChimePresenter::getCurrentInterval() const
    {
        // Always set interval as none
        const auto value = settings->getValue(intervalDBRecordName, settings::SettingsScope::AppLocal);
        for (auto const &option : intervalOptions) {
            if (option.first == std::chrono::minutes{0}) {
            if (utils::to_string(option.first.count()) == value) {
                return option.second;
            }
        }
        // If not found, return "None"
        return intervalOptions.at(0).second;
    }


M products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingSettingsWindow.hpp => products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingSettingsWindow.hpp +1 -1
@@ 3,7 3,7 @@

#pragma once

#include <application-bell-settings/windows/advanced/BellSettingsTimeUnitsWindow.hpp>
#include <application-bell-settings/windows/BellSettingsTimeUnitsWindow.hpp>

namespace gui
{

M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp => products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp +12 -12
@@ 18,7 18,6 @@
#include "presenter/advanced/FrontlightPresenter.hpp"
#include "windows/advanced/AboutYourBellWindow.hpp"
#include "windows/advanced/BellSettingsAdvancedWindow.hpp"
#include "windows/advanced/BellSettingsTimeUnitsWindow.hpp"
#include "windows/advanced/BellSettingsLanguageWindow.hpp"
#include "windows/advanced/BellSettingsFrontlightWindow.hpp"
#include "windows/alarm_settings/BellSettingsAlarmSettingsMenuWindow.hpp"


@@ 27,6 26,7 @@
#include "windows/alarm_settings/BellSettingsPrewakeUpWindow.hpp"
#include "windows/BellSettingsBedtimeToneWindow.hpp"
#include "windows/BellSettingsHomeViewWindow.hpp"
#include "windows/BellSettingsTimeUnitsWindow.hpp"
#include "windows/BellSettingsWindow.hpp"
#include "widgets/DialogYesNo.hpp"



@@ 87,15 87,6 @@ namespace app
                              });

        windowsFactory.attach(
            gui::window::name::bellSettingsTimeUnits, [](ApplicationCommon *app, const std::string &name) {
                auto temperatureUnitModel = std::make_unique<bell_settings::TemperatureUnitModel>(app);
                auto timeUnitsProvider    = std::make_shared<bell_settings::TimeUnitsModel>(app);
                auto presenter            = std::make_unique<bell_settings::TimeUnitsWindowPresenter>(
                    timeUnitsProvider, std::move(temperatureUnitModel));
                return std::make_unique<gui::BellSettingsTimeUnitsWindow>(app, std::move(presenter));
            });

        windowsFactory.attach(
            gui::window::name::bellSettingsLanguage, [&](ApplicationCommon *app, const std::string &name) {
                auto presenter = std::make_unique<bell_settings::LanguageWindowPresenter>(this);
                return std::make_unique<gui::BellSettingsLanguageWindow>(app, std::move(presenter), name);


@@ 122,8 113,8 @@ namespace app

        windowsFactory.attach(
            gui::window::name::bellSettingsBedtimeTone, [this](ApplicationCommon *app, const std::string &name) {
                auto bedtimeModel = std::make_shared<bell_bedtime::BedtimeModel>(app);
                auto audioModel   = std::make_unique<AudioModel>(this);
                auto audioModel   = std::make_unique<AudioModel>(app);
                auto bedtimeModel = std::make_shared<bell_bedtime::BedtimeModel>(app, std::move(audioModel));
                auto soundsRepository =
                    std::make_unique<SoundsRepository>(alarms::paths::getBedtimeReminderChimesDir());
                auto provider = std::make_shared<bell_settings::BedtimeSettingsListItemProvider>(


@@ 133,6 124,15 @@ namespace app
                return std::make_unique<gui::BellSettingsBedtimeToneWindow>(app, std::move(presenter));
            });

        windowsFactory.attach(
            gui::window::name::bellSettingsTimeUnits, [](ApplicationCommon *app, const std::string &name) {
                auto temperatureUnitModel = std::make_unique<bell_settings::TemperatureUnitModel>(app);
                auto timeUnitsProvider    = std::make_shared<bell_settings::TimeUnitsModel>(app);
                auto presenter            = std::make_unique<bell_settings::TimeUnitsWindowPresenter>(
                    timeUnitsProvider, std::move(temperatureUnitModel));
                return std::make_unique<gui::BellSettingsTimeUnitsWindow>(app, std::move(presenter));
            });

        windowsFactory.attach(gui::BellTurnOffOptionWindow::defaultName,
                              [](ApplicationCommon *app, const std::string &name) {
                                  return std::make_unique<gui::BellTurnOffOptionWindow>(app);

M products/BellHybrid/apps/application-bell-settings/CMakeLists.txt => products/BellHybrid/apps/application-bell-settings/CMakeLists.txt +2 -2
@@ 52,12 52,12 @@ target_sources(application-bell-settings
        widgets/DialogYesNo.cpp

        windows/BellSettingsBedtimeToneWindow.cpp
        windows/BellSettingsTimeUnitsWindow.cpp
        windows/BellSettingsHomeViewWindow.cpp
        windows/BellSettingsWindow.cpp
        windows/advanced/AboutYourBellWindow.cpp
        windows/advanced/BellSettingsAdvancedWindow.cpp
        windows/advanced/BellSettingsLanguageWindow.cpp
        windows/advanced/BellSettingsTimeUnitsWindow.cpp
        windows/advanced/BellSettingsFrontlightWindow.cpp
        windows/alarm_settings/BellSettingsAlarmSettingsSnoozeWindow.cpp
        windows/alarm_settings/BellSettingsAlarmSettingsMenuWindow.cpp


@@ 113,7 113,7 @@ target_sources(application-bell-settings
    PUBLIC
        include/application-bell-settings/models/TimeUnitsModel.hpp
        include/application-bell-settings/presenter/TimeUnitsPresenter.hpp
        include/application-bell-settings/windows/advanced/BellSettingsTimeUnitsWindow.hpp
        include/application-bell-settings/windows/BellSettingsTimeUnitsWindow.hpp
        include/application-bell-settings/ApplicationBellSettings.hpp
)


M products/BellHybrid/apps/application-bell-settings/data/BellSettingsStyle.hpp => products/BellHybrid/apps/application-bell-settings/data/BellSettingsStyle.hpp +1 -1
@@ 19,7 19,7 @@ namespace gui

        namespace time_fmt_set_list_item
        {
            inline constexpr auto font = style::window::font::supersizemelight;
            inline constexpr auto font = style::window::font::supersizeme;
        } // namespace time_fmt_set_list_item

        namespace top_text

R products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/windows/advanced/BellSettingsTimeUnitsWindow.hpp => products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/windows/BellSettingsTimeUnitsWindow.hpp +0 -0
M products/BellHybrid/apps/application-bell-settings/models/TimeUnitsModel.cpp => products/BellHybrid/apps/application-bell-settings/models/TimeUnitsModel.cpp +15 -11
@@ 5,10 5,10 @@
#include "widgets/TimeFormatSetListItem.hpp"
#include "widgets/TimeSetListItem.hpp"
#include "widgets/TemperatureUnitListItem.hpp"
#include "ProductConfig.hpp"

#include <gui/widgets/ListViewEngine.hpp>
#include <gui/widgets/Style.hpp>
#include <gui/widgets/text/Text.hpp>
#include <service-time/Constants.hpp>
#include <service-time/api/TimeSettingsApi.hpp>
#include <service-time/service-time/TimeMessage.hpp>


@@ 56,9 56,11 @@ namespace app::bell_settings
            timeSetListItem->timeSetFmtSpinner->setTimeFormat(timeFmtSetListItem->getTimeFmt());
        };

#if CONFIG_ENABLE_TEMP == 1
        temperatureUnitListItem =
            new gui::TemperatureUnitListItem(utils::translate("app_bell_settings_advanced_temp_scale"));
        internalData.push_back(temperatureUnitListItem);
#endif

        for (auto item : internalData) {
            item->deleteByList = false;


@@ 72,27 74,23 @@ namespace app::bell_settings

    void TimeUnitsModel::saveData()
    {
        const auto now     = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        const auto newTime = std::localtime(&now);
        newTime->tm_hour   = timeSetListItem->timeSetFmtSpinner->getHour();
        newTime->tm_min    = timeSetListItem->timeSetFmtSpinner->getMinute();
        const auto newTime = timeSetListItem->timeSetFmtSpinner->getTime();
        const auto time_tm = std::localtime(&newTime);
        const auto newFmt  = timeFmtSetListItem->getTimeFmt();
        LOG_INFO("Setting new time: %d:%d fmt: %s",
                 newTime->tm_hour,
                 newTime->tm_min,
                 time_tm->tm_hour,
                 time_tm->tm_min,
                 utils::time::Locale::format(newFmt).c_str());
        sendRtcUpdateTimeMessage(std::mktime(newTime));
        sendRtcUpdateTimeMessage(newTime);
        sendTimeFmtUpdateMessage(newFmt);
    }

    void TimeUnitsModel::loadData()
    {
        const auto now        = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        const auto time       = std::localtime(&now);
        const auto timeFormat = stm::api::timeFormat();
        timeSetListItem->timeSetFmtSpinner->setHour(time->tm_hour);
        timeSetListItem->timeSetFmtSpinner->setMinute(time->tm_min);
        timeSetListItem->timeSetFmtSpinner->setTimeFormat(timeFormat);
        timeSetListItem->timeSetFmtSpinner->setTime(now);
        timeFmtSetListItem->setTimeFmt(timeFormat);
    }



@@ 116,12 114,18 @@ namespace app::bell_settings

    auto TimeUnitsModel::getTemperatureUnit() const -> utils::temperature::Temperature::Unit
    {
#if CONFIG_ENABLE_TEMP == 1
        return *utils::temperature::strToUnit(temperatureUnitListItem->getUnitAsStr());
#else
        return utils::temperature::Temperature::Unit::Celsius;
#endif
    }

    auto TimeUnitsModel::setTemperatureUnit(const utils::temperature::Temperature::Unit unit) -> void
    {
#if CONFIG_ENABLE_TEMP == 1
        temperatureUnitListItem->setUnit(unit);
#endif
    }

    void TimeUnitsModelFactoryResetValues::loadData()

R products/BellHybrid/apps/application-bell-settings/windows/advanced/BellSettingsTimeUnitsWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTimeUnitsWindow.cpp +2 -2
@@ 3,7 3,7 @@

#include "application-bell-settings/ApplicationBellSettings.hpp"
#include "BellSettingsStyle.hpp"
#include "windows/advanced/BellSettingsTimeUnitsWindow.hpp"
#include "windows/BellSettingsTimeUnitsWindow.hpp"

#include <gui/input/InputEvent.hpp>
#include <apps-common/options/OptionStyle.hpp>


@@ 24,7 24,7 @@ namespace gui
        finishedCallback = [this]() {
            application->switchWindow(
                window::bell_finished::defaultName,
                BellFinishedWindowData::Factory::create("circle_success_big", gui::window::name::bellSettingsAdvanced));
                BellFinishedWindowData::Factory::create("circle_success_big", gui::name::window::main_window));
        };
    }


M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsWindow.cpp +1 -0
@@ 44,6 44,7 @@ namespace gui

        addWinSettings(utils::translate("app_bell_settings_alarm_settings"), BellSettingsAlarmSettingsMenuWindow::name);
        addWinSettings(utils::translate("app_bell_settings_bedtime_tone"), window::name::bellSettingsBedtimeTone);
        addWinSettings(utils::translate("app_bell_settings_time_units"), window::name::bellSettingsTimeUnits);
        addWinSettings(utils::translate("app_bell_settings_advanced"), window::name::bellSettingsAdvanced);
        addWinSettings(utils::translate("app_bell_settings_turn_off"), BellTurnOffOptionWindow::defaultName);


M products/BellHybrid/apps/application-bell-settings/windows/advanced/BellSettingsAdvancedWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/advanced/BellSettingsAdvancedWindow.cpp +0 -3
@@ 69,9 69,6 @@ namespace gui
                std::make_unique<gui::option::OptionBellMenu>(name, callback(window), nullptr, this));
        };

        addOption(utils::translate("app_bell_settings_advanced_time_units"),
                  gui::window::name::bellSettingsTimeUnits,
                  defaultCallback);
        addOption(utils::translate("app_bell_settings_advanced_language"),
                  gui::window::name::bellSettingsLanguage,
                  defaultCallback);

M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +1 -0
@@ 38,6 38,7 @@ target_sources(application-bell-common
        src/options/BellOptionWindow.cpp
        src/options/BellShortOptionWindow.cpp
        src/options/OptionBellMenu.cpp
        src/options/BellOptionsNavigation.cpp
    PUBLIC
        include/common/BellListItemProvider.hpp
        include/common/SoundsRepository.hpp

M products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp => products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp +1 -2
@@ 65,9 65,8 @@ namespace app::bell_bedtime
      public:
        BedtimeModel() = delete;

        explicit BedtimeModel(sys::Service *app)
        explicit BedtimeModel(ApplicationCommon *app, std::unique_ptr<AudioModel> &&audioModel)
        {
            audioModel    = std::make_unique<AudioModel>(static_cast<ApplicationCommon *>(app));
            bedtimeOnOff  = std::make_unique<bell_bedtime::BedtimeOnOffModel>(app);
            bedtimeTime   = std::make_unique<bell_bedtime::BedtimeTimeModel>(app);
            bedtimeTone   = std::make_unique<bell_bedtime::AlarmToneModel>(app);

A products/BellHybrid/apps/common/include/common/options/BellOptionsNavigation.hpp => products/BellHybrid/apps/common/include/common/options/BellOptionsNavigation.hpp +11 -0
@@ 0,0 1,11 @@
// 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 <InputEvent.hpp>

namespace gui
{
    InputEvent invertNavigationDirection(const InputEvent &inputEvent);
}; // namespace gui

M products/BellHybrid/apps/common/src/options/BellOptionWindow.cpp => products/BellHybrid/apps/common/src/options/BellOptionWindow.cpp +6 -0
@@ 3,6 3,7 @@

#include "common/options/BellOptionWindow.hpp"
#include "common/options/OptionBellMenu.hpp"
#include "common/options/BellOptionsNavigation.hpp"

#include <messages/OptionsWindow.hpp>
#include <TextFixedSize.hpp>


@@ 38,6 39,11 @@ namespace gui
        optionsList->prepareRebuildCallback = [this]() { recreateOptions(); };
        optionsModel->createData(options);

        auto storedCallback        = optionsList->inputCallback;
        optionsList->inputCallback = [&, storedCallback](Item &item, const InputEvent &event) {
            return storedCallback(item, invertNavigationDirection(event));
        };

        setFocusItem(optionsList);
    }


A products/BellHybrid/apps/common/src/options/BellOptionsNavigation.cpp => products/BellHybrid/apps/common/src/options/BellOptionsNavigation.cpp +19 -0
@@ 0,0 1,19 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "common/options/BellOptionsNavigation.hpp"

namespace gui
{
    InputEvent invertNavigationDirection(const InputEvent &inputEvent)
    {
        InputEvent input = inputEvent;
        if (input.is(KeyCode::KEY_UP)) {
            input.setKeyCode(KeyCode::KEY_DOWN);
        }
        else if (input.is(KeyCode::KEY_DOWN)) {
            input.setKeyCode(KeyCode::KEY_UP);
        }
        return input;
    }
}; // namespace gui

M products/BellHybrid/apps/common/src/options/BellShortOptionWindow.cpp => products/BellHybrid/apps/common/src/options/BellShortOptionWindow.cpp +7 -0
@@ 3,6 3,7 @@

#include "common/options/BellShortOptionWindow.hpp"
#include "common/options/OptionBellMenu.hpp"
#include "common/options/BellOptionsNavigation.hpp"

#include <messages/OptionsWindow.hpp>
#include <TextFixedSize.hpp>


@@ 14,6 15,11 @@ namespace gui
                                    app, style::bell_options::h + 2 * style::bell_options::option_margin))
    {
        buildInterface();

        auto storedCallback        = optionsList->inputCallback;
        optionsList->inputCallback = [&, storedCallback](Item &item, const InputEvent &event) {
            return storedCallback(item, invertNavigationDirection(event));
        };
    }

    void BellShortOptionWindow::rebuild()


@@ 72,4 78,5 @@ namespace gui

        optionsList->rebuildList(listview::RebuildType::InPlace);
    }

} /* namespace gui */

M products/BellHybrid/apps/include/Application.hpp => products/BellHybrid/apps/include/Application.hpp +1 -0
@@ 18,6 18,7 @@ namespace app
        void startIdleTimer();
        void restartIdleTimer();
        void stopIdleTimer();
        void stopAllAudio();

      private:
        sys::MessagePointer handleKBDKeyEvent(sys::Message *msgl) override;

R products/BellHybrid/config.h => products/BellHybrid/config/ProductConfig.in.hpp +1 -1
@@ 3,4 3,4 @@

#pragma once

#define ENABLE_GSM (0)
#cmakedefine01 CONFIG_ENABLE_TEMP

M products/BellHybrid/services/appmgr/include/appmgr/IdleHandler.hpp => products/BellHybrid/services/appmgr/include/appmgr/IdleHandler.hpp +1 -1
@@ 11,7 11,7 @@

namespace app::manager
{
    constexpr auto idleReturnTimeout = std::chrono::minutes{3};
    constexpr auto idleReturnTimeout = std::chrono::seconds{10};
    using connectFunction            = std::function<bool(const std::type_info &, sys::MessageHandler)>;

    class IdleHandler

M products/BellHybrid/services/evtmgr/EventManager.cpp => products/BellHybrid/services/evtmgr/EventManager.cpp +4 -3
@@ 36,8 36,9 @@ namespace
    };
}

EventManager::EventManager(const std::string &name)
    : EventManagerCommon(name), temperatureSource{hal::temperature::AbstractTemperatureSource::Factory::create()},
EventManager::EventManager(LogDumpFunction logDumpFunction, const std::string &name)
    : EventManagerCommon(logDumpFunction, name),
      temperatureSource{hal::temperature::AbstractTemperatureSource::Factory::create()},
      backlightHandler(settings, this), userActivityHandler(std::make_shared<sys::CpuSentinel>(name, this), this)
{
    buildKeySequences();


@@ 73,7 74,7 @@ void EventManager::initProductEvents()
    backlightHandler.init();

    connect(typeid(sevm::ScreenLightControlMessage), [&](sys::Message *msgl) {
        auto *m = static_cast<sevm::ScreenLightControlMessage *>(msgl);
        auto *m           = static_cast<sevm::ScreenLightControlMessage *>(msgl);
        const auto params = m->getParams();
        backlightHandler.processScreenRequest(m->getAction(), params.value_or(screen_light_control::Parameters()));
        return sys::msgHandled();

M products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp => products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp +2 -1
@@ 18,7 18,8 @@ namespace hal::temperature
class EventManager : public EventManagerCommon
{
  public:
    explicit EventManager(const std::string &name = service::name::evt_manager);
    explicit EventManager(LogDumpFunction logDumpFunction = nullptr,
                          const std::string &name         = service::name::evt_manager);

  private:
    void handleKeyEvent(sys::Message *msg) override;

M products/BellHybrid/services/time/AlarmOperations.cpp => products/BellHybrid/services/time/AlarmOperations.cpp +18 -5
@@ 9,6 9,8 @@
#include <db/SystemSettings.hpp>
#include <time/dateCommon.hpp>

#include <string>

namespace alarms
{
    namespace


@@ 55,19 57,30 @@ namespace alarms
        {
          public:
            explicit BedtimeSettingsProviderImpl(sys::Service *service)
                : bedtimeModel{std::make_unique<app::bell_bedtime::BedtimeModel>(service)}
            {}
                : bedtimeTimeModel{std::make_unique<app::bell_bedtime::BedtimeTimeModel>(service)}
            {
                settings.init(service::ServiceProxy{service->weak_from_this()});
            }
            auto isBedtimeEnabled() -> bool override
            {
                return bedtimeModel.get()->getBedtimeOnOff().getValue();
                bool enabled = false;
                try {
                    enabled =
                        std::stoi(settings.getValue(bell::settings::Bedtime::active, settings::SettingsScope::Global));
                }
                catch (const std::exception &e) {
                    LOG_ERROR("BedtimeSettingsProviderImpl active db record not valid! err: %s", e.what());
                }
                return enabled;
            }
            auto getBedtimeTime() -> time_t override
            {
                return bedtimeModel.get()->getBedtimeTime().getValue();
                return bedtimeTimeModel->getValue();
            }

          private:
            std::unique_ptr<app::bell_bedtime::BedtimeModel> bedtimeModel;
            std::unique_ptr<app::bell_bedtime::BedtimeTimeModel> bedtimeTimeModel;
            settings::Settings settings;
        };
    } // namespace


M products/PurePhone/CMakeLists.txt => products/PurePhone/CMakeLists.txt +1 -0
@@ 63,6 63,7 @@ target_link_libraries(PurePhone
        db
        evtmgr
        log
        logdump
        messagetype
        module-apps
        module-bsp

M products/PurePhone/PurePhoneMain.cpp => products/PurePhone/PurePhoneMain.cpp +6 -2
@@ 60,12 60,13 @@
#include <Application.hpp>
#include <ApplicationLauncher.hpp>
#include <log/log.hpp>
#include <logdump/logdump.h>
#include <Logger.hpp>
#include <product/version.hpp>
#include <sys/SystemManager.hpp>
#include <time/AlarmOperations.hpp>
#include <SystemWatchdog/SystemWatchdog.hpp>
#include <thread.hpp>
#include <time/AlarmOperations.hpp>

#include <memory>
#include <vector>


@@ 94,7 95,7 @@ int main()
    }

    std::vector<std::unique_ptr<sys::BaseServiceCreator>> systemServices;
    systemServices.emplace_back(sys::CreatorFor<EventManager>());
    systemServices.emplace_back(sys::CreatorFor<EventManager>([]() { return dumpLogs(); }));
    systemServices.emplace_back(sys::CreatorFor<service::ServiceFileIndexer>());
    systemServices.emplace_back(sys::CreatorFor<ServiceDB>());
#if ENABLE_GSM == 0


@@ 189,6 190,9 @@ int main()
        [&platform] {
            try {
                LOG_DEBUG("System deinit");
                if (dumpLogs() != 1) {
                    LOG_ERROR("Cannot dump logs");
                }
                platform->deinit();
            }
            catch (const std::runtime_error &e) {

M products/PurePhone/services/evtmgr/include/evtmgr/EventManager.hpp => products/PurePhone/services/evtmgr/include/evtmgr/EventManager.hpp +3 -2
@@ 12,8 12,9 @@
class EventManager : public EventManagerCommon
{
  public:
    explicit EventManager(const std::string &name = service::name::evt_manager)
        : EventManagerCommon(name), vibrator(std::make_unique<vibra_handle::Vibra>(this)),
    explicit EventManager(LogDumpFunction logDumpFunction = nullptr,
                          const std::string &name         = service::name::evt_manager)
        : EventManagerCommon(logDumpFunction, name), vibrator(std::make_unique<vibra_handle::Vibra>(this)),
          backlightHandler(settings, this)
    {}


M products/PurePhone/test/test-settings/test-service-db-settings-api.cpp => products/PurePhone/test/test-settings/test-service-db-settings-api.cpp +1 -2
@@ 57,8 57,7 @@ TEST_CASE("SettingsApi")
                testStart = std::make_shared<std::mutex>();
                testStart->lock();
                std::cout << "start thr_id: " << std::this_thread::get_id() << std::endl << std::flush;
                auto ret = sys::SystemManagerCommon::RunSystemService(
                    std::make_shared<EventManager>(service::name::evt_manager), manager.get());
                auto ret = sys::SystemManagerCommon::RunSystemService(std::make_shared<EventManager>(), manager.get());
                ret &= sys::SystemManagerCommon::RunSystemService(std::make_shared<ServiceDB>(), manager.get());

                varWritter = std::make_shared<settings::MyService>("writterVar");

M third-party/CrashDebug/CrashCatcher/CrashCatcherPriv.h => third-party/CrashDebug/CrashCatcher/CrashCatcherPriv.h +84 -84
@@ 1,84 1,84 @@
/* Copyright (C) 2017  Adam Green (https://github.com/adamgreen)

   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.
*/
/* Private header file shared with unit tests. */
#ifndef _CRASH_CATCHER_PRIV_H_
#define _CRASH_CATCHER_PRIV_H_


/* Definitions used by assembly language and C code. */
#define CRASH_CATCHER_STACK_WORD_COUNT 125

/* Does this device support THUMB instructions for FPU access? */
#ifdef __ARM_ARCH_7EM__
#define CRASH_CATCHER_WITH_FPU 1
#else
#define CRASH_CATCHER_WITH_FPU 0
#endif


/* Definitions only required from C code. */
#if !defined(__ASSEMBLER__) || (!__ASSEMBLER__)

#include <stdint.h>


/* Bit in LR to indicate whether PSP was used for automatic stacking of registers during exception entry. */
#define LR_PSP (1 << 2)

/* Bit in LR set to 0 when automatic stacking of floating point registers occurs during exception handling. */
#define LR_FLOAT (1 << 4)


/* Bit in auto stacked xPSR which indicates whether stack was force 8-byte aligned. */
#define PSR_STACK_ALIGN (1 << 9)

/* This structure is filled in by the Hard Fault exception handler (or unit test) and then passed in as a parameter to
   CrashCatcher_Entry(). */
typedef struct
{
    uint32_t msp;
    uint32_t psp;
    uint32_t exceptionPSR;
    uint32_t r4;
    uint32_t r5;
    uint32_t r6;
    uint32_t r7;
    uint32_t r8;
    uint32_t r9;
    uint32_t r10;
    uint32_t r11;
    uint32_t exceptionLR;
} CrashCatcherExceptionRegisters;

/* This is the area of memory that would normally be used for the stack when running on an actual Cortex-M
   processor.  Unit tests can write to this buffer to simulate stack overflow. */
extern uint32_t g_crashCatcherStack[CRASH_CATCHER_STACK_WORD_COUNT];


/* The main entry point into CrashCatcher.  Is called from the HardFault exception handler and unit tests. */
void CrashCatcher_Entry(const CrashCatcherExceptionRegisters* pExceptionRegisters);

/* Called from CrashCatcher core to copy all floating point registers to supplied buffer. The supplied buffer must be
   large enough to contain 33 32-bit values (S0-S31 & FPCSR). */
void CrashCatcher_CopyAllFloatingPointRegisters(uint32_t* pBuffer);

/* Called from CrashCatcher core to copy upper 16 floating point registers to supplied buffer. The supplied buffer must be
   large enough to contain 16 32-bit values (S16-S31). */
void CrashCatcher_CopyUpperFloatingPointRegisters(uint32_t* pBuffer);

#endif // #if !defined(__ASSEMBLER__) || (!__ASSEMBLER__)


#endif /* _CRASH_CATCHER_PRIV_H_ */
/* Copyright (C) 2017  Adam Green (https://github.com/adamgreen)

   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.
*/
/* Private header file shared with unit tests. */
#ifndef _CRASH_CATCHER_PRIV_H_
#define _CRASH_CATCHER_PRIV_H_


/* Definitions used by assembly language and C code. */
#define CRASH_CATCHER_STACK_WORD_COUNT  8192

/* Does this device support THUMB instructions for FPU access? */
#ifdef __ARM_ARCH_7EM__
#define CRASH_CATCHER_WITH_FPU 1
#else
#define CRASH_CATCHER_WITH_FPU 0
#endif


/* Definitions only required from C code. */
#if !defined(__ASSEMBLER__) || (!__ASSEMBLER__)

#include <stdint.h>


/* Bit in LR to indicate whether PSP was used for automatic stacking of registers during exception entry. */
#define LR_PSP (1 << 2)

/* Bit in LR set to 0 when automatic stacking of floating point registers occurs during exception handling. */
#define LR_FLOAT (1 << 4)


/* Bit in auto stacked xPSR which indicates whether stack was force 8-byte aligned. */
#define PSR_STACK_ALIGN (1 << 9)

/* This structure is filled in by the Hard Fault exception handler (or unit test) and then passed in as a parameter to
   CrashCatcher_Entry(). */
typedef struct
{
    uint32_t msp;
    uint32_t psp;
    uint32_t exceptionPSR;
    uint32_t r4;
    uint32_t r5;
    uint32_t r6;
    uint32_t r7;
    uint32_t r8;
    uint32_t r9;
    uint32_t r10;
    uint32_t r11;
    uint32_t exceptionLR;
} CrashCatcherExceptionRegisters;

/* This is the area of memory that would normally be used for the stack when running on an actual Cortex-M
   processor.  Unit tests can write to this buffer to simulate stack overflow. */
extern uint32_t g_crashCatcherStack[CRASH_CATCHER_STACK_WORD_COUNT];


/* The main entry point into CrashCatcher.  Is called from the HardFault exception handler and unit tests. */
void CrashCatcher_Entry(const CrashCatcherExceptionRegisters* pExceptionRegisters);

/* Called from CrashCatcher core to copy all floating point registers to supplied buffer. The supplied buffer must be
   large enough to contain 33 32-bit values (S0-S31 & FPCSR). */
void CrashCatcher_CopyAllFloatingPointRegisters(uint32_t* pBuffer);

/* Called from CrashCatcher core to copy upper 16 floating point registers to supplied buffer. The supplied buffer must be
   large enough to contain 16 32-bit values (S16-S31). */
void CrashCatcher_CopyUpperFloatingPointRegisters(uint32_t* pBuffer);

#endif // #if !defined(__ASSEMBLER__) || (!__ASSEMBLER__)


#endif /* _CRASH_CATCHER_PRIV_H_ */

M third-party/CrashDebug/CrashCatcher/CrashCatcher_armv7m.S => third-party/CrashDebug/CrashCatcher/CrashCatcher_armv7m.S +47 -2
@@ 42,7 42,7 @@ HardFault_Handler:
        r11
        exceptionLR */
    // Prevent double fault
    ldr r0, = crash_orig_stack
    ldr r0, =crash_orig_stack
    ldr r0, [r0]
    cmp r0, #0
    bne .


@@ 53,7 53,6 @@ HardFault_Handler:
    mrs     r1, msp
    ldr     sp, =(g_crashCatcherStack + 4 * CRASH_CATCHER_STACK_WORD_COUNT)
    push.w  {r1-r11,lr}

    // Call original console dump
    ldr r0,=crash_orig_stack
    str sp, [r0]


@@ 127,6 126,52 @@ CrashCatcher_CopyUpperFloatingPointRegisters:
    .size   CrashCatcher_CopyUpperFloatingPointRegisters, .-CrashCatcher_CopyUpperFloatingPointRegisters


	/*
		This function is called by the SVC #1 syscall
		and then collect stack data for the crash dump
		which will be run in the second stage
		It also changes stack to the static internal
		due to possibility of corruption of the oryginal
		stack frame
		extern "C" void _StackTrace_Dump_svc_1(void);
    */
    .global _StackTrace_Dump_svc_1
    .type _StackTrace_Dump_svc_1 , %function
    .thumb_func
_StackTrace_Dump_svc_1:
    mrs     r3, xpsr
    mrs     r2, psp
    mrs     r1, msp
    ldr     sp, =(g_crashCatcherStack + 4 * CRASH_CATCHER_STACK_WORD_COUNT)
    push.w  {r1-r11,lr}

	ldr     r0, =crash_orig_stack
    str    	sp, [r0]

    mov     sp, r1
    bx      lr
    .pool
    .size   _StackTrace_Dump_svc_1, .-_StackTrace_Dump_svc_1


	/* This function is the second stage of the crash dump
	   crash orig stack should contain valid stack from
	   the exception and now crash catcher should be able
	   to read stack frame pointer and dump data in the
	   user mode from the second part of the exit function
	   In our model crash newer return to the caller so
	   we can use simply branch without care about unstacking
      extern "C" void _StackTrace_Dump_stage_2(void);
	*/
    .global _StackTrace_Dump_stage_2
    .type _StackTrace_Dump_stage_2 , %function
    .thumb_func
_StackTrace_Dump_stage_2:
	 ldr	 r0, =crash_orig_stack
	 ldr     r0, [r0]
     b      CrashCatcher_Entry
    .pool
    .size   _StackTrace_Dump_stage_2, .-_StackTrace_Dump_stage_2

    .data
    crash_orig_stack: .long 0