M => +3 -2
@@ 40,8 40,9 @@ namespace app::popup
template <typename requestType, typename responseType> void AlarmPopupContract::AlarmModel::snoozeAlarm()
{
auto request =
std::make_unique<requestType>(record->ID, TimePointNow() + std::chrono::minutes(record->snoozeDuration));
auto request = std::make_unique<requestType>(record->ID,
std::chrono::floor<std::chrono::minutes>(TimePointNow()) +
std::chrono::minutes(record->snoozeDuration));
auto task = async(std::move(request), service::name::service_time);
auto cb = [&](auto response) {
auto result = dynamic_cast<responseType *>(response);
M module-bluetooth/Bluetooth/BluetoothWorker.cpp => module-bluetooth/Bluetooth/BluetoothWorker.cpp +14 -0
@@ 157,6 157,7 @@ auto BluetoothWorker::handleCommand(QueueHandle_t queue) -> bool
case bluetooth::Command::Unpair:
controller->processCommand(command);
removeFromBoundDevices(command.getDevice().address);
+ handleUnpairDisconnect(command.getDevice());
break;
case bluetooth::Command::None:
break;
@@ 284,3 285,16 @@ void BluetoothWorker::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDe
cpp_freertos::LockGuard lock(loopMutex);
profileManager->setAudioDevice(std::move(device));
}
+auto BluetoothWorker::isAddressConnected(const uint8_t *addr) -> bool
+{
+ auto deviceAddr =
+ std::visit(bluetooth::StringVisitor(), this->settings->getValue(bluetooth::Settings::ConnectedDevice));
+ return static_cast<bool>(deviceAddr == bd_addr_to_str(addr));
+}
+void BluetoothWorker::handleUnpairDisconnect(const Devicei &device)
+{
+ if (isAddressConnected(device.address)) {
+ auto disconnectCmd = bluetooth::Command(bluetooth::Command::DisconnectAudio, device);
+ controller->processCommand(disconnectCmd);
+ }
+}
M module-bluetooth/Bluetooth/BluetoothWorker.hpp => module-bluetooth/Bluetooth/BluetoothWorker.hpp +2 -0
@@ 80,6 80,8 @@ class BluetoothWorker : private sys::Worker
void onLinkKeyAdded(const std::string &deviceAddress);
void initDevicesList();
void removeFromBoundDevices(uint8_t *addr);
+ auto isAddressConnected(const bd_addr_t addr) -> bool;
+ void handleUnpairDisconnect(const Devicei &device);
public:
enum Error
M module-bluetooth/Bluetooth/CommandHandler.cpp => module-bluetooth/Bluetooth/CommandHandler.cpp +0 -3
@@ 152,9 152,6 @@ namespace bluetooth
Error::Code CommandHandler::unpair(const Devicei &device)
{
LOG_INFO("Unpairing...");
- if (profileManager->isAddressActuallyUsed(device.address)) {
- profileManager->disconnect();
- }
const auto error_code = driver->unpair(device) ? Error::Success : Error::LibraryError;
LOG_INFO("Unpairing result: %s", magic_enum::enum_name(error_code).data());
return error_code;
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp +0 -5
@@ 47,7 47,6 @@ namespace bluetooth
ptr->connect();
}
}
-
return Error::Success;
}
@@ 116,10 115,6 @@ namespace bluetooth
profilesList[profileType]->setAudioDevice(device);
return switchProfile(profileType);
}
- auto ProfileManager::isAddressActuallyUsed(const bd_addr_t address) -> bool
- {
- return !static_cast<bool>(bd_addr_cmp(address, remoteAddr));
- }
auto ProfileManager::callAnswered() -> Error::Code
{
return currentProfilePtr->callAnswered();
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp +0 -3
@@ 45,15 45,12 @@ namespace bluetooth
auto initializeCall() -> Error::Code;
auto callAnswered() -> Error::Code;
auto setIncomingCallNumber(const std::string &num) -> Error::Code;
- auto isAddressActuallyUsed(const bd_addr_t address) -> bool;
-
auto setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Error::Code;
private:
sys::Service *ownerService;
ProfileList profilesList;
bluetooth::Profile *currentProfilePtr = nullptr;
- bd_addr_t remoteAddr{};
bool initialized = false;
};
} // namespace bluetooth
M module-os/board/rt1051/_exit.cpp => module-os/board/rt1051/_exit.cpp +12 -10
@@ 44,17 44,19 @@
static void __attribute__((noreturn)) stop_system(void)
{
- 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...");
+ if(!isIRQ()) {
+ 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...");
+ haltIfDebugging();
vTaskEndScheduler();
NVIC_SystemReset();
// waiting for system reset
@@ 68,7 70,7 @@ static void __attribute__((noreturn)) stop_system(void)
void __attribute__((noreturn, used)) _exit_backtrace(int code, bool bt_dump)
{
LOG_INFO("_exit %d", code);
- if( bt_dump ) {
+ if( bt_dump && !isIRQ() ) {
_StackTrace_Dump_And_Abort();
}
stop_system();
M module-platform/linux/tests/unittest_filesystem_core.cpp => module-platform/linux/tests/unittest_filesystem_core.cpp +71 -0
@@ 366,3 366,74 @@ TEST_CASE("Corefs: Autodetect filesystems")
REQUIRE(fscore->mount("emmc0part0", "/sys", "auto") == 0);
REQUIRE(fscore->umount("/sys") == 0);
}
+
+TEST_CASE("Corefs: stat extended")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ purefs::fs::filesystem fs_core(dm);
+ const auto vfs_vfat = std::make_shared<fs::drivers::filesystem_vfat>();
+ REQUIRE(vfs_vfat->mount_count() == 0);
+ auto ret = fs_core.register_filesystem("vfat", vfs_vfat);
+ REQUIRE(ret == 0);
+ REQUIRE(fs_core.mount("emmc0part0", "/sys", "vfat") == 0);
+
+ // Check if it is a directory
+ struct stat st;
+ REQUIRE(fs_core.stat("/sys", st) == 0);
+ REQUIRE(S_ISDIR(st.st_mode));
+ REQUIRE(fs_core.stat("/sys/", st) == 0);
+ REQUIRE(S_ISDIR(st.st_mode));
+ // Check for dir and subdir
+ const auto dir = "/sys/advdirx";
+ const auto fil = "/sys/advdirx/advfile";
+ // Create directory and truncated file
+ REQUIRE(fs_core.mkdir(dir, 0755) == 0);
+ auto fd = fs_core.open(fil, O_CREAT | O_RDWR, 0);
+ REQUIRE(fd >= 3);
+ REQUIRE(fs_core.ftruncate(fd, 124567) == 0);
+ REQUIRE(fs_core.close(fd) == 0);
+ fd = -1;
+
+ // Now check for stat for directories and sub dirs
+ // Root dir
+ REQUIRE(fs_core.stat("/sys", st) == 0);
+ REQUIRE(S_ISFIFO(st.st_mode) == 0);
+ REQUIRE(S_ISCHR(st.st_mode) == 0);
+ REQUIRE(S_ISDIR(st.st_mode));
+ REQUIRE(S_ISBLK(st.st_mode) == 0);
+ REQUIRE(S_ISLNK(st.st_mode) == 0);
+ REQUIRE(S_ISSOCK(st.st_mode) == 0);
+ REQUIRE(S_ISREG(st.st_mode) == 0);
+
+ // Sub dir
+ REQUIRE(fs_core.stat(dir, st) == 0);
+ REQUIRE(S_ISFIFO(st.st_mode) == 0);
+ REQUIRE(S_ISCHR(st.st_mode) == 0);
+ REQUIRE(S_ISDIR(st.st_mode));
+ REQUIRE(S_ISBLK(st.st_mode) == 0);
+ REQUIRE(S_ISLNK(st.st_mode) == 0);
+ REQUIRE(S_ISSOCK(st.st_mode) == 0);
+ REQUIRE(S_ISREG(st.st_mode) == 0);
+
+ // Check for file
+ REQUIRE(0 == fs_core.stat(fil, st));
+ REQUIRE(124567 == st.st_size);
+ REQUIRE(S_ISFIFO(st.st_mode) == 0);
+ REQUIRE(S_ISCHR(st.st_mode) == 0);
+ REQUIRE(S_ISDIR(st.st_mode) == 0);
+ REQUIRE(S_ISBLK(st.st_mode) == 0);
+ REQUIRE(S_ISLNK(st.st_mode) == 0);
+ REQUIRE(S_ISSOCK(st.st_mode) == 0);
+ REQUIRE(S_ISREG(st.st_mode));
+
+ // Final cleanup
+ REQUIRE(0 == fs_core.unlink(fil));
+ REQUIRE(0 == fs_core.rmdir(dir));
+
+ // Final umount
+ REQUIRE(fs_core.umount("/sys") == 0);
+}
M module-platform/linux/tests/unittest_filesystem_ext4.cpp => module-platform/linux/tests/unittest_filesystem_ext4.cpp +64 -1
@@ 239,7 239,7 @@ TEST_CASE("ext4: Directory tests")
REQUIRE(fs_core->umount("/sys") == 0);
}
-TEST_CASE("littlefs: Remount RO->RW->RW")
+TEST_CASE("ext4: Remount RO->RW->RW")
{
using namespace purefs;
static constexpr auto filename = "/sys/remount_test.txt";
@@ 276,3 276,66 @@ TEST_CASE("littlefs: Remount RO->RW->RW")
REQUIRE(fs_core->umount("/sys") == 0);
}
+
+TEST_CASE("ext4: stat extended")
+{
+ using namespace purefs;
+ auto [fs_core, dm] = prepare_filesystem("emmc0");
+ REQUIRE(fs_core);
+ REQUIRE(fs_core->mount("emmc0part0", "/sys", "ext4") == 0);
+ // Check if it is a directory
+ struct stat st;
+ REQUIRE(fs_core->stat("/sys", st) == 0);
+ REQUIRE(S_ISDIR(st.st_mode));
+ REQUIRE(fs_core->stat("/sys/", st) == 0);
+ REQUIRE(S_ISDIR(st.st_mode));
+ // Check for dir and subdir
+ const auto dir = "/sys/advdirx";
+ const auto fil = "/sys/advdirx/advfile";
+ // Create directory and truncated file
+ REQUIRE(fs_core->mkdir(dir, 0755) == 0);
+ auto fd = fs_core->open(fil, O_CREAT | O_RDWR, 0);
+ REQUIRE(fd >= 3);
+ REQUIRE(fs_core->ftruncate(fd, 124567) == 0);
+ REQUIRE(fs_core->close(fd) == 0);
+ fd = -1;
+
+ // Now check for stat for directories and sub dirs
+ // Root dir
+ REQUIRE(fs_core->stat("/sys", st) == 0);
+ REQUIRE(S_ISFIFO(st.st_mode) == 0);
+ REQUIRE(S_ISCHR(st.st_mode) == 0);
+ REQUIRE(S_ISDIR(st.st_mode));
+ REQUIRE(S_ISBLK(st.st_mode) == 0);
+ REQUIRE(S_ISLNK(st.st_mode) == 0);
+ REQUIRE(S_ISSOCK(st.st_mode) == 0);
+ REQUIRE(S_ISREG(st.st_mode) == 0);
+
+ // Sub dir
+ REQUIRE(fs_core->stat(dir, st) == 0);
+ REQUIRE(S_ISFIFO(st.st_mode) == 0);
+ REQUIRE(S_ISCHR(st.st_mode) == 0);
+ REQUIRE(S_ISDIR(st.st_mode));
+ REQUIRE(S_ISBLK(st.st_mode) == 0);
+ REQUIRE(S_ISLNK(st.st_mode) == 0);
+ REQUIRE(S_ISSOCK(st.st_mode) == 0);
+ REQUIRE(S_ISREG(st.st_mode) == 0);
+
+ // Check for file
+ REQUIRE(0 == fs_core->stat(fil, st));
+ REQUIRE(124567 == st.st_size);
+ REQUIRE(S_ISFIFO(st.st_mode) == 0);
+ REQUIRE(S_ISCHR(st.st_mode) == 0);
+ REQUIRE(S_ISDIR(st.st_mode) == 0);
+ REQUIRE(S_ISBLK(st.st_mode) == 0);
+ REQUIRE(S_ISLNK(st.st_mode) == 0);
+ REQUIRE(S_ISSOCK(st.st_mode) == 0);
+ REQUIRE(S_ISREG(st.st_mode));
+
+ // Final cleanup
+ REQUIRE(0 == fs_core->unlink(fil));
+ REQUIRE(0 == fs_core->rmdir(dir));
+
+ // Final umount
+ REQUIRE(fs_core->umount("/sys") == 0);
+}
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +0 -2
@@ 294,8 294,6 @@ auto ServiceBluetooth::handle(message::bluetooth::ConnectResult *msg) -> std::sh
{
if (msg->isSucceed()) {
auto device = msg->getDevice();
- auto deviceInModel = bluetoothDevicesModel->getDeviceByAddress(device.address)->get();
-
bluetoothDevicesModel->mergeInternalDeviceState(device);
settingsHolder->setValue(bluetooth::Settings::ConnectedDevice, bd_addr_to_str(device.address));
M module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp => module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp +5 -0
@@ 108,6 108,11 @@ namespace screen_light_control::functions
rampTarget = value;
}
+ void resetRampToTarget()
+ {
+ rampState = rampTarget;
+ }
+
bool isRampTargetReached()
{
return rampTargetReached;
M module-services/service-evtmgr/screen-light-control/ControlFunctions.hpp => module-services/service-evtmgr/screen-light-control/ControlFunctions.hpp +2 -0
@@ 29,6 29,8 @@ namespace screen_light_control::functions
void setRampStep(float step);
+ void resetRampToTarget();
+
void setHysteresis(float hyst);
void setFunctionFromPoints(const BrightnessFunction &points);
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp +1 -0
@@ 31,5 31,6 @@ namespace screen_light_control
[[nodiscard]] virtual auto isAutoModeOn() const noexcept -> bool = 0;
[[nodiscard]] virtual auto getBrightnessValue() const noexcept
-> bsp::eink_frontlight::BrightnessPercentage = 0;
+ [[nodiscard]] virtual auto isFadeOutOngoing() -> bool = 0;
};
} // namespace screen_light_control
M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp +9 -8
@@ 18,12 18,13 @@ namespace screen_light_control
/// Set of actions to control the screen light
enum class Action
{
- turnOff, ///< Turn off screen frontlight
- turnOn, ///< Turn on screen frontlight
- enableAutomaticMode, ///< Enable automatic mode of screen frontlight
- disableAutomaticMode, ///< Disable automatic mode of screen frontlight
- setManualModeBrightness, ///< Set screen brightness in manual mode control
- setAutomaticModeParameters ///< Set parameters for automatic mode of screen frontlight
+ turnOff, ///< Turn off screen frontlight
+ turnOn, ///< Turn on screen frontlight
+ enableAutomaticMode, ///< Enable automatic mode of screen frontlight
+ disableAutomaticMode, ///< Disable automatic mode of screen frontlight
+ setManualModeBrightness, ///< Set screen brightness in manual mode control
+ setAutomaticModeParameters, ///< Set parameters for automatic mode of screen frontlight
+ fadeOut ///< Set light fade out in automatic mode
};
struct ManualModeParameters
@@ 37,8 38,8 @@ namespace screen_light_control
{
/// Vector of points for screen brightness [%] in relation to ambient light [Lux] function. Points have to be in
/// ascending order of ambient light values.
- functions::BrightnessFunction functionPoints =
- functions::BrightnessFunction({{0.0f, 70.0f}, {250.0f, 70.0f}, {450.0f, 40.0f}, {500.0f, 0.0f}});
+ functions::BrightnessFunction functionPoints = functions::BrightnessFunction(
+ {{0.0f, 35.0f}, {10.0f, 75.0f}, {85.0f, 100.0f}, {500.0f, 100.0f}, {520.0f, 0.0f}});
/// Ramp time of screen brightness in milliseconds per 0-100% change
unsigned int rampTimeMS = 1500;
/// Hysteresis value of screen brightness control
M module-services/service-time/AlarmOperations.cpp => module-services/service-time/AlarmOperations.cpp +15 -3
@@ 136,6 136,9 @@ namespace alarms
}
switchAlarmExecution(*(*found), false);
ongoingSingleEvents.erase(found);
+
+ processOngoingEvents();
+
handleActiveAlarmsCountChange();
callback(true);
}
@@ 193,6 196,8 @@ namespace alarms
switchAlarmExecution(*(*found), false);
ongoingSingleEvents.erase(found);
+ processOngoingEvents();
+
handleSnoozedAlarmsCountChange();
handleActiveAlarmsCountChange();
@@ 280,13 285,20 @@ namespace alarms
processSnoozedEventsQueue(now);
}
- if (!isHandlingInProgress && !ongoingSingleEvents.empty()) {
+ if (!isHandlingInProgress) {
+ processOngoingEvents();
+ return true;
+ }
+ return false;
+ }
+
+ void AlarmOperationsCommon::processOngoingEvents()
+ {
+ if (!ongoingSingleEvents.empty()) {
switchAlarmExecution(*(ongoingSingleEvents.front()), true);
handleActiveAlarmsCountChange();
handleSnoozedAlarmsCountChange();
- return true;
}
- return false;
}
void AlarmOperationsCommon::addAlarmExecutionHandler(const alarms::AlarmType type,
M module-services/service-time/AlarmOperations.hpp => module-services/service-time/AlarmOperations.hpp +1 -0
@@ 141,6 141,7 @@ namespace alarms
void checkAndUpdateCache(AlarmEventRecord record);
void switchAlarmExecution(const SingleEventRecord &singleAlarmEvent, bool newStateOn);
bool processEvents(TimePoint now);
+ void processOngoingEvents();
void processNextEventsQueue(const TimePoint now);
void processSnoozedEventsQueue(const TimePoint now);
virtual void onAlarmTurnedOff(const std::shared_ptr<AlarmEventRecord> &event, alarms::AlarmType alarmType);
M module-services/service-time/tests/tests-AlarmOperations.cpp => module-services/service-time/tests/tests-AlarmOperations.cpp +40 -0
@@ 608,3 608,43 @@ TEST_F(AlarmOperationsFixture, recurrentAlarmEnablingDisabling)
alarmOperations->updateAlarm(alarmRecord, universalBoolCallback);
EXPECT_FALSE(alarmActive);
}
+
+TEST_F(AlarmOperationsFixture, handleMultipleConcurrentAlarms)
+{
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+ const auto alarmTime = TimePointFromStringWithShift("2022-11-11 11:00:00");
+ const auto alarmTimeSnooze = TimePointFromStringWithShift("2022-11-11 11:10:00");
+ alarmRepoMock->nextRecords.push_back(
+ AlarmEventRecord(1, AlarmTime{11h, 0min}, defMusic, defEnabled, defSnooze, defRRule));
+ alarmRepoMock->nextRecords.push_back(
+ AlarmEventRecord(2, AlarmTime{11h, 0min}, defMusic, defEnabled, defSnooze, defRRule));
+ alarmRepoMock->nextRecords.push_back(
+ AlarmEventRecord(3, AlarmTime{11h, 0min}, defMusic, defEnabled, defSnooze, defRRule));
+
+ auto alarmOperations = getMockedAlarmOperations(alarmRepoMock);
+ auto handler = std::make_shared<MockAlarmHandler>();
+ EXPECT_CALL(*handler, handle(testing::_)).Times(6);
+ alarmOperations->addAlarmExecutionHandler(alarms::AlarmType::Clock, handler);
+
+ int snoozedCount = 0;
+ auto countcallback = [&](unsigned count) { snoozedCount = count; };
+ alarmOperations->addSnoozedAlarmsCountChangeCallback(countcallback);
+ bool alarmActive = false;
+ auto activeCallback = [&](bool isAnyActive) { alarmActive = isAnyActive; };
+ alarmOperations->addActiveAlarmCountChangeCallback(activeCallback);
+
+ alarmOperations->updateEventsCache(TimePointFromStringWithShift("2022-11-11 08:59:00"));
+
+ alarmOperations->minuteUpdated(alarmTime);
+ alarmOperations->snoozeRingingAlarm(1, alarmTimeSnooze, universalBoolCallback);
+ alarmOperations->snoozeRingingAlarm(2, alarmTimeSnooze, universalBoolCallback);
+ alarmOperations->snoozeRingingAlarm(3, alarmTimeSnooze, universalBoolCallback);
+ EXPECT_EQ(snoozedCount, 3);
+ EXPECT_TRUE(alarmActive);
+
+ alarmOperations->minuteUpdated(alarmTimeSnooze);
+ EXPECT_EQ(snoozedCount, 0);
+ alarmOperations->turnOffRingingAlarm(1, universalBoolCallback);
+ alarmOperations->turnOffRingingAlarm(2, universalBoolCallback);
+ alarmOperations->turnOffRingingAlarm(3, universalBoolCallback);
+}
M module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp => module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp +49 -7
@@ 127,18 127,48 @@ namespace purefs::fs::drivers
st.st_rdev = 0;
st.st_size = fs.fsize;
- // TODO: Block FF_MIN_SS != FF_MAX_SS
#if FF_MAX_SS != FF_MIN_SS
st.st_blksize = fatfs->ssize;
#else
st.st_blksize = FF_MIN_SS;
#endif
- // TODO: Time is currently not supported
st.st_blocks = fs.fsize / st.st_blksize;
st.st_atime = 0;
st.st_mtime = 0;
st.st_ctime = 0;
}
+
+ int internal_stat_rootdir(const char *translated_path, bool ro, struct stat *entry)
+ {
+ FATFS *fs;
+ DWORD bfree;
+ FRESULT res = f_getfree(translated_path, &bfree, &fs);
+ if (res != FR_OK) {
+ return -EIO;
+ }
+ entry->st_dev = 0;
+ entry->st_ino = 0;
+ entry->st_mode = (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IRUSR | S_IRGRP | S_IROTH);
+ if (!ro) {
+ entry->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ }
+ entry->st_nlink = 1;
+ entry->st_uid = 0;
+ entry->st_gid = 0;
+ entry->st_rdev = 0;
+ entry->st_size = 0;
+#if FF_MAX_SS != FF_MIN_SS
+ entry->st_blksize = fatfs->ssize;
+#else
+ entry->st_blksize = FF_MIN_SS;
+#endif
+ entry->st_blocks = fs->fsize / entry->st_blksize;
+ entry->st_atime = 0;
+ entry->st_mtime = 0;
+ entry->st_ctime = 0;
+ return 0;
+ }
+
} // namespace
auto filesystem_vfat::mount_prealloc(std::shared_ptr<blkdev::internal::disk_handle> diskh,
@@ 360,11 390,19 @@ namespace purefs::fs::drivers
}
FILINFO finfo;
const auto fspath = vmnt->native_path(file);
- const int fres = f_stat(fspath.c_str(), &finfo);
- if (fres == FR_OK) {
- translate_filinfo_to_stat(finfo, nullptr, vmnt->is_ro(), st);
+ static constexpr auto slash_pos = 2U;
+ static constexpr auto root_size = 3U;
+ static constexpr auto empty_root_size = 2U;
+ if ((fspath[slash_pos] == '/' && fspath.size() == root_size) || fspath.size() == empty_root_size) {
+ return internal_stat_rootdir(fspath.c_str(), vmnt->is_ro(), &st);
+ }
+ else {
+ const int fres = f_stat(fspath.c_str(), &finfo);
+ if (fres == FR_OK) {
+ translate_filinfo_to_stat(finfo, nullptr, vmnt->is_ro(), st);
+ }
+ return translate_error(fres);
}
- return translate_error(fres);
}
auto filesystem_vfat::unlink(fsmount mnt, std::string_view name) noexcept -> int
@@ 486,7 524,11 @@ namespace purefs::fs::drivers
LOG_ERROR("Non fat filesystem pointer");
return -EBADF;
}
- const int fres = f_truncate(vfile->ff_filp());
+ int fres = f_lseek(vfile->ff_filp(), len);
+ if (fres != FR_OK) {
+ return translate_error(fres);
+ }
+ fres = f_truncate(vfile->ff_filp());
return translate_error(fres);
}
M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp => products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp +6 -0
@@ 196,4 196,10 @@ namespace bell::screen_light_control
{
return std::max<bsp::eink_frontlight::BrightnessPercentage>(target, MINIMAL_TARGET);
}
+
+ bool ScreenLightController::isFadeOutOngoing()
+ {
+ return false;
+ }
+
} // namespace bell::screen_light_control
M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.hpp => products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.hpp +1 -0
@@ 42,6 42,7 @@ namespace bell::screen_light_control
[[nodiscard]] auto isLightOn() const noexcept -> bool override;
[[nodiscard]] bool isAutoModeOn() const noexcept override;
[[nodiscard]] auto getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage override;
+ [[nodiscard]] auto isFadeOutOngoing() -> bool override;
private:
void controlTimerCallback();
M products/PurePhone/services/desktop/endpoints/contacts/ContactHelper.cpp => products/PurePhone/services/desktop/endpoints/contacts/ContactHelper.cpp +1 -8
@@ 156,14 156,7 @@ namespace sdesktop::endpoints
auto ContactHelper::createDBEntry(Context &context) -> sys::ReturnCodes
{
auto newRecord = from_json(context.getBody());
- if (newRecord.numbers.empty()) {
- LOG_ERROR("Empty number, not added!");
- context.setResponseStatus(http::Code::NotAcceptable);
- putToSendQueue(context.createSimpleResponse());
- return sys::ReturnCodes::Failure;
- }
-
- auto query = std::make_unique<db::query::ContactAdd>(newRecord);
+ auto query = std::make_unique<db::query::ContactAdd>(newRecord);
auto listener = std::make_unique<db::EndpointListener>(
[](db::QueryResult *result, Context context) {
M products/PurePhone/services/evtmgr/EventManager.cpp => products/PurePhone/services/evtmgr/EventManager.cpp +3 -1
@@ 92,6 92,8 @@ void EventManager::initProductEvents()
connect(sevm::ToggleTorchColorMessage(), [&]([[maybe_unused]] sys::Message *msg) {
toggleTorchColor();
+ // Handle only torch short press. Done here as workaround since only app can recognize press length.
+ backlightHandler.handleKeyPressed();
return sys::MessageNone{};
});
@@ 166,7 168,7 @@ void EventManager::handleKeyEvent(sys::Message *msg)
auto kbdMessage = dynamic_cast<sevm::KbdMessage *>(msg);
if (kbdMessage->key.state == RawKey::State::Pressed) {
- backlightHandler.handleKeyPressed();
+ backlightHandler.handleKeyPressed(kbdMessage->key.keyCode);
}
else if (kbdMessage->key.state == RawKey::State::Moved) {
handleKeyMoveEvent(kbdMessage->key);
M products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.cpp => products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.cpp +50 -16
@@ 14,21 14,32 @@ namespace backlight
namespace timers
{
constexpr auto keypadLightTimerName = "KeypadLightTimer";
- constexpr auto keypadLightTimerTimeout = std::chrono::seconds(5);
+ constexpr auto lightTimerTimeout = std::chrono::seconds(20);
+ constexpr auto lightFadeoutTimerTimeout = std::chrono::seconds(10);
} // namespace timers
+ namespace
+ {
+ constexpr std::array exclusions = {bsp::KeyCodes::Torch};
+
+ [[nodiscard]] bool isKeyOnExclusionList(bsp::KeyCodes key)
+ {
+ for (const auto &exclusion : exclusions) {
+ if (key == exclusion) {
+ return true;
+ }
+ }
+ return false;
+ }
+ } // namespace
+
Handler::Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
: HandlerCommon(std::move(settings),
std::make_shared<pure::screen_light_control::ScreenLightController>(parent),
parent,
- [this](sys::Timer &t) {
- if (getScreenAutoModeState() == screen_light_control::ScreenLightMode::Automatic &&
- this->screenLightController->isLightOn()) {
- this->screenLightController->processRequest(screen_light_control::Action::turnOff);
- }
- }),
+ [this](sys::Timer &t) { handleScreenLightTimeout(); }),
keypadLightTimer{sys::TimerFactory::createSingleShotTimer(
- parent, timers::keypadLightTimerName, timers::keypadLightTimerTimeout, [this](sys::Timer &) {
+ parent, timers::keypadLightTimerName, timers::lightTimerTimeout, [this](sys::Timer &) {
bsp::keypad_backlight::shutdown();
})}
{}
@@ 57,17 68,19 @@ namespace backlight
});
}
- void Handler::handleKeyPressed([[maybe_unused]] int key)
+ void Handler::handleKeyPressed(bsp::KeyCodes key)
{
- handleKeypadLightRefresh();
- handleScreenLightRefresh();
+ if (!isKeyOnExclusionList(key)) {
+ handleKeypadLightRefresh();
+ handleScreenLightRefresh();
+ }
}
void Handler::processScreenRequest(screen_light_control::Action action,
const screen_light_control::Parameters ¶ms)
{
if (action == screen_light_control::Action::enableAutomaticMode) {
- startScreenLightTimer();
+ getScreenLightTimer()->restart(timers::lightTimerTimeout);
}
handleScreenLightSettings(action, params);
getScreenLightControl()->processRequest(action, params);
@@ 157,16 170,37 @@ namespace backlight
void Handler::handleScreenLightRefresh([[maybe_unused]] const int key)
{
- if (getScreenLightState() && getScreenAutoModeState() == screen_light_control::ScreenLightMode::Automatic) {
- if (!getScreenLightControl()->isLightOn()) {
+ if (getScreenLightState()) {
+ if (!getScreenLightControl()->isLightOn() || getScreenLightControl()->isFadeOutOngoing()) {
getScreenLightControl()->processRequest(screen_light_control::Action::turnOn);
}
- startScreenLightTimer();
+ getScreenLightTimer()->restart(timers::lightTimerTimeout);
+ }
+ }
+
+ void Handler::handleScreenLightTimeout()
+ {
+ if (getScreenAutoModeState() == screen_light_control::ScreenLightMode::Automatic) {
+ if (screenLightController->isLightOn()) {
+ if (screenLightController->isFadeOutOngoing()) {
+ screenLightController->processRequest(screen_light_control::Action::turnOff);
+ }
+ else {
+ screenLightController->processRequest(screen_light_control::Action::fadeOut);
+ getScreenLightTimer()->restart(timers::lightFadeoutTimerTimeout);
+ }
+ }
+ }
+ else if (getScreenAutoModeState() == screen_light_control::ScreenLightMode::Manual) {
+ if (screenLightController->isLightOn()) {
+ screenLightController->processRequest(screen_light_control::Action::turnOff);
+ }
}
}
void Handler::onScreenLightTurnedOn()
{
- startScreenLightTimer();
+ getScreenLightTimer()->restart(timers::lightTimerTimeout);
}
+
} // namespace backlight
M products/PurePhone/services/evtmgr/include/evtmgr/BacklightHandler.hpp => products/PurePhone/services/evtmgr/include/evtmgr/BacklightHandler.hpp +3 -1
@@ 8,6 8,7 @@
#include <Timers/TimerHandle.hpp>
#include <Service/ServiceProxy.hpp>
#include <backlight-handler/BacklightHandlerCommon.hpp>
+#include <hal/key_input/KeyEventDefinitions.hpp>
namespace settings
{
@@ 23,7 24,7 @@ namespace backlight
Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent);
void init() override;
- void handleKeyPressed(int key = 0);
+ void handleKeyPressed(bsp::KeyCodes key = bsp::KeyCodes::Undefined);
/// Process request of the keypad light control
/// @keypad_backlight::action an action to perform
/// @return True if request was processed successfully, false otherwise
@@ 48,5 49,6 @@ namespace backlight
void handleKeypadLightRefresh();
void handleScreenLightRefresh(int key = 0);
void onScreenLightTurnedOn() override;
+ void handleScreenLightTimeout();
};
} // namespace backlight
M products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.cpp => products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.cpp +40 -1
@@ 8,6 8,10 @@
namespace pure::screen_light_control
{
+ namespace
+ {
+ constexpr bsp::eink_frontlight::BrightnessPercentage fadeOutBrigthnessMax = 35.0f;
+ }
ScreenLightController::ScreenLightController(sys::Service *parent)
{
@@ 58,6 62,9 @@ namespace pure::screen_light_control
setParameters(params.getAutoModeParams());
}
break;
+ case Action::fadeOut:
+ handleFadeOut();
+ break;
}
}
@@ 68,7 75,9 @@ namespace pure::screen_light_control
void ScreenLightController::readoutTimerCallback()
{
- ::screen_light_control::functions::calculateBrightness(bsp::light_sensor::readout());
+ if (!fadeOut) {
+ ::screen_light_control::functions::calculateBrightness(bsp::light_sensor::readout());
+ }
}
auto ScreenLightController::isLightOn() const noexcept -> bool
@@ 137,9 146,21 @@ namespace pure::screen_light_control
void ScreenLightController::turnOn()
{
+ fadeOut = false;
+
bsp::eink_frontlight::turnOn();
bsp::light_sensor::wakeup();
+
if (automaticMode == ScreenLightMode::Automatic) {
+ if (lightOn) {
+ ::screen_light_control::functions::calculateBrightness(bsp::light_sensor::readout());
+ }
+ else {
+ // It takes some time to get initial readout -> using last saved measurement
+ ::screen_light_control::functions::calculateBrightness(stashedReadout);
+ }
+ ::screen_light_control::functions::resetRampToTarget();
+ bsp::eink_frontlight::setBrightness(::screen_light_control::functions::getRampState());
enableTimers();
}
lightOn = true;
@@ 153,9 174,27 @@ namespace pure::screen_light_control
void ScreenLightController::turnOff()
{
bsp::eink_frontlight::turnOff();
+ stashedReadout = bsp::light_sensor::readout();
bsp::light_sensor::standby();
disableTimers();
lightOn = false;
+ fadeOut = false;
+ }
+
+ void ScreenLightController::handleFadeOut()
+ {
+ if (automaticMode == ScreenLightMode::Automatic) {
+ fadeOut = true;
+ // Set fadeout brightess as maximum or current ramp state if lower
+ auto rampState = ::screen_light_control::functions::getRampState();
+ auto fadeOutBrigthness = std::clamp(rampState, 0.0f, fadeOutBrigthnessMax);
+ ::screen_light_control::functions::setRampTarget(fadeOutBrigthness);
+ }
+ }
+
+ bool ScreenLightController::isFadeOutOngoing()
+ {
+ return fadeOut;
}
} // namespace screen_light_control
M products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.hpp => products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.hpp +7 -1
@@ 40,6 40,8 @@ namespace pure::screen_light_control
[[nodiscard]] bool isAutoModeOn() const noexcept override;
[[nodiscard]] auto getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage override;
+ [[nodiscard]] auto isFadeOutOngoing() -> bool override;
+
private:
void controlTimerCallback();
void readoutTimerCallback();
@@ 57,6 59,8 @@ namespace pure::screen_light_control
void enableAutomaticMode();
void disableAutomaticMode();
+ void handleFadeOut();
+
static constexpr inline auto CONTROL_TIMER_MS = 25;
static constexpr inline auto READOUT_TIMER_MS = 500;
@@ 65,6 69,8 @@ namespace pure::screen_light_control
bool lightOn = false;
ScreenLightMode automaticMode = ScreenLightMode::Manual;
- bsp::eink_frontlight::BrightnessPercentage brightnessValue = 0.0;
+ bsp::eink_frontlight::BrightnessPercentage brightnessValue = 0.0f;
+ bool fadeOut = false;
+ bsp::light_sensor::IlluminanceLux stashedReadout = 0.0f;
};
} // namespace pure::screen_light_control